import Foundation
import SwiftData

struct TypeProgressEntry: Identifiable {
    let id: String
    let displayName: String
    var status: Status

    enum Status {
        case pending
        case complete(Int)  // record count
        case unauthorized
        case failed(String)  // error reason
    }
}

@Observable
final class DashboardViewModel {
    var isRequestingAuth = false
    var isCreatingSnapshot = false
    var authError: String?
    var snapshotError: String?
    var fetchProgress: [TypeProgressEntry] = []
    var showProgressSheet = false
    var fetchStartTime: Date?
    var lastSnapshotQuality: SnapshotQuality? = nil

    private let healthKit = HealthKitService.shared
    private let diffService = SnapshotDiffService.shared

    func requestAuthorization() async {
        isRequestingAuth = true
        authError = nil
        defer { isRequestingAuth = false }
        do {
            try await healthKit.requestAuthorization()
        } catch {
            authError = error.localizedDescription
        }
    }

    func createSnapshot(context: ModelContext, selectedTypeIDs: Set<String>) async {
        isCreatingSnapshot = true
        snapshotError = nil
        showProgressSheet = true
        fetchStartTime = Date()

        let monitoredTypes = HealthKitService.allTypes
            .filter { selectedTypeIDs.contains($0.id) }
            .sorted { $0.displayName < $1.displayName }

        fetchProgress = monitoredTypes.map { type in
            TypeProgressEntry(id: type.id, displayName: type.displayName, status: .pending)
        }

        defer { isCreatingSnapshot = false }

        do {
            _ = try await healthKit.createSnapshot(
                in: context,
                selectedTypeIDs: selectedTypeIDs,
                onTypeCompleted: { [weak self] typeCount in
                    Task { @MainActor in
                        self?.updateProgress(for: typeCount)
                    }
                }
            )
            lastSnapshotQuality = .complete
        } catch {
            snapshotError = error.localizedDescription
            lastSnapshotQuality = .failed
        }
    }

    @MainActor
    private func updateProgress(for typeCount: TypeCount) {
        if let index = fetchProgress.firstIndex(where: { $0.id == typeCount.typeIdentifier }) {
            let status: TypeProgressEntry.Status
            switch typeCount.quality {
            case .complete:
                status = .complete(typeCount.count)
            case .unauthorized:
                status = .unauthorized
            case .failed, .partial, .loading:
                status = .failed("Failed")
            }
            fetchProgress[index].status = status
        }
    }

    func totalChanges(latest: HealthSnapshot, previous: HealthSnapshot) -> Int {
        diffService.totalAbsoluteChange(current: latest, baseline: previous)
    }
}
