import SwiftUI
import SwiftData
import HealthKit
import UIKit

struct SettingsView: View {
    @Environment(\.modelContext) private var modelContext
    @Environment(AppSettings.self) private var appSettings
    @Query private var snapshots: [HealthSnapshot]
    @Query private var deviceProfiles: [DeviceProfile]
    @Query(sort: \MetricTimeoutProfile.displayName) private var timeoutProfiles: [MetricTimeoutProfile]
    @AppStorage("checkFrequencyHours") private var checkFrequencyHours: Int = 6
    @State private var showDeleteConfirm = false
    @State private var showRepairLegacyRecordsConfirm = false
    @State private var dataMaintenanceMessage: String?

    private var currentDeviceID: String {
        AppSettings.currentDeviceID
    }

    private var currentDeviceProfile: DeviceProfile? {
        deviceProfiles.first { $0.deviceID == currentDeviceID }
    }

    var body: some View {
        NavigationStack {
            List {
                deviceSection
                monitoringSection
                timeoutCalibrationSection
                typeSelectionSections
                dataSection
                aboutSection
            }
            .navigationTitle("Settings")
            .onAppear {
                ensureCurrentDeviceProfile()
                ensureTimeoutProfiles()
            }
            .confirmationDialog(
                "Delete All Audit Data",
                isPresented: $showDeleteConfirm,
                titleVisibility: .visible
            ) {
                Button("Delete All Data", role: .destructive) { deleteAllData() }
                Button("Cancel", role: .cancel) { }
            } message: {
                Text("This permanently deletes all \(snapshots.count) snapshots. This action cannot be undone.")
            }
            .confirmationDialog(
                "Repair Legacy Records",
                isPresented: $showRepairLegacyRecordsConfirm,
                titleVisibility: .visible
            ) {
                Button("Delete Legacy Record Rows", role: .destructive) { repairLegacyRecordRows() }
                Button("Cancel", role: .cancel) { }
            } message: {
                Text("This removes old per-record SwiftData rows left by earlier builds. Compact record archives and snapshot counts are preserved.")
            }
        }
    }

    // MARK: - Sections

    private var deviceSection: some View {
        Section("This Device") {
            if let profile = currentDeviceProfile {
                HStack {
                    Text("Name")
                    Spacer()
                    TextField("Device name", text: Binding(
                        get: { profile.name },
                        set: {
                            profile.name = $0
                            try? modelContext.save()
                        }
                    ))
                    .multilineTextAlignment(.trailing)
                    .foregroundStyle(.secondary)
                }

                HStack {
                    Text("Color")
                    Spacer()
                    HStack(spacing: 10) {
                        ForEach(DeviceColor.allCases) { dc in
                            ZStack {
                                Circle()
                                    .fill(dc.color)
                                    .frame(width: 24, height: 24)
                                if profile.colorTag == dc.rawValue {
                                    Circle()
                                        .strokeBorder(.primary.opacity(0.75), lineWidth: 2.5)
                                        .frame(width: 24, height: 24)
                                }
                            }
                            .onTapGesture {
                                profile.colorTag = dc.rawValue
                                try? modelContext.save()
                            }
                            .accessibilityLabel(dc.rawValue.capitalized)
                            .accessibilityAddTraits(profile.colorTag == dc.rawValue ? .isSelected : [])
                        }
                    }
                }
            } else {
                Text("Loading…")
                    .foregroundStyle(.secondary)
            }
        }
    }

    private var monitoringSection: some View {
        Section("Monitoring") {
            Picker("Check Frequency", selection: $checkFrequencyHours) {
                Text("Every 2 hours").tag(2)
                Text("Every 6 hours").tag(6)
                Text("Every 12 hours").tag(12)
                Text("Every 24 hours").tag(24)
            }
        }
    }

