import { describe, expect, it } from "vitest";
import type { Flight, ItemList } from "schema-dts";
import { buildScheduleFlightJsonLd, buildScheduleFlightListJsonLd } from "./json-ld.js";
import type { ISimpleFlight } from "./types.js";

function makeDirectFlight(overrides: Partial<{
  carrier: string;
  flightNumber: string;
  depCode: string;
  depAirport: string;
  arrCode: string;
  arrAirport: string;
  depTime: string;
  arrTime: string;
}> = {}): ISimpleFlight {
  return {
    id: "test-schedule-1",
    routeType: "Direct",
    flightId: {
      carrier: overrides.carrier ?? "SU",
      flightNumber: overrides.flightNumber ?? "0012",
      suffix: "",
      date: "20220527",
    },
    flyingTime: "1h 30m",
    operatingBy: {},
    status: "Scheduled",
    leg: {
      index: 0,
      status: "Scheduled",
      flyingTime: "1h 30m",
      updated: "2022-05-27T10:00:00Z",
      dayChange: 0,
      equipment: { name: "Airbus A320", code: "320" },
      flags: { checkinAvailable: false, returnToAirport: false, routeChanged: false },
      operatingBy: {},
      departure: {
        scheduled: {
          airport: overrides.depAirport ?? "Sheremetyevo",
          airportCode: overrides.depCode ?? "SVO",
          city: "Moscow",
          cityCode: "MOW",
          countryCode: "RU",
        },
        checkingStatus: "closed",
        times: {
          scheduledDeparture: {
            dayChange: { value: 0, title: "" },
            local: overrides.depTime ?? "2022-05-27T10:00:00",
            localTime: "10:00",
            tzOffset: 3,
            utc: "2022-05-27T07:00:00Z",
          },
        },
      },
      arrival: {
        scheduled: {
          airport: overrides.arrAirport ?? "Pulkovo",
          airportCode: overrides.arrCode ?? "LED",
          city: "Saint Petersburg",
          cityCode: "LED",
          countryCode: "RU",
        },
        times: {
          scheduledArrival: {
            dayChange: { value: 0, title: "" },
            local: overrides.arrTime ?? "2022-05-27T11:30:00",
            localTime: "11:30",
            tzOffset: 3,
            utc: "2022-05-27T08:30:00Z",
          },
        },
      },
    },
  };
}

describe("buildScheduleFlightJsonLd", () => {
  it("returns a Flight schema with correct @type", () => {
    const flight = makeDirectFlight();
    const result = buildScheduleFlightJsonLd(flight);

    expect(result["@type"]).toBe("Flight");
  });

  it("sets flightNumber in IATA format", () => {
    const flight = makeDirectFlight({ carrier: "SU", flightNumber: "0012" });
    const result = buildScheduleFlightJsonLd(flight);

    expect(result.flightNumber).toBe("SU0012");
  });

  it("maps departure airport", () => {
    const flight = makeDirectFlight({ depCode: "SVO", depAirport: "Sheremetyevo" });
    const result = buildScheduleFlightJsonLd(flight);

    expect(result.departureAirport).toEqual({
      "@type": "Airport",
      iataCode: "SVO",
      name: "Sheremetyevo",
    });
  });

  it("maps arrival airport", () => {
    const flight = makeDirectFlight({ arrCode: "LED", arrAirport: "Pulkovo" });
    const result = buildScheduleFlightJsonLd(flight);

    expect(result.arrivalAirport).toEqual({
      "@type": "Airport",
      iataCode: "LED",
      name: "Pulkovo",
    });
  });

  it("is type-compatible with schema-dts Flight", () => {
    const flight = makeDirectFlight();
    const result = buildScheduleFlightJsonLd(flight);
    const _typed: Flight = result;
    expect(_typed["@type"]).toBe("Flight");
  });
});

describe("buildScheduleFlightListJsonLd", () => {
  it("returns an ItemList schema", () => {
    const flights = [makeDirectFlight()];
    const result = buildScheduleFlightListJsonLd(flights, "Schedule SVO to LED");

    expect(result["@type"]).toBe("ItemList");
  });

  it("sets the description", () => {
    const flights = [makeDirectFlight()];
    const result = buildScheduleFlightListJsonLd(flights, "Schedule SVO to LED");

    expect(result.description).toBe("Schedule SVO to LED");
  });

  it("wraps each flight as a ListItem with position", () => {
    const flights = [
      makeDirectFlight({ carrier: "SU", flightNumber: "0012" }),
      makeDirectFlight({ carrier: "SU", flightNumber: "0013" }),
    ];
    const result = buildScheduleFlightListJsonLd(flights, "Flights");
    const items = result.itemListElement as unknown as Array<{ position: number }>;

    expect(Array.isArray(items)).toBe(true);
    expect(items).toHaveLength(2);
    expect(items[0]).toHaveProperty("position", 1);
    expect(items[1]).toHaveProperty("position", 2);
  });

  it("handles empty flight list", () => {
    const result = buildScheduleFlightListJsonLd([], "No flights");

    expect(result["@type"]).toBe("ItemList");
    expect(result.itemListElement).toEqual([]);
  });

  it("is type-compatible with schema-dts ItemList", () => {
    const result = buildScheduleFlightListJsonLd([], "test");
    const _typed: ItemList = result;
    expect(_typed["@type"]).toBe("ItemList");
  });
});
