import SwiftUI
import SwiftData

struct RecordChangeEvolutionChart: View {
    let snapshots: [HealthSnapshot]
    let currentSnapshotID: UUID
    let typeIdentifier: String
    let displayName: String

    @Query private var allDeltas: [SnapshotDelta]

    private var sortedSnapshots: [HealthSnapshot] {
        snapshots.sorted(by: HealthSnapshot.timelineSort)
    }

    private var currentIndex: Int? {
        sortedSnapshots.firstIndex { $0.id == currentSnapshotID }
    }

    private var contextSnapshots: [HealthSnapshot] {
        guard let idx = currentIndex else { return [] }
        let start = max(0, idx - 3)
        let end = min(sortedSnapshots.count, idx + 4)
        return Array(sortedSnapshots[start..<end])
    }

    private var diffTaskID: String {
        ([typeIdentifier, currentSnapshotID.uuidString] + contextSnapshots.map { $0.id.uuidString }).joined(separator: "|")
    }

    private var maxCount: Int {
        let counts = contextSnapshots.compactMap { snapshot in
            snapshot.typeCounts?.first { $0.typeIdentifier == typeIdentifier }?.count
        }
        return counts.max() ?? 1
    }

    private var maxNegativeCount: Int {
        var max = 0
        for snapshot in contextSnapshots {
            let previousSnapshot = snapshot.previousInTimeline(sortedSnapshots)
            let diff = recordDiff(current: snapshot, previous: previousSnapshot)
            max = Swift.max(max, diff.disappeared)
        }
        return max
    }

    private func recordDiff(current: HealthSnapshot, previous: HealthSnapshot?) -> (added: Int, disappeared: Int) {
        guard let previous = previous else { return (0, 0) }

        guard let delta = allDeltas.first(where: {
            $0.fromSnapshotID == previous.id &&
            $0.toSnapshotID == current.id
        }),
        let typeDelta = delta.typeDeltas?.first(where: { $0.typeIdentifier == typeIdentifier }) else {
            return (0, 0)
        }

        switch typeDelta.transition {
        case .unchanged:
            return (0, 0)
        case .changed:
            if typeDelta.countDelta > 0 {
                return (typeDelta.countDelta, 0)
            }
            if typeDelta.countDelta < 0 {
                return (0, abs(typeDelta.countDelta))
            }
            return (0, 0)
        case .appeared:
            return (max(typeDelta.countDelta, 1), 0)
        case .disappeared:
            return (0, max(abs(typeDelta.countDelta), 1))
        }
    }

    var body: some View {
        if contextSnapshots.count < 2 {
            emptyState
        } else {
            evolutionView
        }
    }

    private var emptyState: some View {
        VStack(spacing: 8) {
            Image(systemName: "chart.line.uptrend.xyaxis")
                .font(.system(size: 24, weight: .semibold))
                .foregroundStyle(.secondary)

            Text("Not enough snapshots")
                .font(.caption)
                .foregroundStyle(.secondary)
        }
        .frame(maxWidth: .infinity)
        .padding(24)
        .background(Color(.systemBackground).opacity(0.5), in: RoundedRectangle(cornerRadius: 8))
    }

    private var evolutionView: some View {
        VStack(alignment: .leading, spacing: 12) {
            HStack {
                Text("Evolution")
                    .font(.headline.weight(.semibold))
                    .foregroundStyle(.primary)

                Spacer()

                Text("\(contextSnapshots.count) snapshots")
                    .font(.caption)
                    .foregroundStyle(.secondary)
            }

            evolutionChart

            HStack(spacing: 12) {
                VStack(alignment: .leading, spacing: 4) {
                    Text("Min")
                        .font(.caption)
                        .foregroundStyle(.secondary)
                    Text("\(contextSnapshots.compactMap { $0.typeCounts?.first { $0.typeIdentifier == typeIdentifier }?.count }.min() ?? 0)")
                        .font(.caption.weight(.semibold))
                        .monospacedDigit()
                }

                Spacer()

                VStack(alignment: .center, spacing: 4) {
                    Text("Current")
                        .font(.caption)
                        .foregroundStyle(.secondary)
                    if let current = contextSnapshots.first(where: { $0.id == currentSnapshotID }),
                       let count = current.typeCounts?.first(where: { $0.typeIdentifier == typeIdentifier })?.count {
                        Text("\(count)")
                            .font(.caption.weight(.semibold))
                            .monospacedDigit()
                            .foregroundStyle(Color.accentColor)
                    }
                }

                Spacer()

                VStack(alignment: .trailing, spacing: 4) {
                    Text("Max")
                        .font(.caption)
                        .foregroundStyle(.secondary)
                    Text("\(maxCount)")
                        .font(.caption.weight(.semibold))
                        .monospacedDigit()
                }
            }
            .padding(8)
            .background(Color(.systemBackground).opacity(0.3), in: RoundedRectangle(cornerRadius: 6))
        }
        .padding(12)
        .background(Color(.systemBackground).opacity(0.5), in: RoundedRectangle(cornerRadius: 8))
    }

