import Foundation
import MapKit

final class AirportDatabase: Sendable {
    let airports: [MapAirport]
    private let regionNames: [String: String]  // "US-TX" -> "Texas"

    init() {
        guard let url = Bundle.main.url(forResource: "airports", withExtension: "json"),
              let data = try? Data(contentsOf: url),
              let decoded = try? JSONDecoder().decode([MapAirport].self, from: data)
        else {
            airports = []
            regionNames = [:]
            return
        }
        airports = decoded
        regionNames = Self.buildRegionNames()
    }

    /// Returns airports within the given map region, capped at `limit` for performance.
    func airports(in region: MKCoordinateRegion, limit: Int = 200) -> [MapAirport] {
        let centerLat = region.center.latitude
        let centerLng = region.center.longitude
        let latDelta = region.span.latitudeDelta / 2
        let lngDelta = region.span.longitudeDelta / 2

        let minLat = centerLat - latDelta
        let maxLat = centerLat + latDelta
        let minLng = centerLng - lngDelta
        let maxLng = centerLng + lngDelta

        var result: [MapAirport] = []
        for airport in airports {
            guard airport.lat >= minLat, airport.lat <= maxLat else { continue }

            if minLng <= maxLng {
                guard airport.lng >= minLng, airport.lng <= maxLng else { continue }
            } else {
                guard airport.lng >= minLng || airport.lng <= maxLng else { continue }
            }

            result.append(airport)
            if result.count >= limit { break }
        }

        return result
    }

    /// Search airports by region/state name (e.g. "Texas" -> all US-TX airports).
    /// Returns matching region name and airports, or nil if no match.
    func searchByRegion(term: String) -> (regionName: String, airports: [MapAirport])? {
        let lowered = term.lowercased().trimmingCharacters(in: .whitespacesAndNewlines)
        guard lowered.count >= 3 else { return nil }

        // Find matching region
        var matchedCode: String?
        var matchedName: String?

        for (code, name) in regionNames {
            if name.lowercased().hasPrefix(lowered) || name.lowercased() == lowered {
                matchedCode = code
                matchedName = name
                break
            }
        }

        guard let code = matchedCode, let name = matchedName else { return nil }

        let results = airports.filter { $0.region == code }
            .sorted { $0.name.localizedCompare($1.name) == .orderedAscending }

        guard !results.isEmpty else { return nil }
        return (regionName: name, airports: results)
    }

    /// Look up a single airport by IATA code
    func airport(byIATA code: String) -> MapAirport? {
        airports.first { $0.iata == code }
    }

    private static func buildRegionNames() -> [String: String] {
        // US states + territories
        var names: [String: String] = [
            "US-AL": "Alabama", "US-AK": "Alaska", "US-AZ": "Arizona", "US-AR": "Arkansas",
            "US-CA": "California", "US-CO": "Colorado", "US-CT": "Connecticut", "US-DE": "Delaware",
            "US-FL": "Florida", "US-GA": "Georgia", "US-HI": "Hawaii", "US-ID": "Idaho",
            "US-IL": "Illinois", "US-IN": "Indiana", "US-IA": "Iowa", "US-KS": "Kansas",
            "US-KY": "Kentucky", "US-LA": "Louisiana", "US-ME": "Maine", "US-MD": "Maryland",
            "US-MA": "Massachusetts", "US-MI": "Michigan", "US-MN": "Minnesota", "US-MS": "Mississippi",
            "US-MO": "Missouri", "US-MT": "Montana", "US-NE": "Nebraska", "US-NV": "Nevada",
            "US-NH": "New Hampshire", "US-NJ": "New Jersey", "US-NM": "New Mexico", "US-NY": "New York",
            "US-NC": "North Carolina", "US-ND": "North Dakota", "US-OH": "Ohio", "US-OK": "Oklahoma",
            "US-OR": "Oregon", "US-PA": "Pennsylvania", "US-RI": "Rhode Island", "US-SC": "South Carolina",
            "US-SD": "South Dakota", "US-TN": "Tennessee", "US-TX": "Texas", "US-UT": "Utah",
            "US-VT": "Vermont", "US-VA": "Virginia", "US-WA": "Washington", "US-WV": "West Virginia",
            "US-WI": "Wisconsin", "US-WY": "Wyoming", "US-DC": "District of Columbia",
            "US-PR": "Puerto Rico", "US-VI": "U.S. Virgin Islands", "US-GU": "Guam",
            "US-AS": "American Samoa",
            // Canadian provinces
            "CA-AB": "Alberta", "CA-BC": "British Columbia", "CA-MB": "Manitoba",
            "CA-NB": "New Brunswick", "CA-NL": "Newfoundland and Labrador",
            "CA-NS": "Nova Scotia", "CA-NT": "Northwest Territories", "CA-NU": "Nunavut",
            "CA-ON": "Ontario", "CA-PE": "Prince Edward Island", "CA-QC": "Quebec",
            "CA-SK": "Saskatchewan", "CA-YT": "Yukon",
            // Australian states
            "AU-NSW": "New South Wales", "AU-VIC": "Victoria", "AU-QLD": "Queensland",
            "AU-WA": "Western Australia", "AU-SA": "South Australia", "AU-TAS": "Tasmania",
            "AU-NT": "Northern Territory", "AU-ACT": "Australian Capital Territory",
        ]
        return names
    }
}
