import { describe, it, expect } from "vitest";
import {
  parseScheduleRouteParams,
  buildScheduleRouteParams,
  parseScheduleUrl,
  buildScheduleUrl,
  type ScheduleParams,
} from "./url";

// ---------------------------------------------------------------------------
// parseScheduleRouteParams
// ---------------------------------------------------------------------------

describe("parseScheduleRouteParams", () => {
  it("parses route without time range or connections", () => {
    expect(parseScheduleRouteParams("MOW-KUF-20220425-20220501")).toEqual({
      departure: "MOW",
      arrival: "KUF",
      dateFrom: "20220425",
      dateTo: "20220501",
    });
  });

  it("parses route with time range", () => {
    expect(parseScheduleRouteParams("MOW-KUF-20220425-20220501-06002200")).toEqual({
      departure: "MOW",
      arrival: "KUF",
      dateFrom: "20220425",
      dateTo: "20220501",
      timeFrom: "0600",
      timeTo: "2200",
    });
  });

  it("parses route with connections only", () => {
    expect(parseScheduleRouteParams("MOW-KUF-20220425-20220501-C1")).toEqual({
      departure: "MOW",
      arrival: "KUF",
      dateFrom: "20220425",
      dateTo: "20220501",
      connections: 1,
    });
  });

  it("parses route with connections=0", () => {
    expect(parseScheduleRouteParams("MOW-KUF-20220425-20220501-C0")).toEqual({
      departure: "MOW",
      arrival: "KUF",
      dateFrom: "20220425",
      dateTo: "20220501",
      connections: 0,
    });
  });

  it("parses route with time range and connections", () => {
    expect(parseScheduleRouteParams("MOW-KUF-20220425-20220501-06002200-C0")).toEqual({
      departure: "MOW",
      arrival: "KUF",
      dateFrom: "20220425",
      dateTo: "20220501",
      timeFrom: "0600",
      timeTo: "2200",
      connections: 0,
    });
  });

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

  it("returns null for insufficient segments", () => {
    expect(parseScheduleRouteParams("MOW-KUF-20220425")).toBeNull();
  });

  it("returns null for invalid dateFrom", () => {
    expect(parseScheduleRouteParams("MOW-KUF-2022-20220501")).toBeNull();
  });

  it("returns null for invalid dateTo", () => {
    expect(parseScheduleRouteParams("MOW-KUF-20220425-2022")).toBeNull();
  });
});

// ---------------------------------------------------------------------------
// buildScheduleRouteParams
// ---------------------------------------------------------------------------

describe("buildScheduleRouteParams", () => {
  it("builds route without time range or connections", () => {
    expect(buildScheduleRouteParams({
      departure: "MOW",
      arrival: "KUF",
      dateFrom: "20220425",
      dateTo: "20220501",
    })).toBe("MOW-KUF-20220425-20220501");
  });

  it("builds route with time range", () => {
    expect(buildScheduleRouteParams({
      departure: "MOW",
      arrival: "KUF",
      dateFrom: "20220425",
      dateTo: "20220501",
      timeFrom: "0600",
      timeTo: "2200",
    })).toBe("MOW-KUF-20220425-20220501-06002200");
  });

  it("builds route with connections", () => {
    expect(buildScheduleRouteParams({
      departure: "MOW",
      arrival: "KUF",
      dateFrom: "20220425",
      dateTo: "20220501",
      connections: 1,
    })).toBe("MOW-KUF-20220425-20220501-C1");
  });

  it("builds route with connections=0", () => {
    expect(buildScheduleRouteParams({
      departure: "MOW",
      arrival: "KUF",
      dateFrom: "20220425",
      dateTo: "20220501",
      connections: 0,
    })).toBe("MOW-KUF-20220425-20220501-C0");
  });

  it("builds route with time range and connections", () => {
    expect(buildScheduleRouteParams({
      departure: "MOW",
      arrival: "KUF",
      dateFrom: "20220425",
      dateTo: "20220501",
      timeFrom: "0600",
      timeTo: "2200",
      connections: 0,
    })).toBe("MOW-KUF-20220425-20220501-06002200-C0");
  });

  it("omits time range when only timeFrom is provided", () => {
    expect(buildScheduleRouteParams({
      departure: "MOW",
      arrival: "KUF",
      dateFrom: "20220425",
      dateTo: "20220501",
      timeFrom: "0600",
    })).toBe("MOW-KUF-20220425-20220501");
  });
});

// ---------------------------------------------------------------------------
// parseScheduleUrl
// ---------------------------------------------------------------------------

