import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import {
  cleanup,
  fireEvent,
  render,
  screen,
  waitFor,
} from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import type { QuestionField } from "@/lib/schema-adapter";
import { QuestionAnswersProvider } from "./question-answer-storage";
import { QuestionSheet } from "./question-sheet";

vi.mock("@/translations/provider", () => ({
  useI18n: vi.fn(() => ({ locale: "fa", dictionary: { Confirm: "تایید" } })),
}));

vi.mock("@/hooks/marriage/use-section-data", () => ({
  applyProfilePatchResultToCache: vi.fn(),
  useMarriageSectionDataQuery: vi.fn(() => ({
    data: undefined,
    isLoading: false,
  })),
  useUpdateMarriageSectionDataMutation: vi.fn(() => ({
    mutateAsync: vi.fn().mockResolvedValue({}),
    isPending: false,
  })),
}));

describe("QuestionSheet component", () => {
  afterEach(() => {
    cleanup();
    window.history.replaceState(null, "", window.location.href);
    document.body.classList.remove("dropdown-open");
    document.body.classList.remove("question-sheet-open");
    document.body.classList.remove("question-keyboard-open");
  });

  const queryClient = new QueryClient({
    defaultOptions: { queries: { retry: false } },
  });

  it("renders trigger and opens bottom sheet on click", async () => {
    const qDropdown = {
      id: "q_nat",
      title: "تابعیت و شهروندی",
      type: "dropdown",
      order: 1,
      required: true,
      isVisible: true,
      description: "",
      tooltip: "",
      extras: { placeHolder: "انتخاب کشور" },
      options: [
        { id: "iran", value: "Iran", label: "ایران", order: 1 },
        { id: "germany", value: "Germany", label: "آلمان", order: 2 },
        { id: "canada", value: "Canada", label: "کانادا", order: 3 },
      ],
      ui_config: {},
    } as QuestionField;

    render(
      <div className="app-shell">
        <QueryClientProvider client={queryClient}>
          <QuestionAnswersProvider slug="test" questions={[qDropdown]}>
            <QuestionSheet question={qDropdown} />
          </QuestionAnswersProvider>
        </QueryClientProvider>
      </div>,
    );

    // Initial placeholder displayed in trigger
    expect(screen.getByText("انتخاب کشور")).toBeDefined();

    // Click trigger to open bottom sheet
    const trigger = screen.getByRole("button", { name: /انتخاب کشور/i });
    fireEvent.click(trigger);

    // Bottom sheet dialog should be visible
    expect(screen.getByRole("dialog")).toBeDefined();
    expect(document.body.classList.contains("dropdown-open")).toBe(true);
    expect(document.body.classList.contains("question-sheet-open")).toBe(true);
    expect(
      (document.querySelector(".app-shell") as HTMLElement).style.overflowY,
    ).toBe("hidden");
    expect(screen.getByRole("button", { name: "ایران" })).toBeDefined();
    expect(screen.getByRole("button", { name: "آلمان" })).toBeDefined();

    // Select Iran
    const iranBtn = screen.getByRole("button", { name: "ایران" });
    fireEvent.click(iranBtn);

    // Trigger should now show Iran
    await waitFor(() => {
      expect(screen.getByText("ایران")).toBeDefined();
      expect(document.body.classList.contains("dropdown-open")).toBe(false);
      expect(document.body.classList.contains("question-sheet-open")).toBe(
        false,
      );
      expect(
        (document.querySelector(".app-shell") as HTMLElement).style.overflowY,
      ).toBe("");
    });
  });

  it("supports multi-selection with confirm button", async () => {
    const qMulti = {
      id: "q_lang",
      title: "سایر زبان‌ها",
      type: "dropdown",
      order: 2,
      required: false,
      isVisible: true,
      description: "",
      tooltip: "",
      extras: { placeHolder: "انتخاب زبان‌ها", range: [0, 5] },
      options: [
        { id: "en", value: "English", label: "انگلیسی", order: 1 },
        { id: "ar", value: "Arabic", label: "عربی", order: 2 },
        { id: "fr", value: "French", label: "فرانسوی", order: 3 },
      ],
      ui_config: {},
    } as QuestionField;

    render(
      <QueryClientProvider client={queryClient}>
        <QuestionAnswersProvider slug="test" questions={[qMulti]}>
          <QuestionSheet question={qMulti} />
        </QuestionAnswersProvider>
      </QueryClientProvider>,
    );

    // Click trigger
    const trigger = screen.getByRole("button", { name: /انتخاب زبان‌ها/i });
    fireEvent.click(trigger);

    // Select English and French
    const enBtn = screen.getByRole("button", { name: "انگلیسی" });
    const frBtn = screen.getByRole("button", { name: "فرانسوی" });
    fireEvent.click(enBtn);
    fireEvent.click(frBtn);

    // Confirm button should show count
    const confirmBtn = screen.getByRole("button", { name: /تایید \(2\)/i });
    expect(confirmBtn).toBeDefined();
    fireEvent.click(confirmBtn);

    // Trigger displays selected items
    await waitFor(() => {
      expect(screen.getByText("انگلیسی, فرانسوی")).toBeDefined();
    });
  });

  it("closes the inline selector with Escape", async () => {
    const question = {
      id: "q_drag",
      title: "کشور محل اقامت",
      type: "dropdown",
      required: true,
      extras: { placeHolder: "انتخاب کشور" },
      options: [{ id: "iran", value: "Iran", label: "ایران", order: 1 }],
      ui_config: {},
    } as QuestionField;

    render(
      <QueryClientProvider client={queryClient}>
        <QuestionAnswersProvider slug="test" questions={[question]}>
          <QuestionSheet question={question} />
        </QuestionAnswersProvider>
      </QueryClientProvider>,
    );

    fireEvent.click(screen.getByRole("button", { name: /انتخاب کشور/i }));
    fireEvent.keyDown(screen.getByRole("dialog"), { key: "Escape" });

    await waitFor(() => {
      expect(screen.queryByRole("dialog")).toBeNull();
      expect(document.body.classList.contains("dropdown-open")).toBe(false);
      expect(document.body.classList.contains("question-sheet-open")).toBe(
        false,
      );
    });
  });

  it("closes the sheet instead of leaving the page on browser Back", async () => {
    const question = {
      id: "q_back",
      title: "کشور",
      type: "dropdown",
      required: true,
      extras: { placeHolder: "انتخاب کشور" },
      options: [{ id: "iran", value: "Iran", label: "ایران", order: 1 }],
      ui_config: {},
    } as QuestionField;
    const pushState = vi.spyOn(window.history, "pushState");

    render(
      <QueryClientProvider client={queryClient}>
        <QuestionAnswersProvider slug="test" questions={[question]}>
          <QuestionSheet question={question} />
        </QuestionAnswersProvider>
      </QueryClientProvider>,
    );

    fireEvent.click(screen.getByRole("button", { name: /انتخاب کشور/i }));
    await waitFor(() => expect(pushState).toHaveBeenCalledTimes(1));

    window.history.replaceState(null, "", window.location.href);
    window.dispatchEvent(new PopStateEvent("popstate"));

    await waitFor(() => {
      expect(screen.queryByRole("dialog")).toBeNull();
    });
    pushState.mockRestore();
  });

  it("opens a searchable sheet for 7+ options without focusing search", () => {
    const question = {
      id: "q_country",
      title: "کشور",
      type: "dropdown",
      required: true,
      extras: { placeHolder: "انتخاب کشور" },
      options: Array.from({ length: 7 }, (_, index) => ({
        id: `country-${index}`,
        value: `country-${index}`,
        label: `کشور ${index + 1}`,
        order: index + 1,
      })),
      ui_config: {},
    } as QuestionField;

    render(
      <QueryClientProvider client={queryClient}>
        <QuestionAnswersProvider slug="test" questions={[question]}>
          <QuestionSheet question={question} />
        </QuestionAnswersProvider>
      </QueryClientProvider>,
    );

    fireEvent.click(screen.getByRole("button", { name: /انتخاب کشور/i }));

    expect(screen.getByPlaceholderText("جستجو...")).not.toHaveFocus();
    expect(screen.getByRole("dialog").querySelector("section")).toHaveClass(
      "h-[82svh]",
    );
  });

  it("sizes a short options sheet to its content (4 options)", () => {
    const question = {
      id: "q_short",
      title: "انتخاب کوتاه",
      type: "dropdown",
      required: true,
      extras: { placeHolder: "انتخاب" },
      options: Array.from({ length: 4 }, (_, index) => ({
        id: `option-${index}`,
        value: `option-${index}`,
        label: `گزینه ${index + 1}`,
        order: index + 1,
      })),
      ui_config: {},
    } as QuestionField;

    render(
      <QueryClientProvider client={queryClient}>
        <QuestionAnswersProvider slug="test" questions={[question]}>
          <QuestionSheet question={question} />
        </QuestionAnswersProvider>
      </QueryClientProvider>,
    );

    fireEvent.click(screen.getByRole("button", { name: "انتخاب" }));

    expect(screen.getByRole("dialog").querySelector("section")).toHaveClass(
      "h-auto",
      "max-h-[82svh]",
    );
  });

  it("compact boundary: 5 options → compact, no search", () => {
    const question = {
      id: "q_boundary_5",
      title: "پنج گزینه",
      type: "dropdown",
      required: true,
      extras: { placeHolder: "انتخاب" },
      options: Array.from({ length: 5 }, (_, i) => ({
        id: `opt-${i}`,
        value: `opt-${i}`,
        label: `گزینه ${i + 1}`,
        order: i + 1,
      })),
      ui_config: {},
    } as QuestionField;

    render(
      <QueryClientProvider client={queryClient}>
        <QuestionAnswersProvider slug="test" questions={[question]}>
          <QuestionSheet question={question} />
        </QuestionAnswersProvider>
      </QueryClientProvider>,
    );

    fireEvent.click(screen.getByRole("button", { name: "انتخاب" }));

    const section = screen.getByRole("dialog").querySelector("section");
    expect(section).toHaveClass("h-auto", "max-h-[82svh]");
    expect(screen.queryByPlaceholderText("جستجو...")).toBeNull();
  });

  it("compact boundary: 6 options → compact, no search", () => {
    const question = {
      id: "q_boundary_6",
      title: "شش گزینه",
      type: "dropdown",
      required: true,
      extras: { placeHolder: "انتخاب" },
      options: Array.from({ length: 6 }, (_, i) => ({
        id: `opt-${i}`,
        value: `opt-${i}`,
        label: `گزینه ${i + 1}`,
        order: i + 1,
      })),
      ui_config: {},
    } as QuestionField;

    render(
      <QueryClientProvider client={queryClient}>
        <QuestionAnswersProvider slug="test" questions={[question]}>
          <QuestionSheet question={question} />
        </QuestionAnswersProvider>
      </QueryClientProvider>,
    );

    fireEvent.click(screen.getByRole("button", { name: "انتخاب" }));

    const section = screen.getByRole("dialog").querySelector("section");
    expect(section).toHaveClass("h-auto", "max-h-[82svh]");
    expect(section).not.toHaveClass("h-[82svh]");
    expect(screen.queryByPlaceholderText("جستجو...")).toBeNull();
  });

  it("compact boundary: 7 options → large sheet with search", () => {
    const question = {
      id: "q_boundary_7",
      title: "هفت گزینه",
      type: "dropdown",
      required: true,
      extras: { placeHolder: "انتخاب" },
      options: Array.from({ length: 7 }, (_, i) => ({
        id: `opt-${i}`,
        value: `opt-${i}`,
        label: `گزینه ${i + 1}`,
        order: i + 1,
      })),
      ui_config: {},
    } as QuestionField;

    render(
      <QueryClientProvider client={queryClient}>
        <QuestionAnswersProvider slug="test" questions={[question]}>
          <QuestionSheet question={question} />
        </QuestionAnswersProvider>
      </QueryClientProvider>,
    );

    fireEvent.click(screen.getByRole("button", { name: "انتخاب" }));

    const section = screen.getByRole("dialog").querySelector("section");
    expect(section).toHaveClass("h-[82svh]");
    expect(section).not.toHaveClass("h-auto");
    expect(screen.getByPlaceholderText("جستجو...")).toBeDefined();
  });
});
