//
//  FilterViewModel.swift
//  Reflect
//
//  Created by Trey Tartt on 1/17/22.
//

import Foundation

@MainActor
class YearViewModel: ObservableObject {
    @Published public var entryStartDate: Date = Date()
    @Published public var entryEndDate: Date = Date()
    @Published var selectedDays = [Int]()

    // year, month, items
    @Published public private(set) var data = [Int: [Int: [DayChartView]]]()
    @Published public private(set) var numberOfRatings: Int = 0
    /// Entries organized by year for efficient access
    @Published public private(set) var entriesByYear = [Int: [MoodEntryModel]]()
    public private(set) var uncategorizedData = [MoodEntryModel]() {
        didSet {
            self.numberOfRatings = uncategorizedData.count
        }
    }

    private var dataListenerToken: DataController.DataListenerToken?

    init() {
        dataListenerToken = DataController.shared.addNewDataListener { [weak self] in
            self?.refreshData()
        }
        updateData()
    }

    deinit {
        if let token = dataListenerToken {
            Task { @MainActor in
                DataController.shared.removeDataListener(token: token)
            }
        }
    }

    /// Re-fetch data using the current date range. Called by the data listener
    /// when mood entries change in other tabs.
    public func refreshData() {
        updateData()
        filterEntries(startDate: entryStartDate, endDate: entryEndDate)
    }

    private func updateData() {
        let filteredEntries = DataController.shared.getData(startDate: Date(timeIntervalSince1970: 0),
                                                            endDate: Date(),
                                                            includedDays: selectedDays)

        if let firstDate = filteredEntries.sorted(by: { $0.forDate < $1.forDate }).first?.forDate {
            self.entryStartDate = firstDate
        }
        self.entryEndDate = Date()
    }

    private let chartViewBuilder = DayChartViewChartBuilder()

    public func filterEntries(startDate: Date, endDate: Date) {
        let filteredEntries = DataController.shared.getData(startDate: startDate,
                                                            endDate: endDate,
                                                            includedDays: selectedDays)
        data.removeAll()
        entriesByYear.removeAll()
        let filledOutData = chartViewBuilder.buildGridData(withData: filteredEntries)
        data = filledOutData
        uncategorizedData = filteredEntries

        // Organize entries by year for efficient access in YearCard
        let calendar = Calendar.current
        for entry in filteredEntries {
            let year = calendar.component(.year, from: entry.forDate)
            entriesByYear[year, default: []].append(entry)
        }
    }
}