    private var timeoutCalibrationSection: some View {
        Section("Timeout Calibration") {
            Toggle("Adaptive Timeouts", isOn: Binding(
                get: { appSettings.adaptiveTimeoutsEnabled },
                set: { appSettings.adaptiveTimeoutsEnabled = $0 }
            ))

            InfoRow(label: "Default Initial Timeout") {
                Text(formatDuration(MetricTimeoutProfile.defaultInitialTimeout))
                    .foregroundStyle(.secondary)
            }

            InfoRow(label: "Maximum Timeout") {
                Text(formatDuration(MetricTimeoutProfile.maximumTimeout))
                    .foregroundStyle(.secondary)
            }

            ForEach(timeoutProfiles) { profile in
                TimeoutProfileRow(profile: profile)
            }

            Button(role: .destructive) {
                resetAllTimeoutProfiles()
            } label: {
                Label("Reset All Learned Timeouts", systemImage: "arrow.counterclockwise")
            }
            .disabled(timeoutProfiles.isEmpty)
        }
    }

    @ViewBuilder
    private var typeSelectionSections: some View {
        ForEach(TypeCategory.allCases, id: \.self) { category in
            Section(category.rawValue) {
                ForEach(HealthKitService.allTypes.filter { $0.category == category }) { type in
                    TypeToggleRow(type: type, appSettings: appSettings)
                }
            }
        }
    }

    private var dataSection: some View {
        Section("Data") {
            InfoRow(label: "Stored Snapshots") {
                Text("\(snapshots.count)")
                    .foregroundStyle(.secondary)
            }
            Button(role: .destructive) {
                showDeleteConfirm = true
            } label: {
                Label("Delete All Audit Data", systemImage: "trash")
            }
            .disabled(snapshots.isEmpty)

            Button {
                showRepairLegacyRecordsConfirm = true
            } label: {
                Label("Repair Legacy Record Rows", systemImage: "wrench.and.screwdriver")
            }

            if let dataMaintenanceMessage {
                Text(dataMaintenanceMessage)
                    .font(.caption)
                    .foregroundStyle(.secondary)
            }
        }
    }

    private var aboutSection: some View {
        Section("About") {
            InfoRow(label: "Version") {
                Text(Bundle.main.appVersionString)
                    .foregroundStyle(.secondary)
            }
            InfoRow(label: "Purpose") {
                Text("Read-only HealthKit audit tool")
                    .foregroundStyle(.secondary)
            }
        }
    }

    // MARK: - Actions

    private func ensureCurrentDeviceProfile() {
        guard currentDeviceProfile == nil, !currentDeviceID.isEmpty else { return }
        modelContext.insert(DeviceProfile(deviceID: currentDeviceID))
        try? modelContext.save()
    }

    private func ensureTimeoutProfiles() {
        let existingIDs = Set(timeoutProfiles.map(\.metricIdentifier))
        for type in HealthKitService.allTypes where !existingIDs.contains(type.id) {
            modelContext.insert(MetricTimeoutProfile(metricIdentifier: type.id, displayName: type.displayName))
        }
        try? modelContext.save()
    }

    private func resetAllTimeoutProfiles() {
        for profile in timeoutProfiles {
            profile.resetLearning()
        }
        try? modelContext.save()
    }

    private func deleteAllData() {
        do {
            try modelContext.delete(model: HealthRecord.self)
            try modelContext.delete(model: TypeDistributionBin.self)
            try modelContext.delete(model: YearlyCount.self)
            try modelContext.delete(model: TypeCount.self)
            try modelContext.delete(model: HealthSnapshot.self)
            try modelContext.save()
            dataMaintenanceMessage = "Audit data deleted."
        } catch {
            dataMaintenanceMessage = "Delete failed: \(error.localizedDescription)"
        }
    }

    private func repairLegacyRecordRows() {
        do {
            try modelContext.delete(model: HealthRecord.self)
            try modelContext.save()
            dataMaintenanceMessage = "Legacy record rows deleted."
        } catch {
            dataMaintenanceMessage = "Repair failed: \(error.localizedDescription)"
        }
    }
}

// MARK: - Subviews

