/**
 * Tests for PopularRequestsPanel component.
 *
 * Covers all 5 request modes, loading/error states, keyboard
 * accessibility, and the 4-item display limit.
 *
 * @vitest-environment jsdom
 */

import { describe, it, expect, vi, beforeEach } from "vitest";
import { render, screen, fireEvent } from "@testing-library/react";
import { PopularRequestsPanel } from "./PopularRequestsPanel";
import type { PopularRequest } from "../types";

// ---------------------------------------------------------------------------
// Mocks
// ---------------------------------------------------------------------------

const mockUsePopularRequests = vi.fn<
  () => { requests: PopularRequest[]; loading: boolean; error: Error | null }
>();

vi.mock("../hooks/usePopularRequests.js", () => ({
  usePopularRequests: () => mockUsePopularRequests(),
}));

vi.mock("@/i18n/provider.js", () => ({
  useTranslation: () => ({
    t: (key: string) => key,
    i18n: { language: "en" },
  }),
}));

vi.mock("@/shared/hooks/useDictionaries.js", () => ({
  useCityName: (code: string) => code,
}));

// ---------------------------------------------------------------------------
// Test data
// ---------------------------------------------------------------------------

const mockRequests: PopularRequest[] = [
  {
    mode: "FlightNumber",
    carrier: "SU",
    flightNumber: "9027",
    type: "Onlineboard",
  },
  {
    mode: "FlightNumber",
    carrier: "SU",
    flightNumber: "9006",
    type: "Onlineboard",
  },
  {
    mode: "Route",
    departure: "KUF",
    arrival: "ABA",
    type: "Onlineboard",
  },
  {
    mode: "Route",
    departure: "RTW",
    arrival: "ABA",
    type: "Onlineboard",
  },
];

// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------

