import { describe, expect, it } from "vitest";
import {
  buildOnlineBoardStartSeo,
  buildFlightSearchSeo,
  buildDepartureSearchSeo,
  buildArrivalSearchSeo,
  buildRouteSearchSeo,
  buildFlightDetailsSeo,
} from "./seo.js";
import type { ISimpleFlight } from "./types.js";

/** Stub t() that returns the key + interpolation vars for assertion. */
function stubT(key: string, opts?: Record<string, unknown>): string {
  if (opts && Object.keys(opts).length > 0) {
    const vars = Object.entries(opts)
      .map(([k, v]) => `${k}=${v}`)
      .join(",");
    return `${key}|${vars}`;
  }
  return key;
}

const CANONICAL = "https://www.aeroflot.ru";

describe("buildOnlineBoardStartSeo", () => {
  it("uses MAIN translation keys for title and description", () => {
    const result = buildOnlineBoardStartSeo(stubT, "ru", CANONICAL);

    expect(result.title).toBe("SEO.BOARD.MAIN.TITLE");
    expect(result.description).toBe("SEO.BOARD.MAIN.DESCRIPTION");
  });

  it("sets canonical to /{locale}/onlineboard", () => {
    const result = buildOnlineBoardStartSeo(stubT, "en", CANONICAL);

    expect(result.canonical).toBe("https://www.aeroflot.ru/en/onlineboard");
  });

  it("includes hreflang with 10 entries (9 langs + x-default)", () => {
    const result = buildOnlineBoardStartSeo(stubT, "ru", CANONICAL);

    expect(result.hreflang).toHaveLength(10);
  });

  it("sets og tags", () => {
    const result = buildOnlineBoardStartSeo(stubT, "ru", CANONICAL);

    expect(result.og.title).toBe(result.title);
    expect(result.og.description).toBe(result.description);
    expect(result.og.url).toBe(result.canonical);
    expect(result.og.type).toBe("website");
    expect(result.og.locale).toBe("ru");
    expect(result.og.siteName).toBe("Aeroflot");
    expect(result.og.image).toContain("aeroflot");
  });

  it("sets twitter card", () => {
    const result = buildOnlineBoardStartSeo(stubT, "ru", CANONICAL);

    expect(result.twitter).toBeDefined();
    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- test assertion guards above
    expect(result.twitter!.card).toBe("summary");
  });
});

describe("buildFlightSearchSeo", () => {
  const params = {
    type: "flight" as const,
    carrier: "SU",
    flightNumber: "0100",
    date: "20250115",
  };

  it("uses FLIGHT-SEARCH translation keys with interpolation", () => {
    const result = buildFlightSearchSeo(stubT, params, "ru", CANONICAL);

    expect(result.title).toContain("SEO.BOARD.FLIGHT-SEARCH.TITLE");
    expect(result.title).toContain("flightNumber=SU 0100");
    expect(result.description).toContain("SEO.BOARD.FLIGHT-SEARCH.DESCRIPTION");
  });

  it("sets canonical to the flight search URL", () => {
    const result = buildFlightSearchSeo(stubT, params, "ru", CANONICAL);

    expect(result.canonical).toBe(
      "https://www.aeroflot.ru/ru/onlineboard/flight/SU0100-20250115",
    );
  });

  it("includes hreflang entries", () => {
    const result = buildFlightSearchSeo(stubT, params, "ru", CANONICAL);

    expect(result.hreflang).toHaveLength(10);
  });
});

describe("buildDepartureSearchSeo", () => {
  const params = {
    type: "departure" as const,
    station: "SVO",
    date: "20250115",
  };

  it("uses DEPARTURE-SEARCH translation keys with city name", () => {
    const result = buildDepartureSearchSeo(
      stubT,
      params,
      "ru",
      CANONICAL,
      { departure: "Moscow" },
    );

    expect(result.title).toContain("SEO.BOARD.DEPARTURE-SEARCH.TITLE");
    expect(result.title).toContain("departureCity=Moscow");
  });

  it("falls back to station code when no city name provided", () => {
    const result = buildDepartureSearchSeo(stubT, params, "ru", CANONICAL);

    expect(result.title).toContain("departureCity=SVO");
  });

  it("sets canonical to the departure search URL", () => {
    const result = buildDepartureSearchSeo(stubT, params, "en", CANONICAL);

    expect(result.canonical).toBe(
      "https://www.aeroflot.ru/en/onlineboard/departure/SVO-20250115",
    );
  });
});