private struct TypeToggleRow: View {
    let type: MonitoredType
    let appSettings: AppSettings

    var body: some View {
        Toggle(isOn: Binding(
            get: { appSettings.isEnabled(type) },
            set: { _ in appSettings.toggle(type) }
        )) {
            Text(type.displayName)
        }
        .accessibilityLabel("\(type.displayName), \(appSettings.isEnabled(type) ? "enabled" : "disabled")")
    }
}

private struct TimeoutProfileRow: View {
    @Bindable var profile: MetricTimeoutProfile

    var body: some View {
        VStack(alignment: .leading, spacing: 8) {
            HStack(alignment: .firstTextBaseline) {
                Text(profile.displayName)
                    .font(.subheadline.weight(.semibold))
                Spacer()
                Text(formatDuration(profile.effectiveTimeout))
                    .font(.subheadline.weight(.semibold))
                    .foregroundStyle(.secondary)
            }

            HStack {
                Text(profile.timeoutMode.capitalized)
                Spacer()
                Text("Success \(profile.successCount)")
                Text("Timeouts \(profile.timeoutCount)")
            }
            .font(.caption)
            .foregroundStyle(.secondary)

            HStack {
                Text("Last success")
                Spacer()
                Text(profile.lastSuccessfulElapsed > 0 ? formatDuration(profile.lastSuccessfulElapsed) : "none")
            }
            .font(.caption)
            .foregroundStyle(.secondary)

            HStack {
                Text("Last timeout")
                Spacer()
                Text(profile.lastTimeoutElapsed > 0 ? formatDuration(profile.lastTimeoutElapsed) : "none")
            }
            .font(.caption)
            .foregroundStyle(.secondary)

            HStack {
                Text("p95 success")
                Spacer()
                Text(profile.p95SuccessfulElapsedIfAvailable.map(formatDuration) ?? "collecting")
            }
            .font(.caption)
            .foregroundStyle(.secondary)

            if profile.isManuallyOverridden {
                Stepper(
                    "Manual \(formatDuration(profile.manualTimeoutValue))",
                    value: $profile.manualTimeoutValue,
                    in: MetricTimeoutProfile.defaultInitialTimeout...MetricTimeoutProfile.maximumTimeout,
                    step: 5
                )
                .font(.caption)
                .onChange(of: profile.manualTimeoutValue) { _, newValue in
                    profile.setManualTimeout(newValue)
                }
            }

            HStack {
                Button("Set Manual") {
                    profile.setManualTimeout(profile.effectiveTimeout)
                }
                .buttonStyle(.borderless)

                Button("Automatic") {
                    profile.returnToAutomatic()
                }
                .buttonStyle(.borderless)
                .disabled(!profile.isManuallyOverridden)

                Spacer()

                Button("Reset", role: .destructive) {
                    profile.resetLearning()
                }
                .buttonStyle(.borderless)
            }
            .font(.caption)
        }
        .padding(.vertical, 4)
    }
}

private struct InfoRow<Content: View>: View {
    let label: String
    @ViewBuilder let content: () -> Content
    var body: some View {
        HStack { Text(label); Spacer(); content() }
    }
}

private extension Bundle {
    var appVersionString: String {
        let version = infoDictionary?["CFBundleShortVersionString"] as? String ?? "–"
        let build   = infoDictionary?["CFBundleVersion"] as? String ?? "–"
        return "\(version) (\(build))"
    }
}

private func formatDuration(_ seconds: TimeInterval) -> String {
    if seconds <= 0 { return "none" }
    if seconds < 60 { return String(format: "%.0fs", seconds) }
    return "\(Int(seconds) / 60)m \(Int(seconds) % 60)s"
}

#Preview {
    SettingsView()
        .modelContainer(for: [HealthSnapshot.self, TypeCount.self, YearlyCount.self, HealthRecord.self, TypeDistributionBin.self, DeviceProfile.self, MetricTimeoutProfile.self], inMemory: true)
        .environment(AppSettings())
}