describe("PopularRequestsPanel", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("renders nothing while loading", () => {
    mockUsePopularRequests.mockReturnValue({
      requests: [],
      loading: true,
      error: null,
    });

    const { container } = render(
      <PopularRequestsPanel onRequestClick={vi.fn()} />,
    );

    expect(container.innerHTML).toBe("");
  });

  it("renders nothing on error (graceful degradation)", () => {
    mockUsePopularRequests.mockReturnValue({
      requests: [],
      loading: false,
      error: new Error("API failure"),
    });

    const { container } = render(
      <PopularRequestsPanel onRequestClick={vi.fn()} />,
    );

    expect(container.innerHTML).toBe("");
  });

  it("renders nothing when requests array is empty", () => {
    mockUsePopularRequests.mockReturnValue({
      requests: [],
      loading: false,
      error: null,
    });

    const { container } = render(
      <PopularRequestsPanel onRequestClick={vi.fn()} />,
    );

    expect(container.innerHTML).toBe("");
  });

  it("renders the title and up to 4 request items", () => {
    mockUsePopularRequests.mockReturnValue({
      requests: mockRequests,
      loading: false,
      error: null,
    });

    render(<PopularRequestsPanel onRequestClick={vi.fn()} />);

    expect(screen.getByText("BOARD.POPULAR-CHAPTERS")).toBeTruthy();
    const items = screen.getAllByRole("button");
    expect(items).toHaveLength(4);
  });

  it("calls onRequestClick when a flight number item is clicked", () => {
    mockUsePopularRequests.mockReturnValue({
      requests: [mockRequests[0] as PopularRequest],
      loading: false,
      error: null,
    });

    const onRequestClick = vi.fn();
    render(<PopularRequestsPanel onRequestClick={onRequestClick} />);

    const button = screen.getByRole("button");
    fireEvent.click(button);

    expect(onRequestClick).toHaveBeenCalledWith(mockRequests[0]);
  });

  it("renders flight number with carrier and number", () => {
    mockUsePopularRequests.mockReturnValue({
      requests: [mockRequests[0] as PopularRequest],
      loading: false,
      error: null,
    });

    const { container } = render(
      <PopularRequestsPanel onRequestClick={vi.fn()} />,
    );

    // The span contains "SU\u00a09027" — check the button text
    const button = screen.getByRole("button");
    expect(button.textContent).toContain("SU");
    expect(button.textContent).toContain("9027");
    // Also check the container has the FLIGHT_NUMBER label
    expect(container.textContent).toContain("BOARD.FLIGHT_NUMBER");
  });

  it("renders route request with departure and arrival", () => {
    mockUsePopularRequests.mockReturnValue({
      requests: [mockRequests[2] as PopularRequest],
      loading: false,
      error: null,
    });

    const { container } = render(
      <PopularRequestsPanel onRequestClick={vi.fn()} />,
    );

    expect(container.textContent).toContain("KUF - ABA");
  });

  it("limits display to 4 items even with more data", () => {
    const manyRequests: PopularRequest[] = [
      ...mockRequests,
      {
        mode: "Arrival",
        arrival: "SVO",
        type: "Onlineboard",
      },
    ];

    mockUsePopularRequests.mockReturnValue({
      requests: manyRequests,
      loading: false,
      error: null,
    });

    render(<PopularRequestsPanel onRequestClick={vi.fn()} />);

    const items = screen.getAllByRole("button");
    expect(items).toHaveLength(4);
  });

  it("renders arrival request mode", () => {
    mockUsePopularRequests.mockReturnValue({
      requests: [
        {
          mode: "Arrival",
          arrival: "SVO",
          type: "Onlineboard",
        },
      ],
      loading: false,
      error: null,
    });

    const { container } = render(
      <PopularRequestsPanel onRequestClick={vi.fn()} />,
    );

    expect(container.textContent).toContain("BOARD.ARRIVAL");
    expect(screen.getByRole("button").textContent).toBe("SVO");
  });

  it("renders departure request mode", () => {
    mockUsePopularRequests.mockReturnValue({
      requests: [
        {
          mode: "Departure",
          departure: "DME",
          type: "Onlineboard",
        },
      ],
      loading: false,
      error: null,
    });

    const { container } = render(
      <PopularRequestsPanel onRequestClick={vi.fn()} />,
    );

    expect(container.textContent).toContain("BOARD.DEPARTURE");
    expect(screen.getByRole("button").textContent).toBe("DME");
  });

  it("renders schedule route with correct label", () => {
    mockUsePopularRequests.mockReturnValue({
      requests: [
        {
          mode: "Route",
          departure: "SVO",
          arrival: "LED",
          type: "Schedule",
        },
      ],
      loading: false,
      error: null,
    });

    const { container } = render(
      <PopularRequestsPanel onRequestClick={vi.fn()} />,
    );

    expect(container.textContent).toContain("SCHEDULE.SCHEDULE-OUTBOUND");
  });

  it("renders RouteWithBack with full-route label", () => {
    mockUsePopularRequests.mockReturnValue({
      requests: [
        {
          mode: "RouteWithBack",
          departure: "SVO",
          arrival: "JFK",
          type: "Schedule",
        },
      ],
      loading: false,
      error: null,
    });

    const { container } = render(
      <PopularRequestsPanel onRequestClick={vi.fn()} />,
    );

    expect(container.textContent).toContain("SCHEDULE.SCHEDULE-FULL-ROUTE");
  });

  it("supports keyboard activation (Enter key)", () => {
    mockUsePopularRequests.mockReturnValue({
      requests: [mockRequests[0] as PopularRequest],
      loading: false,
      error: null,
    });

    const onRequestClick = vi.fn();
    render(<PopularRequestsPanel onRequestClick={onRequestClick} />);

    const button = screen.getByRole("button");
    fireEvent.keyDown(button, { key: "Enter" });

    expect(onRequestClick).toHaveBeenCalledWith(mockRequests[0]);
  });

  it("supports keyboard activation (Space key)", () => {
    mockUsePopularRequests.mockReturnValue({
      requests: [mockRequests[0] as PopularRequest],
      loading: false,
      error: null,
    });

    const onRequestClick = vi.fn();
    render(<PopularRequestsPanel onRequestClick={onRequestClick} />);

    const button = screen.getByRole("button");
    fireEvent.keyDown(button, { key: " " });

    expect(onRequestClick).toHaveBeenCalledWith(mockRequests[0]);
  });
});
