import Foundation
import SwiftData

/// A single flight the user has flown (or is flying), persisted to
/// SwiftData and synced via CloudKit private DB. Intentionally lean —
/// we don't track baggage / terminal / gate / seat / cabin class /
/// delay reason. Just identity, route, aircraft, and free-text notes.
///
/// CloudKit constraints: every property must be optional or have a
/// default value, and no `@Attribute(.unique)` on synced models.
@Model
final class LoggedFlight {
    var id: UUID = UUID()
    var loggedAt: Date = Date()

    // MARK: Identity
    var flightDate: Date = Date()
    var carrierICAO: String?       // "SWA"
    var carrierIATA: String?       // "WN"
    var flightNumber: String?      // "7"

    // MARK: Route — IATA codes are the canonical key into our airport DB
    var departureIATA: String = ""
    var arrivalIATA: String = ""
    var scheduledDeparture: Date?
    var scheduledArrival: Date?
    var actualDeparture: Date?
    var actualArrival: Date?

    // MARK: Aircraft
    var aircraftType: String?      // "B738"
    var registration: String?      // "N281WN" — also keys into AirframeMetadata
    /// 24-bit ICAO transponder address (e.g. "abc123"). Only populated
    /// for live-tap adds; lets the detail screen pull the actual flown
    /// track from OpenSky's history endpoint.
    var icao24: String?

    // MARK: Personal
    var notes: String?

    /// Origin of this record. Used for analytics / debugging only.
    /// Values: "live-tap" | "manual" | "calendar" | "wallet" | "mail-share"
    var source: String = "manual"

    // MARK: Standby (nonrev) tracking
    /// Outcome of a standby attempt for this flight.
    /// Values: "confirmed" | "standby-made" | "standby-bumped" | nil
    /// All optional / default nil so existing records migrate automatically.
    var standbyOutcome: String?
    var standbyAttemptedAt: Date?
    var standbyClearedAt: Date?
    var standbyClass: String?
    var standbyNotes: String?

    init(
        id: UUID = UUID(),
        loggedAt: Date = Date(),
        flightDate: Date = Date(),
        carrierICAO: String? = nil,
        carrierIATA: String? = nil,
        flightNumber: String? = nil,
        departureIATA: String = "",
        arrivalIATA: String = "",
        scheduledDeparture: Date? = nil,
        scheduledArrival: Date? = nil,
        actualDeparture: Date? = nil,
        actualArrival: Date? = nil,
        aircraftType: String? = nil,
        registration: String? = nil,
        icao24: String? = nil,
        notes: String? = nil,
        source: String = "manual"
    ) {
        self.id = id
        self.loggedAt = loggedAt
        self.flightDate = flightDate
        self.carrierICAO = carrierICAO
        self.carrierIATA = carrierIATA
        self.flightNumber = flightNumber
        self.departureIATA = departureIATA
        self.arrivalIATA = arrivalIATA
        self.scheduledDeparture = scheduledDeparture
        self.scheduledArrival = scheduledArrival
        self.actualDeparture = actualDeparture
        self.actualArrival = actualArrival
        self.aircraftType = aircraftType
        // Normalise tail to uppercase at write time so the
        // AirframeHistoryStore fast-path predicate (an exact-match
        // #Predicate, which can't call .uppercased()) always hits.
        // AirframeMetadata.registration is similarly uppercased.
        self.registration = registration.flatMap { reg in
            let trimmed = reg.trimmingCharacters(in: .whitespacesAndNewlines)
            return trimmed.isEmpty ? nil : trimmed.uppercased()
        }
        self.icao24 = icao24
        self.notes = notes
        self.source = source
    }

    /// IATA-style flight label, e.g. "WN7" or "SWA7" if IATA is missing.
    var flightLabel: String {
        let prefix = carrierIATA ?? carrierICAO ?? ""
        let number = flightNumber ?? ""
        if prefix.isEmpty && number.isEmpty { return "—" }
        return "\(prefix)\(number)"
    }

    /// True when this flight was attempted on standby (regardless of whether
    /// it cleared or the user got bumped).
    var wasStandby: Bool {
        standbyOutcome == "standby-made" || standbyOutcome == "standby-bumped"
    }
}
