import Foundation

enum ComparisonMode: Hashable {
    case previous
    case selected
    case relativeTime(TimeInterval)

    static let relativeOptions: [(label: String, interval: TimeInterval)] = [
        ("1 Hour Ago",  3_600),
        ("1 Day Ago",  86_400),
        ("1 Week Ago", 604_800),
    ]

    var label: String {
        switch self {
        case .previous:             return "Previous"
        case .selected:             return "Selected"
        case .relativeTime(let t):
            return Self.relativeOptions.first { $0.interval == t }?.label ?? "Custom"
        }
    }
}

@Observable
final class SnapshotsViewModel {
    var comparisonMode: ComparisonMode = .previous
    var selectedBaseline: HealthSnapshot?
    var archiveRows: [CachedArchiveObservationRow]?
    var archiveRowsError: String?

    @MainActor
    func loadArchiveRows(limit: Int = 200) async {
        do {
            let cache = try CoreDataArchiveCacheStore()
            let rows = try cache.observationRows(limit: limit)
            archiveRows = rows.isEmpty ? nil : rows
            archiveRowsError = nil
        } catch {
            archiveRows = nil
            archiveRowsError = error.localizedDescription
        }
    }

    func baselines(for snapshots: [HealthSnapshot]) -> [UUID: HealthSnapshot] {
        let orderedDescending = snapshots.sorted { $0.timestamp > $1.timestamp }

        return snapshots.reduce(into: [UUID: HealthSnapshot]()) { partial, snapshot in
            partial[snapshot.id] = baseline(
                for: snapshot,
                in: snapshots,
                orderedDescending: orderedDescending
            )
        }
    }

    func baseline(for snapshot: HealthSnapshot, in snapshots: [HealthSnapshot]) -> HealthSnapshot? {
        baseline(
            for: snapshot,
            in: snapshots,
            orderedDescending: snapshots.sorted { $0.timestamp > $1.timestamp }
        )
    }

    private func baseline(
        for snapshot: HealthSnapshot,
        in snapshots: [HealthSnapshot],
        orderedDescending: [HealthSnapshot]
    ) -> HealthSnapshot? {
        switch comparisonMode {
        case .previous:
            return orderedDescending.first { $0.timestamp < snapshot.timestamp }
        case .selected:
            return selectedBaseline
        case .relativeTime(let interval):
            let target = snapshot.timestamp.addingTimeInterval(-interval)
            return SnapshotDiffService.shared.nearest(to: target, in: snapshots)
        }
    }

    func toggleBaseline(_ snapshot: HealthSnapshot) {
        if selectedBaseline?.id == snapshot.id {
            selectedBaseline = nil
        } else {
            selectedBaseline = snapshot
            comparisonMode = .selected
        }
    }
}