    @ViewBuilder
    private var evolutionChart: some View {
        HStack(alignment: .bottom, spacing: 4) {
            ForEach(Array(contextSnapshots.enumerated()), id: \.element.id) { idx, snapshot in
                chartBar(at: idx, snapshot: snapshot)
            }
        }
        .frame(height: 100)
        .padding(12)
        .background(Color(.systemBackground).opacity(0.3), in: RoundedRectangle(cornerRadius: 8))
    }

    @ViewBuilder
    private func chartBar(at index: Int, snapshot: HealthSnapshot) -> some View {
        let typeCount = snapshot.typeCounts?.first { $0.typeIdentifier == typeIdentifier }
        let count = typeCount?.count ?? 0
        let isCurrent = snapshot.id == currentSnapshotID
        let previousSnapshot = snapshot.previousInTimeline(sortedSnapshots)
        let diff = recordDiff(current: snapshot, previous: previousSnapshot)
        let unchanged = count - diff.added

        let barTotalRange = CGFloat(diff.disappeared + count)
        let redHeight = barTotalRange > 0 ? CGFloat(diff.disappeared) / barTotalRange * 80 : 0
        let blueHeight = barTotalRange > 0 ? CGFloat(unchanged) / barTotalRange * 80 : 0
        let greenHeight = barTotalRange > 0 ? CGFloat(diff.added) / barTotalRange * 80 : 0

        let minVisibleHeight: CGFloat = 3

        VStack(spacing: 0) {
            if isCurrent {
                Image(systemName: "star.fill")
                    .font(.system(size: 12, weight: .semibold))
                    .foregroundStyle(Color.accentColor)
                    .padding(.bottom, 4)
            }

            VStack(spacing: 0) {
                if diff.added > 0 {
                    RoundedRectangle(cornerRadius: 1)
                        .fill(Color.healthyGreen)
                        .frame(height: max(minVisibleHeight, greenHeight))
                }

                if unchanged > 0 {
                    RoundedRectangle(cornerRadius: 1)
                        .fill(Color.neutralGray.opacity(0.6))
                        .frame(height: max(1, blueHeight))
                }

                if diff.disappeared > 0 {
                    RoundedRectangle(cornerRadius: 1)
                        .fill(Color.criticalRed)
                        .frame(height: max(minVisibleHeight, redHeight))
                }
            }
            .frame(height: 80)
            .frame(maxWidth: .infinity)

            Text(snapshot.timestamp.formatted(.dateTime.month().day()))
                .font(.caption2)
                .foregroundStyle(.secondary)
                .lineLimit(1)
                .padding(.top, 4)
        }
        .frame(maxWidth: .infinity)
    }

}

#Preview {
    let mockSnapshots = (0..<7).map { idx in
        let snapshot = HealthSnapshot(
            timestamp: Calendar.current.date(byAdding: .day, value: idx - 3, to: Date.now) ?? .now,
            osVersion: "iOS 26.4",
            deviceName: "Preview iPhone",
            deviceID: "preview-device"
        )

        let recordCount = Int.random(in: 5000..<15000)
        let mockRecords = (0..<recordCount).map { i in
            HealthRecordValue(
                typeIdentifier: "HKQuantityTypeIdentifierStepCount",
                sampleUUIDHash: UUID().uuidString,
                recordFingerprint: "fp-\(idx)-\(i)",
                startDate: Date.now.addingTimeInterval(-Double(i * 3600)),
                endDate: Date.now.addingTimeInterval(-Double(i * 3600) + 3600),
                displayValue: nil
            )
        }

        let typeCount = TypeCount(
            typeIdentifier: "HKQuantityTypeIdentifierStepCount",
            displayName: "Step Count",
            count: recordCount
        )
        typeCount.setRecordValues(mockRecords)
        snapshot.typeCounts = [typeCount]

        return snapshot
    }

    RecordChangeEvolutionChart(
        snapshots: mockSnapshots,
        currentSnapshotID: mockSnapshots[3].id,
        typeIdentifier: "HKQuantityTypeIdentifierStepCount",
        displayName: "Step Count"
    )
    .padding(16)
}
