import SwiftUI

struct DataTypeArchiveDetailView: View {
    let current: DataTypeSnapshotContext
    let baseline: DataTypeSnapshotContext
    let timeline: [DataTypeSnapshotContext]
    let typeIdentifier: String
    let displayName: String
    let initialDiff: TypeDiff

    @State private var currentSummary: CachedArchiveTypeSummary?
    @State private var baselineSummary: CachedArchiveTypeSummary?
    @State private var diff: TypeDiff
    @State private var loadError: String?
    @State private var showAddedRecords = false
    @State private var showDisappearedRecords = false

    private var taskID: String {
        "\(baseline.observationID)|\(current.observationID)|\(typeIdentifier)"
    }

    private var usesImmediatePreviousBaseline: Bool {
        timeline
            .filter { $0.observedAt < current.observedAt }
            .max { $0.observedAt < $1.observedAt }?
            .observationID == baseline.observationID
    }

    private var currentCount: Int {
        currentSummary?.visibleRecordCount ?? diff.currentCount
    }

    private var baselineCount: Int {
        baselineSummary?.visibleRecordCount ?? diff.previousCount
    }

    private var evolutionSnapshots: [RecordChangeEvolutionSnapshot] {
        let sorted = timeline.sorted { $0.observedAt < $1.observedAt }
        return sorted.enumerated().map { index, context in
            RecordChangeEvolutionSnapshot(
                id: context.chartID,
                timestamp: context.observedAt,
                localSequenceNumber: index,
                previousSnapshotID: index > 0 ? sorted[index - 1].chartID : nil,
                archiveObservationID: context.observationID,
                count: context.observationID == current.observationID ? currentCount : 0
            )
        }
    }

    init(
        current: DataTypeSnapshotContext,
        baseline: DataTypeSnapshotContext,
        timeline: [DataTypeSnapshotContext],
        typeIdentifier: String,
        displayName: String,
        initialDiff: TypeDiff
    ) {
        self.current = current
        self.baseline = baseline
        self.timeline = timeline
        self.typeIdentifier = typeIdentifier
        self.displayName = displayName
        self.initialDiff = initialDiff
        _diff = State(initialValue: initialDiff)
    }

    var body: some View {
        ScrollView {
            VStack(spacing: 16) {
                DataTypeRangeIndicator(
                    earliestDate: currentSummary?.earliestStartDate,
                    latestDate: currentSummary?.latestEndDate,
                    quality: .complete
                )

                RecordChangeComparisonCard(
                    displayName: displayName,
                    currentCount: currentCount,
                    previousCount: baselineSummary == nil && !diff.previousTracked ? nil : baselineCount,
                    addedCount: diff.appearedCount,
                    disappearedCount: diff.disappearedCount,
                    isCurrentValid: currentCount >= 0,
                    isPreviousTracked: baselineSummary != nil || diff.previousTracked,
                    onAddedTap: {
                        if diff.appearedCount > 0 {
                            showAddedRecords = true
                        }
                    },
                    onDisappearedTap: {
                        if diff.disappearedCount > 0 {
                            showDisappearedRecords = true
                        }
                    }
                )

                RecordChangeEvolutionChart(
                    snapshots: evolutionSnapshots,
                    currentSnapshotID: current.chartID,
                    typeIdentifier: typeIdentifier,
                    displayName: displayName
                )

                if let loadError {
                    Label(loadError, systemImage: "exclamationmark.triangle.fill")
                        .font(.caption)
                        .foregroundStyle(Color.warningAmber)
                        .frame(maxWidth: .infinity, alignment: .leading)
                }
            }
            .padding(16)
        }
        .navigationTitle(displayName)
        .navigationBarTitleDisplayMode(.inline)
        .task(id: taskID) {
            await loadArchiveDetail()
        }
        .navigationDestination(isPresented: $showAddedRecords) {
            DataTypeRecordListView(
                title: "New Records",
                displayName: displayName,
                totalCount: diff.appearedCount,
                mode: .addedDiff(
                    typeIdentifier: typeIdentifier,
                    afterDate: baseline.observedAt,
                    beforeDate: current.observedAt,
                    fromObservationID: baseline.observationID,
                    toObservationID: current.observationID
                ),
                tint: Color.healthyGreen
            )
        }
        .navigationDestination(isPresented: $showDisappearedRecords) {
            DataTypeRecordListView(
                title: "Missing Records",
                displayName: displayName,
                totalCount: diff.disappearedCount,
                mode: .disappearedDiff(
                    typeIdentifier: typeIdentifier,
                    fromObservationID: baseline.observationID,
                    toObservationID: current.observationID
                ),
                tint: Color.criticalRed
            )
        }
    }

