// @vitest-environment jsdom
import { describe, it, expect, vi } from "vitest";
import { render, screen, fireEvent } from "@testing-library/react";
import { FlightSchedule } from "./FlightSchedule.js";
import type { ISimpleFlight } from "../../types.js";

vi.mock("@/i18n/provider.js", () => ({
  useTranslation: () => ({
    t: (k: string) => {
      if (k === "SHARED.NOTE-TIME-SCHEDULE") {
        return "Valid from {START_DATE} to {END_DATE}";
      }
      return k;
    },
  }),
}));

interface FlightOverrides {
  daysOfWeek?: { current: string; flight: string };
  depLocal?: string;
  arrLocal?: string;
  flyingTime?: string;
}

function makeFlight(overrides: FlightOverrides = {}): ISimpleFlight {
  const depLocal = overrides.depLocal ?? "2026-04-15T10:00:00";
  const arrLocal = overrides.arrLocal ?? "2026-04-15T12:30:00";
  const flyingTime = overrides.flyingTime ?? "02:30:00";
  return {
    id: "X",
    routeType: "Direct",
    flyingTime,
    status: "Scheduled",
    flightId: { carrier: "SU", flightNumber: "0022", suffix: "", date: "20260415" },
    operatingBy: { carrier: "SU", flightNumber: "0022" },
    leg: {
      arrival: {
        scheduled: {
          airport: "LED",
          airportCode: "LED",
          city: "SPB",
          cityCode: "LED",
          countryCode: "RU",
        },
        latest: {
          airport: "LED",
          airportCode: "LED",
          city: "SPB",
          cityCode: "LED",
          countryCode: "RU",
        },
        dispatch: "",
        gate: "",
        terminal: "",
        times: {
          scheduledArrival: {
            dayChange: { value: 0, title: "" },
            local: arrLocal,
            localTime: "",
            tzOffset: 0,
            utc: "",
          },
        },
      },
      dayChange: 0,
      departure: {
        scheduled: {
          airport: "SVO",
          airportCode: "SVO",
          city: "MOW",
          cityCode: "MOW",
          countryCode: "RU",
        },
        latest: {
          airport: "SVO",
          airportCode: "SVO",
          city: "MOW",
          cityCode: "MOW",
          countryCode: "RU",
        },
        dispatch: "",
        gate: "",
        terminal: "",
        checkingStatus: "Scheduled",
        parkingStand: "",
        times: {
          scheduledDeparture: {
            dayChange: { value: 0, title: "" },
            local: depLocal,
            localTime: "10:00",
            tzOffset: 0,
            utc: "",
          },
        },
      },
      equipment: {},
      flags: { checkinAvailable: false, returnToAirport: false, routeChanged: false },
      flyingTime,
      index: 0,
      operatingBy: {},
      status: "Scheduled",
      updated: "",
      ...(overrides.daysOfWeek ? { daysOfWeek: overrides.daysOfWeek } : {}),
    },
  } as ISimpleFlight;
}

