import Foundation
import SwiftData

// Interface updated 2026-05-17 — see AGENTS.md
@Model final class HealthSnapshot {
    var id: UUID = UUID()
    var timestamp: Date = Date.now
    var osVersion: String = ""
    var deviceName: String = ""
    var deviceID: String = ""
    var localSequenceNumber: Int = 0
    var previousSnapshotID: UUID?
    var contentEquivalentSnapshotID: UUID?
    var isChainStart: Bool = false
    var recoveredDeviceID: Bool = false
    var snapshotQualityRaw: String = SnapshotQuality.complete.rawValue
    var anomalyFlagsJSON: String = "[]"
    var triggerReason: String = "manual"
    var retryOfSnapshotID: UUID?
    var isPostRestore: Bool = false
    var isPostRestoreInferred: Bool = false
    var isPostRestoreSuppressedDeltaID: UUID?
    var hardwareModel: String = ""
    var appBuildVersion: String = ""
    var monitoredTypeSetHash: String = ""
    var monitoredRegistryVersion: Int = 0
    var yearlyCountTimezoneIdentifier: String = ""
    var cachedSummaryVersion: Int = 0
    var cachedTypeCount: Int = 0
    var cachedRecordCount: Int = 0
    var cachedEarliestRecordDate: Date?
    var cachedLatestRecordDate: Date?
    @Relationship(deleteRule: .cascade, inverse: \TypeCount.snapshot)
    var typeCounts: [TypeCount]? = []

    init(timestamp: Date, osVersion: String, deviceName: String, deviceID: String) {
        self.id = UUID()
        self.timestamp = timestamp
        self.osVersion = osVersion
        self.deviceName = deviceName
        self.deviceID = deviceID
        self.typeCounts = []
    }
}

extension HealthSnapshot {
    static let currentCachedSummaryVersion = 1

    static func timelineSort(_ lhs: HealthSnapshot, _ rhs: HealthSnapshot) -> Bool {
        if lhs.timestamp != rhs.timestamp {
            return lhs.timestamp < rhs.timestamp
        }
        if lhs.localSequenceNumber != rhs.localSequenceNumber {
            return lhs.localSequenceNumber < rhs.localSequenceNumber
        }
        return lhs.id.uuidString < rhs.id.uuidString
    }

    func previousInTimeline(_ snapshots: [HealthSnapshot]) -> HealthSnapshot? {
        if let previousSnapshotID,
           let previous = snapshots.first(where: { $0.id == previousSnapshotID }) {
            return previous
        }

        let orderedSnapshots = snapshots.sorted(by: Self.timelineSort)
        guard let index = orderedSnapshots.firstIndex(where: { $0.id == id }),
              index > 0 else {
            return nil
        }
        return orderedSnapshots[index - 1]
    }

    func nextInTimeline(_ snapshots: [HealthSnapshot]) -> HealthSnapshot? {
        let orderedSnapshots = snapshots.sorted(by: Self.timelineSort)
        guard let index = orderedSnapshots.firstIndex(where: { $0.id == id }),
              index < orderedSnapshots.count - 1 else {
            return nil
        }
        return orderedSnapshots[index + 1]
    }

    var snapshotQuality: SnapshotQuality {
        get { SnapshotQuality(rawValue: snapshotQualityRaw) ?? .complete }
        set { snapshotQualityRaw = newValue.rawValue }
    }

    var anomalyFlags: [String] {
        get { (try? JSONDecoder().decode([String].self, from: Data(anomalyFlagsJSON.utf8))) ?? [] }
        set { anomalyFlagsJSON = (try? String(data: JSONEncoder().encode(newValue), encoding: .utf8)) ?? "[]" }
    }

    var isContentAlias: Bool {
        contentEquivalentSnapshotID != nil
    }

    var contentRepresentativeSnapshotID: UUID {
        contentEquivalentSnapshotID ?? id
    }

    var hasCurrentCachedSummary: Bool {
        cachedSummaryVersion >= Self.currentCachedSummaryVersion
    }
}