describe("parseScheduleUrl", () => {
  it("parses start page (no trailing slash)", () => {
    expect(parseScheduleUrl("/schedule")).toEqual({ type: "start" });
  });

  it("parses start page (with trailing slash)", () => {
    expect(parseScheduleUrl("/schedule/")).toEqual({ type: "start" });
  });

  it("parses one-way route search", () => {
    expect(parseScheduleUrl("/schedule/route/MOW-KUF-20220425-20220501")).toEqual({
      type: "route",
      outbound: {
        departure: "MOW",
        arrival: "KUF",
        dateFrom: "20220425",
        dateTo: "20220501",
      },
    });
  });

  it("parses one-way route with time range", () => {
    expect(parseScheduleUrl("/schedule/route/MOW-KUF-20220425-20220501-06002200")).toEqual({
      type: "route",
      outbound: {
        departure: "MOW",
        arrival: "KUF",
        dateFrom: "20220425",
        dateTo: "20220501",
        timeFrom: "0600",
        timeTo: "2200",
      },
    });
  });

  it("parses one-way route with connections", () => {
    expect(parseScheduleUrl("/schedule/route/MOW-KUF-20220425-20220501-C1")).toEqual({
      type: "route",
      outbound: {
        departure: "MOW",
        arrival: "KUF",
        dateFrom: "20220425",
        dateTo: "20220501",
        connections: 1,
      },
    });
  });

  it("parses round-trip route search", () => {
    expect(parseScheduleUrl("/schedule/route/MOW-KUF-20220425-20220501/KUF-MOW-20220502-20220508")).toEqual({
      type: "roundtrip",
      outbound: {
        departure: "MOW",
        arrival: "KUF",
        dateFrom: "20220425",
        dateTo: "20220501",
      },
      inbound: {
        departure: "KUF",
        arrival: "MOW",
        dateFrom: "20220502",
        dateTo: "20220508",
      },
    });
  });

  it("parses round-trip with time ranges", () => {
    expect(parseScheduleUrl("/schedule/route/MOW-KUF-20220425-20220501-06002200/KUF-MOW-20220502-20220508-06002200")).toEqual({
      type: "roundtrip",
      outbound: {
        departure: "MOW",
        arrival: "KUF",
        dateFrom: "20220425",
        dateTo: "20220501",
        timeFrom: "0600",
        timeTo: "2200",
      },
      inbound: {
        departure: "KUF",
        arrival: "MOW",
        dateFrom: "20220502",
        dateTo: "20220508",
        timeFrom: "0600",
        timeTo: "2200",
      },
    });
  });

  it("parses round-trip with connections", () => {
    expect(parseScheduleUrl("/schedule/route/MOW-KUF-20220425-20220501-C0/KUF-MOW-20220502-20220508-C0")).toEqual({
      type: "roundtrip",
      outbound: {
        departure: "MOW",
        arrival: "KUF",
        dateFrom: "20220425",
        dateTo: "20220501",
        connections: 0,
      },
      inbound: {
        departure: "KUF",
        arrival: "MOW",
        dateFrom: "20220502",
        dateTo: "20220508",
        connections: 0,
      },
    });
  });

  it("parses single-flight details", () => {
    expect(parseScheduleUrl("/schedule/SU0012-20220527")).toEqual({
      type: "details",
      flights: [
        { carrier: "SU", flightNumber: "0012", date: "20220527" },
      ],
    });
  });

  it("parses multi-flight details (connecting)", () => {
    expect(parseScheduleUrl("/schedule/SU0012-20220501/SU0013-20220507")).toEqual({
      type: "details",
      flights: [
        { carrier: "SU", flightNumber: "0012", date: "20220501" },
        { carrier: "SU", flightNumber: "0013", date: "20220507" },
      ],
    });
  });

  it("parses details with airport codes interleaved", () => {
    // Format: /{depCode}/{flight-date}/{arrCode}/{depCode2}/{flight2-date}/{arrCode2}
    // Airport codes (3-letter) are skipped, flight segments are parsed
    expect(parseScheduleUrl("/schedule/SVO/SU0012-20220501/LED/LED/SU0013-20220507/SVO")).toEqual({
      type: "details",
      flights: [
        { carrier: "SU", flightNumber: "0012", date: "20220501" },
        { carrier: "SU", flightNumber: "0013", date: "20220507" },
      ],
    });
  });

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

  it("returns null for non-schedule path", () => {
    expect(parseScheduleUrl("/some/other/path")).toBeNull();
  });

  it("returns null for invalid route params", () => {
    expect(parseScheduleUrl("/schedule/route/")).toBeNull();
  });

  it("handles path without leading slash", () => {
    expect(parseScheduleUrl("schedule")).toEqual({ type: "start" });
  });

  it("handles path without leading slash for route", () => {
    expect(parseScheduleUrl("schedule/route/MOW-KUF-20220425-20220501")).toEqual({
      type: "route",
      outbound: {
        departure: "MOW",
        arrival: "KUF",
        dateFrom: "20220425",
        dateTo: "20220501",
      },
    });
  });
});

// ---------------------------------------------------------------------------
// buildScheduleUrl
// ---------------------------------------------------------------------------

