import Foundation

@Observable
final class TodayViewModel {
    private let repo = FitnessRepository.shared

    var selectedDate = Date()
    var entries: [FoodEntry] = []
    var goal: DailyGoal?
    var isLoading = false
    var error: String?

    var dateString: String {
        selectedDate.apiDateString
    }

    var isToday: Bool {
        Calendar.current.isDateInToday(selectedDate)
    }

    var displayDateString: String {
        if isToday { return "Today" }
        if Calendar.current.isDateInYesterday(selectedDate) { return "Yesterday" }
        if Calendar.current.isDateInTomorrow(selectedDate) { return "Tomorrow" }
        return selectedDate.displayString
    }

    // MARK: - Grouped entries

    var mealGroups: [(MealType, [FoodEntry])] {
        let grouped = Dictionary(grouping: entries) { entry in
            MealType(rawValue: entry.mealType) ?? .snack
        }
        return MealType.allCases.compactMap { meal in
            guard let items = grouped[meal], !items.isEmpty else { return nil }
            return (meal, items)
        }
    }

    // MARK: - Totals

    var totalCalories: Double {
        entries.reduce(0) { $0 + $1.calories }
    }

    var totalProtein: Double {
        entries.reduce(0) { $0 + $1.protein }
    }

    var totalCarbs: Double {
        entries.reduce(0) { $0 + $1.carbs }
    }

    var totalFat: Double {
        entries.reduce(0) { $0 + $1.fat }
    }

    var totalSugar: Double {
        entries.reduce(0) { $0 + $1.sugar }
    }

    var totalFiber: Double {
        entries.reduce(0) { $0 + $1.fiber }
    }

    var calorieGoal: Double {
        goal?.calories ?? 2000
    }

    var proteinGoal: Double {
        goal?.protein ?? 150
    }

    var carbsGoal: Double {
        goal?.carbs ?? 200
    }

    var fatGoal: Double {
        goal?.fat ?? 65
    }

    var sugarGoal: Double {
        goal?.sugar ?? 50
    }

    var fiberGoal: Double {
        goal?.fiber ?? 30
    }

    // MARK: - Actions

    func load() async {
        isLoading = true
        error = nil
        async let entriesTask: () = loadEntries()
        async let goalTask: () = loadGoal()
        _ = await (entriesTask, goalTask)
        isLoading = false
    }

    func loadEntries() async {
        await repo.loadEntries(date: dateString)
        entries = repo.entries
    }

    func loadGoal() async {
        await repo.loadGoal(date: dateString)
        goal = repo.goal
    }

    func deleteEntry(_ entry: FoodEntry) async {
        do {
            try await repo.deleteEntry(id: entry.id, date: dateString)
            entries = repo.entries
        } catch {
            self.error = error.localizedDescription
        }
    }

    func goToPreviousDay() {
        selectedDate = Calendar.current.date(byAdding: .day, value: -1, to: selectedDate) ?? selectedDate
    }

    func goToNextDay() {
        selectedDate = Calendar.current.date(byAdding: .day, value: 1, to: selectedDate) ?? selectedDate
    }

    func goToToday() {
        selectedDate = Date()
    }
}
