import SwiftUI
import UniformTypeIdentifiers

/// File-importer-driven CSV import flow. User picks a CSV from Files
/// (iCloud Drive / On My iPhone / etc.); we detect the format, show a
/// preview with dedupe counts, and on confirm save every novel row as
/// a LoggedFlight. Dupes (same date + flight # + route) are skipped.
struct ImportCSVView: View {
    let store: FlightHistoryStore
    let routeExplorer: RouteExplorerClient

    @Environment(\.dismiss) private var dismiss

    @State private var phase: Phase = .picking
    @State private var pickedURL: URL?
    @State private var parsed: [CSVFlightImporter.ParsedFlight] = []
    @State private var novel: [CSVFlightImporter.ParsedFlight] = []
    @State private var skipped: Int = 0
    @State private var errorText: String?
    @State private var importedCount: Int = 0
    @State private var enrichedCount: Int = 0
    @State private var enrichEnabled: Bool = true
    @State private var showFilePicker = false

    enum Phase: Equatable {
        case picking
        case parsing
        case preview
        case importing
        case done
        case failed
    }

    var body: some View {
        NavigationStack {
            content
                .navigationTitle("Import CSV")
                .navigationBarTitleDisplayMode(.inline)
                .toolbar {
                    ToolbarItem(placement: .cancellationAction) {
                        Button("Done") { dismiss() }
                    }
                    if phase == .preview && !novel.isEmpty {
                        ToolbarItem(placement: .primaryAction) {
                            Button("Import \(novel.count)") { Task { await runImport() } }
                        }
                    }
                }
                .fileImporter(
                    isPresented: $showFilePicker,
                    allowedContentTypes: [.commaSeparatedText, .text, .data],
                    allowsMultipleSelection: false
                ) { result in
                    handlePicker(result)
                }
                .task(id: pickedURL) {
                    guard let pickedURL else { return }
                    await runParse(url: pickedURL)
                }
        }
    }

    @ViewBuilder
    private var content: some View {
        switch phase {
        case .picking:
            VStack(spacing: 16) {
                Image(systemName: "doc.text")
                    .font(.system(size: 56))
                    .foregroundStyle(FlightTheme.textTertiary)
                Text("Choose a CSV file to import")
                    .font(.headline)
                Text("Supported: Southwest PNR export\n(columns Flt No, ORG, DST, Dep Date, OPNG Flt)")
                    .font(.caption)
                    .multilineTextAlignment(.center)
                    .foregroundStyle(FlightTheme.textTertiary)
                    .padding(.horizontal, 32)
                Button {
                    showFilePicker = true
                } label: {
                    Label("Choose file…", systemImage: "folder")
                        .font(.subheadline.weight(.semibold))
                        .padding(.horizontal, 16)
                        .padding(.vertical, 10)
                }
                .background(FlightTheme.accent, in: Capsule())
                .foregroundStyle(.white)
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)

        case .parsing:
            VStack(spacing: 12) {
                ProgressView()
                Text("Parsing…")
                    .font(.subheadline)
                    .foregroundStyle(FlightTheme.textSecondary)
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)

        case .preview:
            previewList

        case .importing:
            VStack(spacing: 12) {
                ProgressView()
                Text("Importing \(importedCount) / \(novel.count)…")
                    .font(.subheadline)
                    .foregroundStyle(FlightTheme.textSecondary)
                if enrichEnabled {
                    Text("Found aircraft type for \(enrichedCount)")
                        .font(.caption)
                        .foregroundStyle(FlightTheme.textTertiary)
                }
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)

        case .done:
            ContentUnavailableView(
                "Imported \(importedCount) flights",
                systemImage: "checkmark.circle.fill",
                description: Text(skipped > 0 ? "Skipped \(skipped) duplicates." : "Your log is up to date.")
            )

        case .failed:
            ContentUnavailableView(
                "Couldn't read this file",
                systemImage: "exclamationmark.triangle.fill",
                description: Text(errorText ?? "Try a different CSV.")
            )
        }
    }

