/**
 * @vitest-environment jsdom
 */

import { describe, it, expect, vi } from "vitest";
import { render, screen, fireEvent } from "@testing-library/react";
import { CityAutocomplete } from "./CityAutocomplete.js";
import { transformDictionaries } from "@/shared/dictionaries/index.js";
import type { IRawDictionaries } from "@/shared/dictionaries/index.js";

const raw: IRawDictionaries = {
  regions: [{ world_region_id: 500374, title: { ru: "Россия" } }],
  countries: [{ code: "RU", title: { ru: "Россия" }, world_region_id: 500374 }],
  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 } },
  ],
  airports: [
    { code: "SVO", city_code: "MOW", title: { ru: "Шереметьево" }, has_afl_flights: true, location: { lat: 55, lon: 37 } },
    { code: "LED", city_code: "LED", title: { ru: "Пулково" }, has_afl_flights: true, location: { lat: 60, lon: 30 } },
  ],
};
const dictionaries = transformDictionaries(raw, "ru");

vi.mock("primereact/autocomplete", () => ({
  AutoComplete: (props: Record<string, unknown>) => (
    <input
      data-testid={props["data-testid"] as string}
      placeholder={props["placeholder"] as string}
      value={typeof props["value"] === "string" ? props["value"] : ""}
      onChange={(e) => {
        const onChange = props["onChange"] as ((ev: { value: string }) => void) | undefined;
        onChange?.({ value: e.target.value });
      }}
    />
  ),
}));

describe("CityAutocomplete", () => {
  it("renders label and placeholder", () => {
    render(
      <CityAutocomplete
        label="City"
        placeholder="Pick one"
        value=""
        onChange={vi.fn()}
        dictionaries={dictionaries}
      />,
    );
    expect(screen.getByText("City")).toBeTruthy();
    expect(screen.getByPlaceholderText("Pick one")).toBeTruthy();
  });

  it("shows the selected city code in the right label when value is set", () => {
    render(
      <CityAutocomplete
        label="City"
        placeholder="Pick"
        value="MOW"
        onChange={vi.fn()}
        dictionaries={dictionaries}
        testIdPrefix="test"
      />,
    );
    expect(screen.getByTestId("test-code").textContent).toBe("MOW");
  });

  it("opens the regional picker when the popup-trigger button is clicked", () => {
    render(
      <CityAutocomplete
        label="City"
        placeholder="Pick"
        value=""
        onChange={vi.fn()}
        dictionaries={dictionaries}
        testIdPrefix="test"
      />,
    );
    expect(screen.queryByTestId("city-picker-popup")).toBeNull();
    fireEvent.click(screen.getByTestId("test-popup-button"));
    expect(screen.getByTestId("city-picker-popup")).toBeTruthy();
  });

  it("calls onChange with the selected code when a popup cell is clicked", () => {
    const onChange = vi.fn();
    render(
      <CityAutocomplete
        label="City"
        placeholder="Pick"
        value=""
        onChange={onChange}
        dictionaries={dictionaries}
        testIdPrefix="test"
      />,
    );
    fireEvent.click(screen.getByTestId("test-popup-button"));
    fireEvent.click(screen.getByText("Санкт-Петербург"));
    expect(onChange).toHaveBeenCalledWith("LED");
  });

  it("clears the value when the clear button is clicked", () => {
    const onChange = vi.fn();
    render(
      <CityAutocomplete
        label="City"
        placeholder="Pick"
        value="MOW"
        onChange={onChange}
        dictionaries={dictionaries}
        testIdPrefix="test"
      />,
    );
    fireEvent.click(screen.getByTestId("test-clear-button"));
    expect(onChange).toHaveBeenCalledWith("");
  });

  it("closes the popup when clicking outside the component", () => {
    render(
      <div>
        <CityAutocomplete
          label="City"
          placeholder="Pick"
          value=""
          onChange={vi.fn()}
          dictionaries={dictionaries}
          testIdPrefix="test"
        />
        <div data-testid="outside">outside</div>
      </div>,
    );
    fireEvent.click(screen.getByTestId("test-popup-button"));
    expect(screen.getByTestId("city-picker-popup")).toBeTruthy();
    fireEvent.mouseDown(screen.getByTestId("outside"));
    expect(screen.queryByTestId("city-picker-popup")).toBeNull();
  });

  it("renders error tooltip and has-error class when error prop is set", () => {
    const { container } = render(
      <CityAutocomplete
        label="City"
        placeholder="Pick"
        value=""
        onChange={vi.fn()}
        dictionaries={dictionaries}
        error="required"
        testIdPrefix="test"
      />,
    );
    expect(screen.getByTestId("test-error").textContent).toBe("required");
    expect(container.querySelector(".city-autocomplete__input--has-error")).toBeTruthy();
  });

  it("does not open popup when dictionaries is null", () => {
    render(
      <CityAutocomplete
        label="City"
        placeholder="Pick"
        value=""
        onChange={vi.fn()}
        dictionaries={null}
        testIdPrefix="test"
      />,
    );
    fireEvent.click(screen.getByTestId("test-popup-button"));
    expect(screen.queryByTestId("city-picker-popup")).toBeNull();
  });
});
