import SwiftUI
import MapKit

struct AirportMapView: View {
    let database: AirportDatabase
    let service: FlightService
    let onSelect: (Airport) -> Void

    @State private var position: MapCameraPosition = .automatic
    @State private var visibleRegion: MKCoordinateRegion?
    @State private var visibleAirports: [MapAirport] = []
    @State private var selectedAirport: MapAirport?
    @State private var isSelecting = false

    var body: some View {
        ZStack {
            Map(position: $position) {
                ForEach(visibleAirports) { airport in
                    Annotation(airport.iata, coordinate: airport.coordinate) {
                        Button {
                            selectedAirport = airport
                        } label: {
                            Image(systemName: "airplane.circle.fill")
                                .font(.title2)
                                .foregroundStyle(selectedAirport?.id == airport.id ? .blue : .red)
                                .background(Circle().fill(.white).padding(2))
                        }
                    }
                }
            }
            .onMapCameraChange(frequency: .onEnd) { context in
                visibleRegion = context.region
                updateVisibleAirports()
            }

            if let airport = selectedAirport {
                VStack {
                    Spacer()
                    airportPopup(airport)
                        .padding()
                        .transition(.move(edge: .bottom).combined(with: .opacity))
                }
                .animation(.easeInOut(duration: 0.2), value: selectedAirport)
            }
        }
        .onAppear {
            let initial = MKCoordinateRegion(
                center: CLLocationCoordinate2D(latitude: 30, longitude: -40),
                span: MKCoordinateSpan(latitudeDelta: 120, longitudeDelta: 180)
            )
            position = .region(initial)
            visibleRegion = initial
            updateVisibleAirports()
        }
    }

    private func airportPopup(_ airport: MapAirport) -> some View {
        HStack(spacing: 16) {
            VStack(alignment: .leading, spacing: 4) {
                Text(airport.name)
                    .font(.headline)
                HStack(spacing: 8) {
                    Text(airport.iata)
                        .font(.subheadline)
                        .fontWeight(.semibold)
                        .foregroundStyle(.blue)
                    Text(airport.country)
                        .font(.subheadline)
                        .foregroundStyle(.secondary)
                }
            }

            Spacer()

            if isSelecting {
                ProgressView()
                    .controlSize(.small)
            } else {
                Button {
                    selectAirport(airport)
                } label: {
                    Text("Select")
                        .fontWeight(.semibold)
                        .padding(.horizontal, 16)
                        .padding(.vertical, 8)
                        .background(.blue)
                        .foregroundStyle(.white)
                        .clipShape(RoundedRectangle(cornerRadius: 8))
                }
            }

            Button {
                selectedAirport = nil
            } label: {
                Image(systemName: "xmark.circle.fill")
                    .font(.title3)
                    .foregroundStyle(.secondary)
            }
        }
        .padding()
        .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 16))
        .shadow(radius: 8)
    }

    private func updateVisibleAirports() {
        guard let region = visibleRegion else { return }
        visibleAirports = database.airports(in: region, limit: 200)
    }

    private func selectAirport(_ mapAirport: MapAirport) {
        isSelecting = true
        Task {
            do {
                let results = try await service.searchAirports(term: mapAirport.iata)
                if let match = results.first(where: { $0.iata == mapAirport.iata }) {
                    onSelect(match)
                } else {
                    onSelect(Airport(
                        id: "",
                        iata: mapAirport.iata,
                        name: mapAirport.name
                    ))
                }
            } catch {
                isSelecting = false
            }
        }
    }
}