describe("FlightSchedule", () => {
  it("returns null when firstLeg has no daysOfWeek", () => {
    const { container } = render(<FlightSchedule flight={makeFlight()} />);
    expect(container.firstChild).toBeNull();
  });

  it("returns null when daysOfWeek.flight is empty string", () => {
    const flight = makeFlight({ daysOfWeek: { current: "1111111", flight: "" } });
    const { container } = render(<FlightSchedule flight={flight} />);
    expect(container.firstChild).toBeNull();
  });

  it("renders with data-testid=flight-schedule when daysOfWeek present", () => {
    const flight = makeFlight({
      daysOfWeek: { current: "1111111", flight: "1111111" },
    });
    render(<FlightSchedule flight={flight} />);
    expect(screen.getByTestId("flight-schedule")).toBeTruthy();
  });

  it("renders 7 day boxes from daysOfWeek.flight", () => {
    const flight = makeFlight({
      daysOfWeek: { current: "1110000", flight: "1110000" },
    });
    render(<FlightSchedule flight={flight} />);
    const boxes = screen.getAllByTestId(/^day-of-week-\d$/);
    expect(boxes).toHaveLength(7);
  });

  it("substitutes {START_DATE} and {END_DATE} into the note", () => {
    const flight = makeFlight({
      daysOfWeek: { current: "1111111", flight: "1111111" },
    });
    render(<FlightSchedule flight={flight} />);
    const note = screen.getByTestId("flight-schedule-note");
    expect(note.textContent).toContain("13.04.2026");
    expect(note.textContent).toContain("19.04.2026");
  });

  it("renders scheduled departure/arrival times and duration", () => {
    const flight = makeFlight({
      daysOfWeek: { current: "1111111", flight: "1111111" },
    });
    render(<FlightSchedule flight={flight} />);
    // The dep/arr times are rendered alongside their UTC offset suffix in
    // separate spans, so use regex matchers that ignore the offset.
    expect(screen.getByText(/^10:00$/)).toBeTruthy();
    expect(screen.getByText(/^12:30$/)).toBeTruthy();
    // Scheduled duration derived from dep→arr timestamps, Angular format
    // '2ч. 30мин.' via formatDuration in ru locale.
    expect(screen.getByText("2ч. 30мин.")).toBeTruthy();
  });

  // TZ §4.1.16.8: uses daysOfWeek.flight (schedule days), not .current (today's active day)
  it("uses daysOfWeek.flight digit-list for active days, not .current", () => {
    // current = daily ("1234567"), flight = Mon/Wed/Fri only ("135")
    const flight = makeFlight({
      daysOfWeek: { current: "1234567", flight: "135" },
    });
    render(<FlightSchedule flight={flight} />);
    // Mon(0), Wed(2), Fri(4) should be active
    expect(screen.getByTestId("day-of-week-0").className).not.toMatch(/--inactive/);
    expect(screen.getByTestId("day-of-week-2").className).not.toMatch(/--inactive/);
    expect(screen.getByTestId("day-of-week-4").className).not.toMatch(/--inactive/);
    // Tue(1), Thu(3), Sat(5), Sun(6) should be inactive
    expect(screen.getByTestId("day-of-week-1").className).toMatch(/--inactive/);
    expect(screen.getByTestId("day-of-week-3").className).toMatch(/--inactive/);
    expect(screen.getByTestId("day-of-week-5").className).toMatch(/--inactive/);
    expect(screen.getByTestId("day-of-week-6").className).toMatch(/--inactive/);
  });

  // TZ §4.1.16.8: collapsible accordion — open by default, toggles
  it("accordion is expanded by default and collapses on click", async () => {
    const flight = makeFlight({
      daysOfWeek: { current: "1111111", flight: "1111111" },
    });
    render(<FlightSchedule flight={flight} />);
    const header = screen.getByRole("button");
    // Days strip is visible initially
    expect(screen.getAllByTestId(/^day-of-week-\d$/).length).toBe(7);
    // Click to collapse
    fireEvent.click(header);
    expect(screen.queryAllByTestId(/^day-of-week-\d$/).length).toBe(0);
  });

  // TZ §4.1.16.8: week note uses departure local date, not arrival or UTC
  it("week note is derived from first-leg scheduled departure local time", () => {
    // dep = 2026-04-20 (Monday) → week is 20.04.2026 – 26.04.2026
    const flight = makeFlight({
      daysOfWeek: { current: "1111111", flight: "1111111" },
      depLocal: "2026-04-20T08:00:00",
      arrLocal: "2026-04-20T11:00:00",
    });
    render(<FlightSchedule flight={flight} />);
    const note = screen.getByTestId("flight-schedule-note");
    expect(note.textContent).toContain("20.04.2026");
    expect(note.textContent).toContain("26.04.2026");
  });
});