    private var previewList: some View {
        List {
            Section {
                HStack {
                    Text("\(parsed.count) rows in file")
                    Spacer()
                    Text("\(novel.count) new · \(skipped) dupes")
                        .foregroundStyle(FlightTheme.textTertiary)
                }
                .font(.subheadline)
            } header: {
                Text("Summary")
            }
            Section {
                Toggle(isOn: $enrichEnabled) {
                    VStack(alignment: .leading, spacing: 2) {
                        Text("Look up aircraft type")
                            .font(.subheadline.weight(.semibold))
                        Text("Adds a few seconds per flight via route-explorer schedule data. Old flights may not match.")
                            .font(.caption)
                            .foregroundStyle(FlightTheme.textSecondary)
                    }
                }
            } header: {
                Text("Enrichment")
            }
            Section {
                ForEach(Array(novel.prefix(50).enumerated()), id: \.offset) { _, p in
                    VStack(alignment: .leading, spacing: 2) {
                        Text("\(p.carrierIATA ?? "?")\(p.flightNumber ?? "?")")
                            .font(.subheadline.weight(.semibold).monospaced())
                        Text("\(p.departureIATA) → \(p.arrivalIATA) · \(shortDate(p.flightDate))")
                            .font(.caption.monospaced())
                            .foregroundStyle(FlightTheme.textSecondary)
                    }
                }
                if novel.count > 50 {
                    Text("…and \(novel.count - 50) more")
                        .font(.caption)
                        .foregroundStyle(FlightTheme.textTertiary)
                }
            } header: {
                Text("Will be imported")
            }
        }
    }

    private func handlePicker(_ result: Result<[URL], Error>) {
        switch result {
        case .success(let urls):
            pickedURL = urls.first
        case .failure(let error):
            errorText = error.localizedDescription
            phase = .failed
        }
    }

    /// Two-step lookup. Tries route-explorer first (works for future
    /// schedules, returns IATA), then FlightAware (works for
    /// historical flights, returns ICAO). Normalizes the result to
    /// canonical ICAO before returning.
    private func lookupAircraftType(for p: CSVFlightImporter.ParsedFlight) async -> String? {
        guard let carrier = p.carrierIATA,
              let numStr = p.flightNumber,
              let num = Int(numStr)
        else { return nil }
        let day = Calendar.current.startOfDay(for: p.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
        )
        let exact = results.first {
            $0.departure.airportIata == p.departureIATA
                && $0.arrival.airportIata == p.arrivalIATA
        } ?? results.first
        if let eq = exact?.equipmentIata, !eq.isEmpty {
            return AircraftDatabase.shared.normalizedICAO(forCode: eq)
        }

        // FlightAware fallback for historical flights
        guard let carrierICAO = p.carrierICAO
            ?? AircraftRegistry.shared.lookup(iata: carrier)?.icao
        else { return nil }
        let callsign = "\(carrierICAO)\(num)"
        if let icaoType = await FlightAwareLookup.shared.lookupType(
            callsign: callsign,
            departureIATA: p.departureIATA,
            arrivalIATA: p.arrivalIATA
        ) {
            return AircraftDatabase.shared.normalizedICAO(forCode: icaoType)
        }
        return nil
    }

    private func runParse(url: URL) async {
        phase = .parsing
        let didStart = url.startAccessingSecurityScopedResource()
        defer {
            if didStart { url.stopAccessingSecurityScopedResource() }
        }
        do {
            let data = try Data(contentsOf: url)
            let rows = try CSVFlightImporter.parse(data)
            parsed = rows
            var (n, s) = ([CSVFlightImporter.ParsedFlight](), 0)
            for r in rows {
                let label = "\(r.carrierIATA ?? "")\(r.flightNumber ?? "")"
                if store.exists(
                    flightDate: r.flightDate,
                    flightLabel: label,
                    departureIATA: r.departureIATA,
                    arrivalIATA: r.arrivalIATA
                ) {
                    s += 1
                } else {
                    n.append(r)
                }
            }
            novel = n
            skipped = s
            phase = .preview
        } catch {
            errorText = error.localizedDescription
            phase = .failed
        }
    }

    private func runImport() async {
        phase = .importing
        importedCount = 0
        enrichedCount = 0
        for p in novel {
            // Optionally look up the scheduled aircraft type via
            // route-explorer for this carrier/flight/date so the
            // Aircraft stats screen has data even from a bare CSV.
            // Best-effort: silently skip on failure or no match.
            let enrichedType: String? = enrichEnabled
                ? await lookupAircraftType(for: p)
                : nil
            if enrichedType != nil { enrichedCount += 1 }

            let f = LoggedFlight(
                flightDate: p.flightDate,
                carrierICAO: p.carrierICAO,
                carrierIATA: p.carrierIATA,
                flightNumber: p.flightNumber,
                departureIATA: p.departureIATA,
                arrivalIATA: p.arrivalIATA,
                scheduledDeparture: p.scheduledDeparture,
                scheduledArrival: nil,
                aircraftType: enrichedType,
                registration: nil,
                icao24: nil,
                notes: p.pnr.map { "PNR: \($0)" },
                source: "csv-import"
            )
            store.save(f)
            importedCount += 1
        }
        phase = .done
    }

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