    @MainActor
    private func loadArchiveDetail() async {
        do {
            let archiveStore = SQLiteHealthArchiveStore.shared
            currentSummary = try await archiveStore.typeSummaries(observationID: current.observationID)
                .first { $0.sampleTypeIdentifier == typeIdentifier }
            baselineSummary = try await archiveStore.typeSummaries(observationID: baseline.observationID)
                .first { $0.sampleTypeIdentifier == typeIdentifier }

            let archiveDiff: HealthArchiveDiffSummary?
            if usesImmediatePreviousBaseline {
                archiveDiff = nil
            } else {
                archiveDiff = try await archiveStore.diffSummary(HealthArchiveDiffRequest(
                    fromObservationID: baseline.observationID,
                    toObservationID: current.observationID,
                    sampleTypeIdentifier: typeIdentifier
                ))
            }
            diff = TypeDiff(
                id: typeIdentifier,
                typeIdentifier: typeIdentifier,
                displayName: currentSummary?.displayName ?? baselineSummary?.displayName ?? displayName,
                currentCount: currentSummary?.visibleRecordCount ?? 0,
                previousCount: baselineSummary?.visibleRecordCount ?? 0,
                previousTracked: baselineSummary != nil,
                appearedCount: archiveDiff?.appearedCount ?? currentSummary?.appearedCount ?? 0,
                disappearedCount: archiveDiff?.disappearedCount ?? currentSummary?.disappearedCount ?? 0,
                representationChangedCount: archiveDiff?.representationChangedCount ?? currentSummary?.representationChangedCount ?? 0
            )
            loadError = nil
        } catch {
            loadError = error.localizedDescription
        }
    }
}

private extension DataTypeSnapshotContext {
    var chartID: UUID {
        let masked = UInt64(bitPattern: observationID) & 0xffff_ffff_ffff
        let suffix = String(format: "%012llx", masked)
        return UUID(uuidString: "00000000-0000-0000-0000-\(suffix)") ?? UUID()
    }
}

#Preview {
    NavigationStack {
        DataTypeArchiveDetailView(
            current: DataTypeSnapshotContext(
                observationID: 2,
                observedAt: Date.now
            ),
            baseline: DataTypeSnapshotContext(
                observationID: 1,
                observedAt: Date.now.addingTimeInterval(-86_400)
            ),
            timeline: [
                DataTypeSnapshotContext(
                    observationID: 1,
                    observedAt: Date.now.addingTimeInterval(-86_400)
                ),
                DataTypeSnapshotContext(
                    observationID: 2,
                    observedAt: Date.now
                )
            ],
            typeIdentifier: "HKQuantityTypeIdentifierStepCount",
            displayName: "Step Count",
            initialDiff: TypeDiff(
                id: "HKQuantityTypeIdentifierStepCount",
                typeIdentifier: "HKQuantityTypeIdentifierStepCount",
                displayName: "Step Count",
                currentCount: 1200,
                previousCount: 980,
                previousTracked: true,
                appearedCount: 240,
                disappearedCount: 20,
                representationChangedCount: 0
            )
        )
    }
}
