import { describe, it, expect } from "vitest";
import {
  OPERATOR_LOGO_PATHS,
  resolveCarrierByFlightNumber,
  resolveOperatorLogoPaths,
  pickLogoSrc,
} from "./operatorIcon.js";

// ---------------------------------------------------------------------------
// OPERATOR_LOGO_PATHS — 35-carrier table assertions (TZ §4.1.22, Таблица 67)
// ---------------------------------------------------------------------------
describe("OPERATOR_LOGO_PATHS", () => {
  const REQUIRED_TZ_CARRIERS = [
    "FV", // Россия
    "SU", // Аэрофлот
    "HZ", // Аврора
    "RO", // TAROM
    "DP", // Pobeda
    "OM", // MIAT
    "KL", // KLM
    "AY", // Finnair
    "DL", // Delta
    "OK", // Czech Airline
    "JU", // Air Serbia
    "UX", // Air Europa
    "BT", // Air Baltic
    "AM", // Aeromexico
    "AR", // Aerolíneas Argentinas
    "KM", // Airmalta
    "AF", // Airfrance
    "AZ", // Alitalia
    "PG", // Bangkok Airways
    "SN", // Brussels Airlines
    "FB", // Bulgaria Air
    "CI", // China Airlines
    "MU", // China Eastern
    "CZ", // China Southern
    "GA", // Garuda Indonesia
    "FI", // Icelandair
    "KO", // Kenya Airways
    "KE", // Korean Air
    "JL", // Japan Airlines
    "LO", // LOT Polish Airlines
    "ME", // Middle East Airlines
    "S7", // S7
    "SV", // Saudi Arabian Airlines
    "VN", // Vietnam Airlines
    "MF", // XiamenAir
  ] as const;

  it("contains all 35 TZ carriers", () => {
    for (const code of REQUIRED_TZ_CARRIERS) {
      expect(OPERATOR_LOGO_PATHS).toHaveProperty(code);
    }
  });

  it("has at least one asset path for every carrier", () => {
    for (const [code, paths] of Object.entries(OPERATOR_LOGO_PATHS)) {
      expect(paths.en, `${code}.en must be defined`).toBeTruthy();
    }
  });

  it("SU has ru + round variants", () => {
    expect(OPERATOR_LOGO_PATHS["SU"]!.ru).toBeTruthy();
    expect(OPERATOR_LOGO_PATHS["SU"]!.round).toBeTruthy();
  });

  it("FV has ru + round variants", () => {
    expect(OPERATOR_LOGO_PATHS["FV"]!.ru).toBeTruthy();
    expect(OPERATOR_LOGO_PATHS["FV"]!.round).toBeTruthy();
  });

  it("HZ has ru + round variants", () => {
    expect(OPERATOR_LOGO_PATHS["HZ"]!.ru).toBeTruthy();
    expect(OPERATOR_LOGO_PATHS["HZ"]!.round).toBeTruthy();
  });

  it("RO has round variant", () => {
    expect(OPERATOR_LOGO_PATHS["RO"]!.round).toBeTruthy();
  });

  it("DP has round variant", () => {
    expect(OPERATOR_LOGO_PATHS["DP"]!.round).toBeTruthy();
  });

  // KM, AF, AZ, PG, SN, FB, CI, MU, CZ, GA, FI, KO, KE, JL, LO, ME, S7,
  // SV, MF, VN — TZ specifies only the wide logo (no round column entry).
  it.each(["KM", "AF", "AZ", "PG", "SN", "FB", "CI", "MU", "CZ", "GA",
            "FI", "KO", "KE", "JL", "LO", "ME", "S7", "SV", "MF", "VN"])(
    "%s has en path but no round (per TZ table)",
    (code) => {
      const p = OPERATOR_LOGO_PATHS[code];
      expect(p?.en).toBeTruthy();
      expect(p?.round).toBeUndefined();
    },
  );
});

// ---------------------------------------------------------------------------
// resolveCarrierByFlightNumber — TZ §4.1.22 range fallback
// ---------------------------------------------------------------------------
describe("resolveCarrierByFlightNumber", () => {
  const cases: Array<[string | number, string | null]> = [
    // SU1–2999 → SU
    [1, "SU"],
    [1000, "SU"],
    [2999, "SU"],
    // SU3000–4999 → null (no icon)
    [3000, null],
    [4000, null],
    [4999, null],
    // SU5000–5399 → DP (Pobeda)
    [5000, "DP"],
    [5200, "DP"],
    [5399, "DP"],
    // SU5400–5799 → HZ (Aurora)
    [5400, "HZ"],
    [5600, "HZ"],
    [5799, "HZ"],
    // SU5800–5999 → null (no icon)
    [5800, null],
    [5999, null],
    // SU6000–6999 → FV (Rossiya)
    [6000, "FV"],
    [6500, "FV"],
    [6999, "FV"],
    // SU7000–9999 → SU
    [7000, "SU"],
    [9000, "SU"],
    [9999, "SU"],
    // Out of all ranges
    [0, null],
    [10000, null],
    // Non-numeric
    ["abc", null],
    // Numeric string
    ["1234", "SU"],
    ["6100", "FV"],
  ];

  it.each(cases)(
    "flight %s → carrier %s",
    (flightNumber, expected) => {
      expect(resolveCarrierByFlightNumber(flightNumber)).toBe(expected);
    },
  );
});

// ---------------------------------------------------------------------------
// resolveOperatorLogoPaths
// ---------------------------------------------------------------------------
describe("resolveOperatorLogoPaths", () => {
  it("returns paths for known carrier", () => {
    const p = resolveOperatorLogoPaths("SU");
    expect(p).not.toBeNull();
    expect(p?.en).toContain("aeroflot");
  });

  it("returns null for unknown carrier", () => {
    expect(resolveOperatorLogoPaths("XX")).toBeNull();
  });

  it("returns null for null input", () => {
    expect(resolveOperatorLogoPaths(null)).toBeNull();
  });

  it("returns null for undefined input", () => {
    expect(resolveOperatorLogoPaths(undefined)).toBeNull();
  });

  it("returns null for empty string", () => {
    expect(resolveOperatorLogoPaths("")).toBeNull();
  });
});

// ---------------------------------------------------------------------------
// pickLogoSrc
// ---------------------------------------------------------------------------
describe("pickLogoSrc", () => {
  // SU is a known entry — assert non-null so TS knows the type is OperatorIconPaths.
  const suPaths = OPERATOR_LOGO_PATHS["SU"]!;

  it("returns en path for en locale", () => {
    expect(pickLogoSrc(suPaths, "en", false)).toBe(suPaths.en);
  });

  it("returns ru path for ru locale", () => {
    expect(pickLogoSrc(suPaths, "ru", false)).toBe(suPaths.ru);
  });

  it("returns ru path for ru-RU BCP-47 locale", () => {
    expect(pickLogoSrc(suPaths, "ru-RU", false)).toBe(suPaths.ru);
  });

  it("returns round path when round=true and round path exists", () => {
    expect(pickLogoSrc(suPaths, "en", true)).toBe(suPaths.round);
  });

  it("falls back to en when round=true but round path absent", () => {
    const noRound = { en: "/some/logo.svg" };
    expect(pickLogoSrc(noRound, "en", true)).toBe("/some/logo.svg");
  });

  it("falls back to en when ru requested but ru path absent", () => {
    const noRu = { en: "/some/logo.svg" };
    expect(pickLogoSrc(noRu, "ru", false)).toBe("/some/logo.svg");
  });
});
