import { Flight, Journey, Layover, LayoverRiskLevel } from '@/types';

function getEffectiveArrival(flight: Flight): Date | null {
  const t = flight.actualArrival || flight.estimatedArrival || flight.scheduledArrival;
  return t ? new Date(t) : null;
}

function getEffectiveDeparture(flight: Flight): Date | null {
  const t = flight.actualDeparture || flight.estimatedDeparture || flight.scheduledDeparture;
  return t ? new Date(t) : null;
}

function computeLayoverRisk(effectiveMinutes: number, scheduledMinutes: number): LayoverRiskLevel {
  if (effectiveMinutes < 0) return 'missed';
  if (effectiveMinutes < 30) return 'critical';
  if (effectiveMinutes < 60) return 'warning';
  if (scheduledMinutes > 0) return 'ok';
  return 'none';
}

function computeLayover(arriving: Flight, departing: Flight, index: number): Layover {
  const scheduledArr = arriving.scheduledArrival ? new Date(arriving.scheduledArrival) : null;
  const scheduledDep = departing.scheduledDeparture ? new Date(departing.scheduledDeparture) : null;
  const effectiveArr = getEffectiveArrival(arriving);
  const effectiveDep = getEffectiveDeparture(departing);

  const scheduledMinutes = scheduledArr && scheduledDep
    ? (scheduledDep.getTime() - scheduledArr.getTime()) / 60000
    : 0;

  const effectiveMinutes = effectiveArr && effectiveDep
    ? (effectiveDep.getTime() - effectiveArr.getTime()) / 60000
    : scheduledMinutes;

  return {
    airport: arriving.arrivalAirport,
    afterSegmentIndex: index,
    scheduledMinutes: Math.round(scheduledMinutes),
    effectiveMinutes: Math.round(effectiveMinutes),
    risk: computeLayoverRisk(effectiveMinutes, scheduledMinutes),
  };
}

function computeEffectiveStatus(flights: Flight[]): { effectiveStatus: string; currentSegmentIndex: number } {
  // Critical statuses on any segment take priority
  for (let i = 0; i < flights.length; i++) {
    const s = flights[i].status?.toLowerCase();
    if (s === 'cancelled' || s === 'diverted' || s === 'incident') {
      return { effectiveStatus: s, currentSegmentIndex: i };
    }
  }

  // Find first non-terminal segment (the "active" one)
  for (let i = 0; i < flights.length; i++) {
    const s = flights[i].status?.toLowerCase();
    const isTerminal = s === 'landed' || !!flights[i].actualArrival;
    if (!isTerminal) {
      return { effectiveStatus: s || 'scheduled', currentSegmentIndex: i };
    }
  }

  // All segments landed
  const last = flights.length - 1;
  return { effectiveStatus: flights[last].status?.toLowerCase() || 'landed', currentSegmentIndex: last };
}

export function groupFlightsIntoJourneys(flights: Flight[]): Journey[] {
  const byVip = new Map<string, Flight[]>();
  for (const flight of flights) {
    const group = byVip.get(flight.vipId) || [];
    group.push(flight);
    byVip.set(flight.vipId, group);
  }

  const journeys: Journey[] = [];

  for (const [vipId, vipFlights] of byVip) {
    // Sort chronologically by departure time, then segment as tiebreaker
    const sorted = [...vipFlights].sort((a, b) => {
      const depA = a.scheduledDeparture || a.flightDate;
      const depB = b.scheduledDeparture || b.flightDate;
      const timeDiff = new Date(depA).getTime() - new Date(depB).getTime();
      if (timeDiff !== 0) return timeDiff;
      return a.segment - b.segment;
    });

    const layovers: Layover[] = [];
    for (let i = 0; i < sorted.length - 1; i++) {
      layovers.push(computeLayover(sorted[i], sorted[i + 1], i));
    }

    const { effectiveStatus, currentSegmentIndex } = computeEffectiveStatus(sorted);

    journeys.push({
      vipId,
      vip: sorted[0]?.vip,
      flights: sorted,
      layovers,
      effectiveStatus,
      currentSegmentIndex,
      hasLayoverRisk: layovers.some(l => l.risk === 'warning' || l.risk === 'critical' || l.risk === 'missed'),
      origin: sorted[0]?.departureAirport,
      destination: sorted[sorted.length - 1]?.arrivalAirport,
      isMultiSegment: sorted.length > 1,
    });
  }

  return journeys;
}

export function formatLayoverDuration(minutes: number): string {
  if (minutes < 0) return `${Math.abs(minutes)}min late`;
  const h = Math.floor(minutes / 60);
  const m = minutes % 60;
  if (h === 0) return `${m}min`;
  if (m === 0) return `${h}h`;
  return `${h}h ${m}min`;
}