describe("buildScheduleUrl", () => {
  it("builds start page URL", () => {
    expect(buildScheduleUrl({ type: "start" })).toBe("schedule");
  });

  it("builds one-way route URL", () => {
    expect(buildScheduleUrl({
      type: "route",
      outbound: {
        departure: "MOW",
        arrival: "KUF",
        dateFrom: "20220425",
        dateTo: "20220501",
      },
    })).toBe("schedule/route/MOW-KUF-20220425-20220501");
  });

  it("builds one-way route with time range and connections", () => {
    expect(buildScheduleUrl({
      type: "route",
      outbound: {
        departure: "MOW",
        arrival: "KUF",
        dateFrom: "20220425",
        dateTo: "20220501",
        timeFrom: "0600",
        timeTo: "2200",
        connections: 0,
      },
    })).toBe("schedule/route/MOW-KUF-20220425-20220501-06002200-C0");
  });

  it("builds round-trip route URL", () => {
    expect(buildScheduleUrl({
      type: "roundtrip",
      outbound: {
        departure: "MOW",
        arrival: "KUF",
        dateFrom: "20220425",
        dateTo: "20220501",
      },
      inbound: {
        departure: "KUF",
        arrival: "MOW",
        dateFrom: "20220502",
        dateTo: "20220508",
      },
    })).toBe("schedule/route/MOW-KUF-20220425-20220501/KUF-MOW-20220502-20220508");
  });

  it("builds round-trip with time ranges and connections", () => {
    expect(buildScheduleUrl({
      type: "roundtrip",
      outbound: {
        departure: "MOW",
        arrival: "KUF",
        dateFrom: "20220425",
        dateTo: "20220501",
        timeFrom: "0600",
        timeTo: "2200",
        connections: 0,
      },
      inbound: {
        departure: "KUF",
        arrival: "MOW",
        dateFrom: "20220502",
        dateTo: "20220508",
        timeFrom: "0600",
        timeTo: "2200",
        connections: 0,
      },
    })).toBe("schedule/route/MOW-KUF-20220425-20220501-06002200-C0/KUF-MOW-20220502-20220508-06002200-C0");
  });

  it("builds single-flight details URL", () => {
    expect(buildScheduleUrl({
      type: "details",
      flights: [
        { carrier: "SU", flightNumber: "0012", date: "20220527" },
      ],
    })).toBe("schedule/SU0012-20220527");
  });

  it("builds multi-flight details URL", () => {
    expect(buildScheduleUrl({
      type: "details",
      flights: [
        { carrier: "SU", flightNumber: "0012", date: "20220501" },
        { carrier: "SU", flightNumber: "0013", date: "20220507" },
      ],
    })).toBe("schedule/SU0012-20220501/SU0013-20220507");
  });
});

// ---------------------------------------------------------------------------
// Roundtrip tests: build -> parse -> build
// ---------------------------------------------------------------------------

describe("roundtrip: build -> parse -> build", () => {
  const cases: Array<{ name: string; params: ScheduleParams }> = [
    { name: "start", params: { type: "start" } },
    {
      name: "one-way route without extras",
      params: {
        type: "route",
        outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501" },
      },
    },
    {
      name: "one-way route with time range",
      params: {
        type: "route",
        outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", timeFrom: "0600", timeTo: "2200" },
      },
    },
    {
      name: "one-way route with connections",
      params: {
        type: "route",
        outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", connections: 1 },
      },
    },
    {
      name: "one-way route with time range and connections",
      params: {
        type: "route",
        outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", timeFrom: "0600", timeTo: "2200", connections: 0 },
      },
    },
    {
      name: "round-trip without extras",
      params: {
        type: "roundtrip",
        outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501" },
        inbound: { departure: "KUF", arrival: "MOW", dateFrom: "20220502", dateTo: "20220508" },
      },
    },
    {
      name: "round-trip with time range and connections",
      params: {
        type: "roundtrip",
        outbound: { departure: "MOW", arrival: "KUF", dateFrom: "20220425", dateTo: "20220501", timeFrom: "0600", timeTo: "2200", connections: 0 },
        inbound: { departure: "KUF", arrival: "MOW", dateFrom: "20220502", dateTo: "20220508", timeFrom: "0600", timeTo: "2200", connections: 0 },
      },
    },
    {
      name: "single-flight details",
      params: {
        type: "details",
        flights: [{ carrier: "SU", flightNumber: "0012", date: "20220527" }],
      },
    },
    {
      name: "multi-flight details",
      params: {
        type: "details",
        flights: [
          { carrier: "SU", flightNumber: "0012", date: "20220501" },
          { carrier: "SU", flightNumber: "0013", date: "20220507" },
        ],
      },
    },
  ];

  for (const { name, params } of cases) {
    it(`roundtrips ${name}`, () => {
      const url = buildScheduleUrl(params);
      const parsed = parseScheduleUrl(url);
      expect(parsed).not.toBeNull();
      if (parsed === null) return;
      const rebuilt = buildScheduleUrl(parsed);
      expect(rebuilt).toBe(url);
    });
  }
});
