import { describe, it, expect } from "vitest";
import { filterRoutes } from "./filterRoutes.js";
import { transformDictionaries } from "@/shared/dictionaries/index.js";
import type { IFlightRoute, IFlightsMapFilterState } from "./types.js";
import type { IDictionaries, IRawDictionaries } from "@/shared/dictionaries/index.js";

const raw: IRawDictionaries = {
  regions: [],
  countries: [
    { code: "RU", title: { ru: "Россия" }, world_region_id: 500374 },
    { code: "US", title: { ru: "США" }, world_region_id: 1 },
  ],
  cities: [
    { code: "MOW", title: { ru: "Москва" }, country_code: "RU", has_afl_flights: true, location: { lat: 55, lon: 37 } },
    { code: "LED", title: { ru: "Санкт-Петербург" }, country_code: "RU", has_afl_flights: true, location: { lat: 60, lon: 30 } },
    { code: "AER", title: { ru: "Сочи" }, country_code: "RU", has_afl_flights: true, location: { lat: 43, lon: 39 } },
    { code: "NYC", title: { ru: "Нью-Йорк" }, country_code: "US", has_afl_flights: true, location: { lat: 40, lon: -74 } },
  ],
  airports: [
    { code: "SVO", city_code: "MOW", title: { ru: "Шереметьево" }, has_afl_flights: true, location: { lat: 55, lon: 37 } },
    { code: "JFK", city_code: "NYC", title: { ru: "Джон Кеннеди" }, has_afl_flights: true, location: { lat: 40, lon: -74 } },
    { code: "LED", city_code: "LED", title: { ru: "Пулково" }, has_afl_flights: true, location: { lat: 60, lon: 30 } },
    { code: "AER", city_code: "AER", title: { ru: "Сочи" }, has_afl_flights: true, location: { lat: 43, lon: 39 } },
  ],
};

const d: IDictionaries = transformDictionaries(raw, "ru");

function filter(
  overrides: Partial<IFlightsMapFilterState> = {},
): IFlightsMapFilterState {
  return {
    connections: false,
    domestic: false,
    international: false,
    ...overrides,
  };
}

describe("filterRoutes — empty and passthrough", () => {
  it("returns [] for no routes", () => {
    expect(filterRoutes([], filter(), d)).toEqual([]);
  });

  it("returns routes unchanged when no toggles are active", () => {
    const routes: IFlightRoute[] = [
      { route: ["MOW", "LED"], isDirect: true },
      { route: ["MOW", "NYC"], isDirect: true },
    ];
    expect(filterRoutes(routes, filter(), d)).toEqual(routes);
  });
});

describe("filterRoutes — domestic", () => {
  it("keeps only routes where every city is RU", () => {
    const routes: IFlightRoute[] = [
      { route: ["MOW", "LED"], isDirect: true },
      { route: ["MOW", "NYC"], isDirect: true },
    ];
    const out = filterRoutes(routes, filter({ domestic: true }), d);
    expect(out).toHaveLength(1);
    expect(out[0]!.route).toEqual(["MOW", "LED"]);
  });
});

describe("filterRoutes — international", () => {
  it("keeps only routes with at least one non-RU city", () => {
    const routes: IFlightRoute[] = [
      { route: ["MOW", "LED"], isDirect: true },
      { route: ["MOW", "NYC"], isDirect: true },
    ];
    const out = filterRoutes(routes, filter({ international: true }), d);
    expect(out).toHaveLength(1);
    expect(out[0]!.route).toEqual(["MOW", "NYC"]);
  });
});

describe("filterRoutes — both domestic AND international", () => {
  it("applies no domestic/intl filter when both are true", () => {
    const routes: IFlightRoute[] = [
      { route: ["MOW", "LED"], isDirect: true },
      { route: ["MOW", "NYC"], isDirect: true },
    ];
    const out = filterRoutes(
      routes,
      filter({ domestic: true, international: true }),
      d,
    );
    expect(out).toEqual(routes);
  });
});

describe("filterRoutes — connections", () => {
  it("keeps only non-direct routes", () => {
    const routes: IFlightRoute[] = [
      { route: ["MOW", "LED"], isDirect: true },
      { route: ["MOW", "X", "LED"], isDirect: false },
    ];
    const out = filterRoutes(routes, filter({ connections: true }), d);
    expect(out).toHaveLength(1);
    expect(out[0]!.route).toEqual(["MOW", "X", "LED"]);
  });
});

describe("filterRoutes — airport-code normalization", () => {
  it("treats airport codes (SVO, JFK) as their city codes (MOW, NYC)", () => {
    const routes: IFlightRoute[] = [
      { route: ["SVO", "JFK"], isDirect: true },
      { route: ["SVO", "LED"], isDirect: true },
    ];
    const intl = filterRoutes(routes, filter({ international: true }), d);
    expect(intl).toHaveLength(1);
    expect(intl[0]!.route).toEqual(["SVO", "JFK"]);

    const dom = filterRoutes(routes, filter({ domestic: true }), d);
    expect(dom).toHaveLength(1);
    expect(dom[0]!.route).toEqual(["SVO", "LED"]);
  });

  it("drops routes containing unknown codes when any toggle is active", () => {
    const routes: IFlightRoute[] = [{ route: ["MOW", "???"], isDirect: true }];
    expect(filterRoutes(routes, filter({ domestic: true }), d)).toEqual([]);
    expect(filterRoutes(routes, filter({ international: true }), d)).toEqual([]);
  });
});

describe("filterRoutes — combo", () => {
  it("applies domestic + connections together", () => {
    const routes: IFlightRoute[] = [
      { route: ["MOW", "LED"], isDirect: true },
      { route: ["MOW", "AER", "LED"], isDirect: false },
      { route: ["MOW", "NYC"], isDirect: false },
    ];
    const out = filterRoutes(
      routes,
      filter({ domestic: true, connections: true }),
      d,
    );
    expect(out).toHaveLength(1);
    expect(out[0]!.route).toEqual(["MOW", "AER", "LED"]);
  });
});
