import { BookingPackageFlightMetaData } from "@qite/tide-client/build/types";
import { differenceInCalendarDays, format, parseISO } from "date-fns";
import { compact, orderBy, uniq } from "lodash";
import { useSelector } from "react-redux";
import { FlightLine } from "../../types";
import { selectTranslations } from "../booking/selectors";

export const getTravelersText = (
  rooms: { adults: number[]; children: number[] }[]
): string[] => {
  const translations = useSelector(selectTranslations);

  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 = (
  from?: string,
  to?: string,
  nightsOnly?: boolean
) => {
  if (!from || !to) {
    return undefined;
  }

  const translations = useSelector(selectTranslations);  

  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,
      };
    }
  );

  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;
  }
};
