import SwiftUI
import EventKit

/// Scan-the-calendar import flow. Shows discovered flight-shaped events
/// as a checkable list; user toggles which to import, taps Import All,
/// and we route-explorer-autofill them in the background. Dedupes
/// against existing logs.
struct CalendarImportView: View {
    let routeExplorer: RouteExplorerClient
    let database: AirportDatabase
    let store: FlightHistoryStore

    @Environment(\.dismiss) private var dismiss

    @State private var phase: Phase = .askingPermission
    @State private var candidates: [CalendarFlightImporter.Candidate] = []
    @State private var selected: Set<UUID> = []
    @State private var importing = false
    @State private var importedCount = 0

    enum Phase {
        case askingPermission
        case denied
        case scanning
        case ready
        case importing
        case done
    }

    private let importer = CalendarFlightImporter()

    var body: some View {
        NavigationStack {
            content
                .navigationTitle("Scan calendar")
                .navigationBarTitleDisplayMode(.inline)
                .toolbar {
                    ToolbarItem(placement: .cancellationAction) {
                        Button("Done") { dismiss() }
                    }
                    if phase == .ready && !selected.isEmpty {
                        ToolbarItem(placement: .primaryAction) {
                            Button("Import \(selected.count)") {
                                Task { await importSelected() }
                            }
                        }
                    }
                }
                .task(id: phase) {
                    if phase == .askingPermission {
                        let ok = await importer.requestAccess()
                        phase = ok ? .scanning : .denied
                    } else if phase == .scanning {
                        let cands = importer.scan()
                        // Pre-dedupe against existing log
                        let novel = cands.filter { c in
                            !store.exists(
                                flightDate: c.flightDate,
                                flightLabel: c.flightLabel,
                                departureIATA: c.departureIATA ?? "",
                                arrivalIATA: c.arrivalIATA ?? ""
                            )
                        }
                        candidates = novel.sorted { $0.flightDate > $1.flightDate }
                        selected = Set(candidates.map { $0.id })
                        phase = .ready
                    }
                }
        }
    }

    @ViewBuilder
    private var content: some View {
        switch phase {
        case .askingPermission, .scanning:
            VStack(spacing: 12) {
                ProgressView()
                Text(phase == .askingPermission ? "Requesting access…" : "Scanning your calendar…")
                    .font(.subheadline)
                    .foregroundStyle(FlightTheme.textSecondary)
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)

        case .denied:
            ContentUnavailableView(
                "Calendar access denied",
                systemImage: "calendar.badge.exclamationmark",
                description: Text("Enable calendar access in Settings to scan for flight events.")
            )

        case .ready:
            if candidates.isEmpty {
                ContentUnavailableView(
                    "No new flights found",
                    systemImage: "calendar.badge.checkmark",
                    description: Text("Your calendar didn't have any flight-shaped events that aren't already in your log.")
                )
            } else {
                List(candidates) { c in
                    Button {
                        toggle(c.id)
                    } label: {
                        HStack {
                            Image(systemName: selected.contains(c.id) ? "checkmark.circle.fill" : "circle")
                                .foregroundStyle(selected.contains(c.id) ? FlightTheme.accent : FlightTheme.textTertiary)
                            VStack(alignment: .leading) {
                                Text(c.flightLabel)
                                    .font(.subheadline.weight(.bold).monospaced())
                                if let from = c.departureIATA, let to = c.arrivalIATA {
                                    Text("\(from) → \(to)")
                                        .font(.caption.monospaced())
                                        .foregroundStyle(FlightTheme.textSecondary)
                                } else {
                                    Text("Route TBD via lookup")
                                        .font(.caption)
                                        .foregroundStyle(FlightTheme.textTertiary)
                                }
                            }
                            Spacer()
                            Text(shortDate(c.flightDate))
                                .font(.caption.monospaced())
                                .foregroundStyle(FlightTheme.textTertiary)
                        }
                    }
                    .buttonStyle(.plain)
                }
            }

        case .importing:
            VStack(spacing: 12) {
                ProgressView()
                Text("Importing \(importedCount) / \(selected.count)…")
                    .font(.subheadline)
                    .foregroundStyle(FlightTheme.textSecondary)
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)

        case .done:
            ContentUnavailableView(
                "Imported \(importedCount) flights",
                systemImage: "checkmark.circle.fill",
                description: Text("Your log is up to date.")
            )
        }
    }

    private func toggle(_ id: UUID) {
        if selected.contains(id) { selected.remove(id) } else { selected.insert(id) }
    }

    private func importSelected() async {
        phase = .importing
        importedCount = 0
        for c in candidates where selected.contains(c.id) {
            // Route-explorer enrichment when carrier + flight # are known.
            var depIATA = c.departureIATA ?? ""
            var arrIATA = c.arrivalIATA ?? ""
            var sched: (dep: Date?, arr: Date?) = (nil, nil)

            if let carrier = c.carrierIATA, let num = c.flightNumber.flatMap(Int.init) {
                let day = Calendar.current.startOfDay(for: c.flightDate)
                let next = Calendar.current.date(byAdding: .day, value: 1, to: day) ?? day
                let results = await routeExplorer.searchSchedule(
                    carrierCode: carrier,
                    flightNumber: num,
                    startDate: day,
                    endDate: next
                )
                if let r = results.first {
                    if depIATA.isEmpty { depIATA = r.departure.airportIata }
                    if arrIATA.isEmpty { arrIATA = r.arrival.airportIata }
                    sched = (r.departure.dateTime, r.arrival.dateTime)
                }
            }

            let icao = c.carrierIATA.flatMap { AircraftRegistry.shared.lookup(iata: $0)?.icao }
            let flight = LoggedFlight(
                flightDate: c.flightDate,
                carrierICAO: icao,
                carrierIATA: c.carrierIATA,
                flightNumber: c.flightNumber,
                departureIATA: depIATA,
                arrivalIATA: arrIATA,
                scheduledDeparture: sched.dep,
                scheduledArrival: sched.arr,
                source: "calendar"
            )
            store.save(flight)
            importedCount += 1
        }
        phase = .done
    }

    private func shortDate(_ d: Date) -> String {
        let f = DateFormatter()
        f.dateFormat = "MMM d, yyyy"
        return f.string(from: d)
    }
}
