import { BookingPackageFlightMetaData } from '@qite/tide-client/build/types';
import { differenceInCalendarDays, format, parseISO } from 'date-fns';
import { compact, orderBy, uniq } from 'lodash';
import { FlightLine, RoomTraveler } from '../../types';

export const getTravelersText = (rooms: { adults: RoomTraveler[]; children: RoomTraveler[] }[], translations: any): string[] => {
  return rooms.map((r) =>
    compact([
      r.adults.length,
      r.adults.length === 1 && ` ${translations.SIDEBAR.TRAVELERS_ADULT}`,
      r.adults.length > 1 && ` ${translations.SIDEBAR.TRAVELERS_ADULTS}`,
      r.adults && r.adults.length && r.children && r.children.length && ', ',
      r.children.length,
      r.children.length === 1 && ` ${translations.SIDEBAR.TRAVELERS_CHILD}`,
      r.children.length > 1 && ` ${translations.SIDEBAR.TRAVELERS_CHILDREN}`
    ]).join('')
  );
};

export const getDateText = (date: string | undefined, hideYear?: boolean): string | undefined => {
  if (!date) {
    // No date set
    return undefined;
  }

  try {
    return hideYear ? format(parseISO(date), 'dd/MM') : format(parseISO(date), 'dd/MM/yyyy');
  } catch {
    // Error while parsing date
    return undefined;
  }
};

export const getDatePeriodText = (translations: Record<string, any>, from?: string, to?: string, nightsOnly?: boolean) => {
  if (!from || !to) {
    return undefined;
  }

  try {
    const fromDate = parseISO(from);
    const toDate = parseISO(to);

    const dayDifference = differenceInCalendarDays(toDate, fromDate);
    const daysLabel = dayDifference == 0 ? `1 ${translations.OPTIONS_FORM.DAY}` : `${dayDifference + 1} ${translations.OPTIONS_FORM.DAYS}`;

    if (!dayDifference) return daysLabel;

    const nightsLabel = dayDifference == 1 ? `1 ${translations.OPTIONS_FORM.NIGHT}` : `${dayDifference} ${translations.OPTIONS_FORM.NIGHTS}`;

    return nightsOnly ? nightsLabel : `${daysLabel}, ${nightsLabel}`;
  } catch {
    return undefined;
  }
};

export const getFlightText = (firstFlight: FlightLine | undefined, lastFlight: FlightLine | undefined): string => {
  return compact([
    firstFlight?.departureAirportDescription,
    ` (${firstFlight?.departureAirportIata})`,
    firstFlight?.departureAirportDescription && lastFlight?.arrivalAirportDescription && ' > ',
    lastFlight?.arrivalAirportDescription,
    ` (${lastFlight?.arrivalAirportIata})`
  ]).join('');
};

export const getAirlines = (flightLines: FlightLine[] | undefined) => {
  return uniq(flightLines?.filter((x) => x.airlineDescription)?.map((flightLine) => flightLine.airlineDescription)).join(', ');
};

export const getFlightHours = (firstFlight: FlightLine | undefined, lastFlight: FlightLine | undefined): string => {
  return compact([
    getDateText(firstFlight?.departureDate),
    ' ',
    firstFlight?.departureTime,
    ' > ',
    getDateText(lastFlight?.arrivalDate),
    ' ',
    lastFlight?.arrivalTime
  ]).join('');
};

export const parseFlightLines = (metaDatas: BookingPackageFlightMetaData): FlightLine[] | undefined => {
  if (!metaDatas.flightLines) {
    return undefined;
  }

  const parsedFlightLines: FlightLine[] = metaDatas.flightLines.map((parsedFlightLine) => {
    const departureDate = parseFlightLineDateTime(parsedFlightLine.departureDate, parsedFlightLine.departureTime);
    const arrivalDate = parseFlightLineDateTime(parsedFlightLine.arrivalDate, parsedFlightLine.arrivalTime);

    return <FlightLine>{
      departureAirportIata: parsedFlightLine.departureAirport,
      departureAirportDescription: parsedFlightLine.departureAirportDescription,
      departureDate: departureDate,
      departureTime: parsedFlightLine.departureTime,
      arrivalAirportIata: parsedFlightLine.arrivalAirport,
      arrivalAirportDescription: parsedFlightLine.arrivalAirportDescription,
      arrivalDate: arrivalDate,
      arrivalTime: parsedFlightLine.arrivalTime,
      airlineIata: parsedFlightLine.airline,
      airlineDescription: parsedFlightLine.operatingAirlineDescription,
      airlineNumber: parsedFlightLine.number,
      travelClass: parsedFlightLine.travelClass,
      number: parsedFlightLine.number,
      airlineCode: parsedFlightLine.airlineCode
    };
  });

  return orderBy(parsedFlightLines, 'departureDate', 'asc');
};

const parseFlightLineDateTime = (date: string, time: string): string | undefined => {
  try {
    // Parse date
    const parsedDate = parseISO(date);

    // Parse time
    const parsedTimeHours = parseInt(time.substring(0, 2));
    const parsedTimeMinutes = parseInt(time.substring(3, 5));

    if (!Number.isNaN(parsedTimeHours) && !Number.isNaN(parsedTimeMinutes)) {
      parsedDate.setUTCHours(parsedTimeHours, parsedTimeMinutes);
    }

    return parsedDate.toISOString().slice(0, -1);
  } catch {
    // Parsing failed
    return undefined;
  }
};

export const getPaxTypeTranslation = (translations: Record<string, any>, paxType: string, numberOfPax: number): string => {
  switch (paxType) {
    case 'ADULT':
      return numberOfPax === 1 ? translations.SIDEBAR.TRAVELERS_ADULT : translations.SIDEBAR.TRAVELERS_ADULTS;
    case 'CHILD':
      return numberOfPax === 1 ? translations.SIDEBAR.TRAVELERS_CHILD : translations.SIDEBAR.TRAVELERS_CHILDREN;
    case 'INFANT':
      return numberOfPax === 1 ? translations.SIDEBAR.TRAVELERS_INFANT : translations.SIDEBAR.TRAVELERS_INFANTS;
    default:
      return '';
  }
};
