import Foundation

@MainActor @Observable
final class FitnessRepository {
    static let shared = FitnessRepository()

    private let api = FitnessAPI()

    // Cached data
    var cachedFoods: [FoodItem] = []
    var cachedRecentFoods: [FoodItem] = []
    var cachedTemplates: [MealTemplate] = []
    var cachedGoals: [String: DailyGoal] = [:]
    var cachedEntries: [String: [FoodEntry]] = [:]

    private init() {}

    // MARK: - Entries

    func entries(for date: String, forceRefresh: Bool = false) async throws -> [FoodEntry] {
        if !forceRefresh, let cached = cachedEntries[date] {
            return cached
        }
        let entries = try await api.getEntries(date: date)
        cachedEntries[date] = entries
        return entries
    }

    func createEntry(_ request: CreateEntryRequest) async throws -> FoodEntry {
        let entry = try await api.createEntry(request)
        // Invalidate cache for that date
        cachedEntries[request.entryDate] = nil
        return entry
    }

    func updateEntry(id: String, request: UpdateEntryRequest, date: String) async throws -> FoodEntry {
        let entry = try await api.updateEntry(id: id, request: request)
        cachedEntries[date] = nil
        return entry
    }

    func deleteEntry(id: String, date: String) async throws {
        try await api.deleteEntry(id: id)
        cachedEntries[date] = nil
    }

    // MARK: - Foods

    func allFoods(forceRefresh: Bool = false) async throws -> [FoodItem] {
        if !forceRefresh, !cachedFoods.isEmpty {
            return cachedFoods
        }
        cachedFoods = try await api.getFoods()
        return cachedFoods
    }

    func searchFoods(query: String) async throws -> [FoodItem] {
        try await api.searchFoods(query: query)
    }

    func recentFoods(forceRefresh: Bool = false) async throws -> [FoodItem] {
        if !forceRefresh, !cachedRecentFoods.isEmpty {
            return cachedRecentFoods
        }
        cachedRecentFoods = try await api.getRecentFoods()
        return cachedRecentFoods
    }

    // MARK: - Goals

    func goals(for date: String, forceRefresh: Bool = false) async throws -> DailyGoal {
        if !forceRefresh, let cached = cachedGoals[date] {
            return cached
        }
        let goal = try await api.getGoals(date: date)
        cachedGoals[date] = goal
        return goal
    }

    // MARK: - Templates

    func templates(forceRefresh: Bool = false) async throws -> [MealTemplate] {
        if !forceRefresh, !cachedTemplates.isEmpty {
            return cachedTemplates
        }
        cachedTemplates = try await api.getTemplates()
        return cachedTemplates
    }

    func logTemplate(id: String, date: String) async throws {
        try await api.logTemplate(id: id, date: date)
        cachedEntries[date] = nil
    }

    // MARK: - Invalidation

    func invalidateAll() {
        cachedFoods = []
        cachedRecentFoods = []
        cachedTemplates = []
        cachedGoals = [:]
        cachedEntries = [:]
    }
}