describe("buildArrivalSearchSeo", () => {
  const params = {
    type: "arrival" as const,
    station: "JFK",
    date: "20250115",
  };

  it("uses ARRIVAL-SEARCH translation keys with city name", () => {
    const result = buildArrivalSearchSeo(
      stubT,
      params,
      "ru",
      CANONICAL,
      { arrival: "New York" },
    );

    expect(result.title).toContain("SEO.BOARD.ARRIVAL-SEARCH.TITLE");
    expect(result.title).toContain("arrivalCity=New York");
  });

  it("falls back to station code when no city name provided", () => {
    const result = buildArrivalSearchSeo(stubT, params, "ru", CANONICAL);

    expect(result.title).toContain("arrivalCity=JFK");
  });

  it("sets canonical to the arrival search URL", () => {
    const result = buildArrivalSearchSeo(stubT, params, "ru", CANONICAL);

    expect(result.canonical).toBe(
      "https://www.aeroflot.ru/ru/onlineboard/arrival/JFK-20250115",
    );
  });
});

describe("buildRouteSearchSeo", () => {
  const params = {
    type: "route" as const,
    departure: "SVO",
    arrival: "JFK",
    date: "20250115",
  };

  it("uses ROUTE-SEARCH translation keys with both city names", () => {
    const result = buildRouteSearchSeo(
      stubT,
      params,
      "ru",
      CANONICAL,
      { departure: "Moscow", arrival: "New York" },
    );

    expect(result.title).toContain("SEO.BOARD.ROUTE-SEARCH.TITLE");
    expect(result.title).toContain("departureCity=Moscow");
    expect(result.title).toContain("arrivalCity=New York");
  });

  it("falls back to IATA codes when no city names provided", () => {
    const result = buildRouteSearchSeo(stubT, params, "ru", CANONICAL);

    expect(result.title).toContain("departureCity=SVO");
    expect(result.title).toContain("arrivalCity=JFK");
  });

  it("sets canonical to the route search URL", () => {
    const result = buildRouteSearchSeo(stubT, params, "en", CANONICAL);

    expect(result.canonical).toBe(
      "https://www.aeroflot.ru/en/onlineboard/route/SVO-JFK-20250115",
    );
  });
});

describe("buildFlightDetailsSeo", () => {
  const flight: ISimpleFlight = {
    id: "SU100-20250115",
    routeType: "Direct",
    flightId: {
      carrier: "SU",
      flightNumber: "0100",
      suffix: "",
      date: "20250115",
    },
    flyingTime: "10h 30m",
    operatingBy: {},
    status: "Scheduled",
    leg: {
      index: 0,
      status: "Scheduled",
      flyingTime: "10h 30m",
      updated: "2025-01-15T10:00:00Z",
      dayChange: 0,
      equipment: { name: "Boeing 777-300ER", code: "773" },
      flags: { checkinAvailable: false, returnToAirport: false, routeChanged: false },
      operatingBy: {},
      departure: {
        scheduled: {
          airport: "Sheremetyevo International Airport",
          airportCode: "SVO",
          city: "Moscow",
          cityCode: "MOW",
          countryCode: "RU",
        },
        checkingStatus: "closed",
        times: {
          scheduledDeparture: {
            dayChange: { value: 0, title: "" },
            local: "2025-01-15T10:00:00",
            localTime: "10:00",
            tzOffset: 3,
            utc: "2025-01-15T07:00:00Z",
          },
        },
      },
      arrival: {
        scheduled: {
          airport: "John F. Kennedy International Airport",
          airportCode: "JFK",
          city: "New York",
          cityCode: "NYC",
          countryCode: "US",
        },
        times: {
          scheduledArrival: {
            dayChange: { value: 0, title: "" },
            local: "2025-01-15T14:30:00",
            localTime: "14:30",
            tzOffset: -5,
            utc: "2025-01-15T19:30:00Z",
          },
        },
      },
    },
  };

  it("uses FLIGHT-DETAILS translation keys", () => {
    const result = buildFlightDetailsSeo(stubT, flight, "ru", CANONICAL);

    expect(result.title).toContain("SEO.BOARD.FLIGHT-DETAILS.TITLE");
    expect(result.title).toContain("flightNumber=SU 0100");
  });

  it("sets canonical to the details URL", () => {
    const result = buildFlightDetailsSeo(stubT, flight, "ru", CANONICAL);

    expect(result.canonical).toBe(
      "https://www.aeroflot.ru/ru/onlineboard/SU0100-20250115",
    );
  });

  it("includes hreflang entries", () => {
    const result = buildFlightDetailsSeo(stubT, flight, "ru", CANONICAL);

    expect(result.hreflang).toHaveLength(10);
  });

  it("sets og.type to article for details pages", () => {
    const result = buildFlightDetailsSeo(stubT, flight, "ru", CANONICAL);

    expect(result.og.type).toBe("article");
  });
});
