import { computed, ComputedRef } from 'vue'
import { Flight } from '@/Types/types'

export interface Continent {
    id: number
    name: string
    code: string
    internal_name: string
}

export interface ContinentPairEntry {
    key: string
    label: string
    flights: Flight[]
}

/** Stable undirected key — always alphabetically sorted so A|B === B|A */
export function undirectedKey(a: string, b: string): string {
    return [a, b].sort().join('|')
}

/** Directed key — order preserved */
export function directedKey(dep: string, arr: string): string {
    return `${dep}|${arr}`
}

export function labelFor(a: string, b: string): string {
    return `${a}↔${b}`
}

export function continentNameOf(flight: Flight, side: 'departure' | 'arrival'): string | null {
    const airport = side === 'departure' ? flight.departure_airport : flight.arrival_airport
    return airport.region?.continent?.name ?? null
}

export function isInternational(flight: Flight): boolean {
    const depCountry = flight.departure_airport.region?.country_id
    const arrCountry = flight.arrival_airport.region?.country_id
    if (depCountry == null || arrCountry == null) return true
    return depCountry !== arrCountry
}

/** Filter flights to only those that qualify for continent-pair achievements */
export function qualifyingFlights(flights: Flight[]): Flight[] {
    return flights.filter(flight => {
        const dep = continentNameOf(flight, 'departure')
        const arr = continentNameOf(flight, 'arrival')
        if (!dep || !arr) return false
        if (dep === arr && !isInternational(flight)) return false
        return true
    })
}

// ── One-way (undirected) pairs ─────────────────────────────────────────────

export function useUndirectedContinentPairs(
    flights: ComputedRef<Flight[]>,
    continents: ComputedRef<Continent[]>,
) {
    const allKeys = computed<string[]>(() => {
        const names = continents.value.map(c => c.name).sort()
        const keys: string[] = []
        for (let i = 0; i < names.length; i++) {
            for (let j = i; j < names.length; j++) {
                keys.push(undirectedKey(names[i], names[j]))
            }
        }
        return keys.sort((a, b) => {
            const [a1, a2] = a.split('|')
            const [b1, b2] = b.split('|')
            return labelFor(a1, a2).localeCompare(labelFor(b1, b2))
        })
    })

    const flightsByKey = computed<Map<string, Flight[]>>(() => {
        const map = new Map(allKeys.value.map(k => [k, [] as Flight[]]))
        for (const flight of qualifyingFlights(flights.value)) {
            const dep = continentNameOf(flight, 'departure')!
            const arr = continentNameOf(flight, 'arrival')!
            const key = undirectedKey(dep, arr)
            map.get(key)?.push(flight)
        }
        return map
    })

    const entries = computed<ContinentPairEntry[]>(() =>
        allKeys.value.map(key => {
            const [a, b] = key.split('|')
            return { key, label: labelFor(a, b), flights: flightsByKey.value.get(key) ?? [] }
        })
    )

    const completedCount = computed(() => entries.value.filter(e => e.flights.length > 0).length)
    const totalCount = computed(() => entries.value.length)

    return { entries, completedCount, totalCount }
}

// ── Both-ways (directed) pairs ─────────────────────────────────────────────

export function useDirectedContinentPairs(
    flights: ComputedRef<Flight[]>,
    continents: ComputedRef<Continent[]>,
) {
    /** All directed keys grouped by the departure continent name */
    const keysByDeparture = computed<Map<string, string[]>>(() => {
        const names = continents.value.map(c => c.name).sort()
        const map = new Map<string, string[]>()
        for (const dep of names) {
            map.set(dep, names.map(arr => directedKey(dep, arr)).sort((a, b) => {
                const [, a2] = a.split('|')
                const [, b2] = b.split('|')
                return a2.localeCompare(b2)
            }))
        }
        return map
    })

    const flightsByKey = computed<Map<string, Flight[]>>(() => {
        const map = new Map<string, Flight[]>()
        for (const keys of keysByDeparture.value.values()) {
            for (const key of keys) map.set(key, [])
        }
        for (const flight of qualifyingFlights(flights.value)) {
            const dep = continentNameOf(flight, 'departure')!
            const arr = continentNameOf(flight, 'arrival')!
            const key = directedKey(dep, arr)
            map.get(key)?.push(flight)
        }
        return map
    })

    /** Entries grouped by departure continent, each sorted by arrival continent name */
    const entriesByDeparture = computed<Map<string, ContinentPairEntry[]>>(() => {
        const map = new Map<string, ContinentPairEntry[]>()
        for (const [dep, keys] of keysByDeparture.value) {
            map.set(dep, keys.map(key => {
                const [a, b] = key.split('|')
                return { key, label: `${a} → ${b}`, flights: flightsByKey.value.get(key) ?? [] }
            }))
        }
        return map
    })

    const departureNames = computed(() => [...keysByDeparture.value.keys()])

    const completedCount = computed(() => {
        let count = 0
        for (const entries of entriesByDeparture.value.values()) {
            count += entries.filter(e => e.flights.length > 0).length
        }
        return count
    })

    const totalCount = computed(() => {
        let count = 0
        for (const entries of entriesByDeparture.value.values()) {
            count += entries.length
        }
        return count
    })

    return { entriesByDeparture, departureNames, completedCount, totalCount }
}
