import SwiftUI

struct FlightLoadDetailView: View {
    let schedule: FlightSchedule
    let departureCode: String
    let arrivalCode: String
    let date: Date
    let loadService: AirlineLoadService

    @Environment(\.dismiss) private var dismiss
    @State private var load: FlightLoad?
    @State private var isLoading = true
    @State private var error: String?
    @State private var isUpgradeListExpanded = false
    @State private var isStandbyListExpanded = false

    var body: some View {
        NavigationStack {
            ZStack {
                FlightTheme.background
                    .ignoresSafeArea()

                if isLoading {
                    ProgressView()
                        .tint(FlightTheme.accent)
                } else if let error {
                    errorView(error)
                } else if let load {
                    loadContent(load)
                } else {
                    unsupportedAirlineView
                }
            }
            .navigationTitle("Flight Load")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button {
                        dismiss()
                    } label: {
                        Image(systemName: "xmark")
                            .font(.subheadline.weight(.semibold))
                            .foregroundStyle(FlightTheme.textSecondary)
                    }
                }
            }
            .task {
                await fetchLoadData()
            }
        }
    }

    // MARK: - Data Fetching

    private func fetchLoadData() async {
        isLoading = true
        error = nil

        let flightNum = extractFlightNumber(from: schedule.flightNumber)

        print("[FlightLoadDetailView] TAP id=\(schedule.id.uuidString.prefix(8))"
            + " airline=\(schedule.airline.iata)"
            + " scheduleFlightNumber='\(schedule.flightNumber)'"
            + " extracted='\(flightNum)'"
            + " departureTime=\(schedule.departureTime)"
            + " arrivalTime=\(schedule.arrivalTime)"
            + " \(departureCode)->\(arrivalCode)")

        let result = await loadService.fetchLoad(
            airlineCode: schedule.airline.iata,
            flightNumber: flightNum,
            date: date,
            origin: departureCode,
            destination: arrivalCode,
            departureTime: schedule.departureTime
        )
        load = result

        if let l = result {
            print("[FlightLoadDetailView] RECEIVED id=\(schedule.id.uuidString.prefix(8))"
                + " load.flightNumber=\(l.flightNumber)"
                + " totalAvailable=\(l.totalAvailable)"
                + " totalCapacity=\(l.totalCapacity)")
        } else {
            print("[FlightLoadDetailView] RECEIVED id=\(schedule.id.uuidString.prefix(8)) load=nil")
        }

        isLoading = false
    }

    // MARK: - Flight Number Extraction

    /// Strips the airline prefix from a flight number.
    /// "AA 2209" -> "2209", "UA2238" -> "2238", "2209" -> "2209"
    private func extractFlightNumber(from raw: String) -> String {
        let trimmed = raw.trimmingCharacters(in: .whitespaces)
        var start = trimmed.startIndex
        while start < trimmed.endIndex && (trimmed[start].isLetter || trimmed[start] == " ") {
            start = trimmed.index(after: start)
        }
        let result = String(trimmed[start...])
        return result.isEmpty ? trimmed : result
    }

    // MARK: - Error View

    private func errorView(_ message: String) -> some View {
        ContentUnavailableView {
            Label("Unable to Load", systemImage: "exclamationmark.triangle")
        } description: {
            Text("Unable to load flight data.\n\(message)")
        }
    }

    // MARK: - Unsupported Airline

    /// Shown when fetchLoad returns nil. That can be either:
    ///   - the airline is one we don't have a fetcher for (DL, WN, etc.), or
    ///   - the airline IS supported but the carrier's API has no data for
    ///     this specific flight (typical for regional codeshares — AA Eagle
    ///     4-digit flights, UA Express, etc.).
    /// Without knowing which case we hit, the message stays flight-scoped
    /// rather than blaming the whole airline.
    private var unsupportedAirlineView: some View {
        ContentUnavailableView {
            Label("Load Data Unavailable", systemImage: "info.circle")
        } description: {
            Text("Load data isn't available for this flight on \(schedule.airline.name).")
        }
    }

    // MARK: - Load Content

    private func loadContent(_ load: FlightLoad) -> some View {
        ScrollView {
            VStack(alignment: .leading, spacing: 20) {
                flightHeader

                // MARK: - Summary Numbers (hero stats)
                summaryCardUnified(load)

                if !load.cabins.isEmpty {
                    cabinSection(load.cabins)
                }

                if !load.seatAvailability.isEmpty {
                    seatAvailabilitySection(load.seatAvailability)
                }

                if !load.upgradeList.isEmpty {
                    collapsiblePassengerSection(
                        title: "Upgrade Waitlist",
                        count: load.upgradeList.count,
                        passengers: load.upgradeList
                    )
                }

                if !load.standbyList.isEmpty || load.totalStandbyFromPBTS > 0 {
                    collapsiblePassengerSection(
                        title: "Standby List",
                        count: max(load.standbyList.count, load.totalStandbyFromPBTS),
                        passengers: load.standbyList
                    )
                }
            }
            .padding(.horizontal, 16)
            .padding(.vertical, 12)
        }
    }

    // MARK: - Flight Header

    private var flightHeader: some View {
        VStack(alignment: .leading, spacing: 4) {
            Text("\(schedule.airline.iata) \(extractFlightNumber(from: schedule.flightNumber)) \u{00B7} \(departureCode) \u{2192} \(arrivalCode)")
                .font(.title3.weight(.bold))
                .foregroundStyle(FlightTheme.textPrimary)

            Text(schedule.airline.name)
                .font(.subheadline)
                .foregroundStyle(FlightTheme.textSecondary)
        }
        .padding(.bottom, 4)
    }

    // MARK: - Cabin Section

    private func cabinSection(_ cabins: [CabinLoad]) -> some View {
        VStack(alignment: .leading, spacing: 12) {
            Text("CABIN AVAILABILITY")
                .font(FlightTheme.label())
                .foregroundStyle(FlightTheme.textTertiary)

            VStack(spacing: 0) {
                ForEach(Array(cabins.enumerated()), id: \.element.id) { index, cabin in
                    cabinRow(cabin)

                    if index < cabins.count - 1 {
                        Divider()
                            .padding(.horizontal, FlightTheme.cardPadding)
                    }
                }
            }
            .background(FlightTheme.cardBackground)
            .clipShape(RoundedRectangle(cornerRadius: FlightTheme.cardCornerRadius))
        }
    }

    private func cabinRow(_ cabin: CabinLoad) -> some View {
        VStack(alignment: .leading, spacing: 8) {
            HStack {
                Text(cabin.name)
                    .font(.subheadline.weight(.semibold))
                    .foregroundStyle(FlightTheme.textPrimary)

                Spacer()

                Text("\(cabin.available) available")
                    .font(.subheadline)
                    .foregroundStyle(FlightTheme.textSecondary)
            }

            loadProgressBar(loadFactor: cabin.loadFactor, loadColor: cabin.loadColor)

            if cabin.capacity > 0 {
                Text("\(cabin.capacity - cabin.available) of \(cabin.capacity) seats \u{00B7} \(Int(cabin.loadFactor * 100))%")
                    .font(FlightTheme.label(11))
                    .foregroundStyle(FlightTheme.textTertiary)
            }
        }
        .padding(FlightTheme.cardPadding)
    }

    // MARK: - Summary Card (unified for all airlines)

    private func summaryCardUnified(_ load: FlightLoad) -> some View {
        let openSeats: Int
        let standbyCount: Int

        if load.hasCabinData {
            // United-style: derive from pbts
            openSeats = load.totalAvailable
            standbyCount = load.totalStandbyFromPBTS
        } else {
            // AA-style: sum from seatAvailability
            openSeats = load.seatAvailability.reduce(0) { $0 + $1.available }
            standbyCount = load.standbyList.count
        }

        return HStack(spacing: 0) {
            VStack(spacing: 4) {
                Text("\(openSeats)")
                    .font(.system(size: 36, weight: .bold, design: .rounded))
                    .foregroundStyle(FlightTheme.onTime)
                Text("Open Seats")
                    .font(FlightTheme.label())
                    .foregroundStyle(FlightTheme.textSecondary)
            }
            .frame(maxWidth: .infinity)

            Divider()
                .frame(height: 50)

            VStack(spacing: 4) {
                Text("\(standbyCount)")
                    .font(.system(size: 36, weight: .bold, design: .rounded))
                    .foregroundStyle(standbyCount > openSeats ? FlightTheme.cancelled : FlightTheme.delayed)
                Text("On Standby")
                    .font(FlightTheme.label())
                    .foregroundStyle(FlightTheme.textSecondary)
            }
            .frame(maxWidth: .infinity)
        }
        .padding(.vertical, 16)
        .flightCard()
    }

    // MARK: - Collapsible Passenger Section

    private func collapsiblePassengerSection(title: String, count: Int, passengers: [StandbyPassenger]) -> some View {
        VStack(alignment: .leading, spacing: 0) {
            let isExpanded = title.contains("Upgrade") ? isUpgradeListExpanded : isStandbyListExpanded

            Button {
                withAnimation(.easeInOut(duration: 0.2)) {
                    if title.contains("Upgrade") {
                        isUpgradeListExpanded.toggle()
                    } else {
                        isStandbyListExpanded.toggle()
                    }
                }
            } label: {
                HStack {
                    Text("\(title.uppercased()) (\(count))")
                        .font(FlightTheme.label())
                        .foregroundStyle(FlightTheme.textTertiary)
                    Spacer()
                    Image(systemName: isExpanded ? "chevron.up" : "chevron.down")
                        .font(.caption)
                        .foregroundStyle(FlightTheme.textTertiary)
                }
            }
            .buttonStyle(.plain)
            .padding(.bottom, isExpanded ? 12 : 0)

            if isExpanded {
                if passengers.isEmpty {
                    Text("\(count) passenger\(count == 1 ? "" : "s") on \(title.lowercased())")
                        .font(.subheadline)
                        .foregroundStyle(FlightTheme.textSecondary)
                        .padding(FlightTheme.cardPadding)
                        .frame(maxWidth: .infinity, alignment: .leading)
                        .background(FlightTheme.cardBackground)
                        .clipShape(RoundedRectangle(cornerRadius: FlightTheme.cardCornerRadius))
                } else {
                    VStack(spacing: 0) {
                        ForEach(Array(passengers.enumerated()), id: \.element.id) { index, passenger in
                            passengerRow(passenger)

                            if index < passengers.count - 1 {
                                Divider()
                                    .padding(.horizontal, FlightTheme.cardPadding)
                            }
                        }
                    }
                    .background(FlightTheme.cardBackground)
                    .clipShape(RoundedRectangle(cornerRadius: FlightTheme.cardCornerRadius))
                }
            }
        }
    }

    // MARK: - Seat Availability (AA-style, no capacity data)

    private func seatAvailabilitySection(_ items: [SeatAvailability]) -> some View {
        VStack(alignment: .leading, spacing: 12) {
            Text("SEAT AVAILABILITY")
                .font(FlightTheme.label())
                .foregroundStyle(FlightTheme.textTertiary)

            VStack(spacing: 0) {
                ForEach(Array(items.enumerated()), id: \.element.id) { index, item in
                    HStack {
                        Text(item.label)
                            .font(.subheadline.weight(.semibold))
                            .foregroundStyle(FlightTheme.textPrimary)

                        Spacer()

                        Text("\(item.available) available")
                            .font(.subheadline.weight(.medium))
                            .foregroundStyle(colorForAvailability(item.color))
                    }
                    .padding(FlightTheme.cardPadding)

                    if index < items.count - 1 {
                        Divider()
                            .padding(.horizontal, FlightTheme.cardPadding)
                    }
                }
            }
            .background(FlightTheme.cardBackground)
            .clipShape(RoundedRectangle(cornerRadius: FlightTheme.cardCornerRadius))
        }
    }

    private func colorForAvailability(_ color: SeatAvailabilityColor) -> Color {
        switch color {
        case .success: return FlightTheme.onTime
        case .warning: return FlightTheme.delayed
        case .failure: return FlightTheme.cancelled
        }
    }

    // MARK: - Progress Bar

    private func loadProgressBar(loadFactor: Double, loadColor: LoadColor) -> some View {
        GeometryReader { geometry in
            ZStack(alignment: .leading) {
                RoundedRectangle(cornerRadius: 4)
                    .fill(Color(.quaternarySystemFill))

                RoundedRectangle(cornerRadius: 4)
                    .fill(colorForLoadColor(loadColor))
                    .frame(width: max(0, geometry.size.width * min(loadFactor, 1.0)))
            }
        }
        .frame(height: 8)
    }

    private func colorForLoadColor(_ loadColor: LoadColor) -> Color {
        switch loadColor {
        case .green: return FlightTheme.onTime
        case .yellow: return FlightTheme.delayed
        case .red: return FlightTheme.cancelled
        }
    }

    private func passengerRow(_ passenger: StandbyPassenger) -> some View {
        HStack(spacing: 8) {
            Text("\(passenger.order).")
                .font(.subheadline.weight(.bold))
                .foregroundStyle(FlightTheme.textPrimary)
                .frame(width: 28, alignment: .trailing)

            Text(passenger.displayName)
                .font(.subheadline)
                .foregroundStyle(FlightTheme.textPrimary)

            Spacer()

            if passenger.cleared {
                HStack(spacing: 4) {
                    Image(systemName: "checkmark.circle.fill")
                        .font(.caption)
                        .foregroundStyle(FlightTheme.onTime)

                    if let seat = passenger.seat {
                        Text(seat)
                            .font(FlightTheme.label(11))
                            .foregroundStyle(FlightTheme.textSecondary)
                    }
                }
            }
        }
        .padding(.horizontal, FlightTheme.cardPadding)
        .padding(.vertical, 10)
    }
}
