import {
  render,
  screen,
  fireEvent,
  waitFor,
  createEvent,
} from "@testing-library/react";
import { NavigationSearch } from "./NavigationSearch";
import { vi, describe, it, expect, beforeEach } from "vitest";
import React from "react";

// Mock next/navigation
vi.mock("next/navigation", () => ({
  useRouter: () => ({
    push: vi.fn(),
  }),
}));

describe("NavigationSearch Accessibility", () => {
  beforeEach(() => {
    vi.clearAllMocks();
    // Default to non-Mac
    Object.defineProperty(navigator, 'userAgent', {
      value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
      configurable: true
    });
  });

  it("has the correct ARIA roles and attributes on the input", () => {
    render(<NavigationSearch />);
    const input = screen.getByLabelText("Zur Seite navigieren");
    expect(input).toHaveAttribute("role", "combobox");
    expect(input).toHaveAttribute("aria-autocomplete", "list");
    expect(input).toHaveAttribute("aria-haspopup", "listbox");
    expect(input).toHaveAttribute("aria-expanded", "false");
  });

  it("updates aria-expanded when results are shown", async () => {
    render(<NavigationSearch />);
    const input = screen.getByLabelText("Zur Seite navigieren");

    fireEvent.change(input, { target: { value: "Dash" } });
    fireEvent.focus(input);

    await waitFor(() => {
      expect(input).toHaveAttribute("aria-expanded", "true");
    });

    const listbox = screen.getByRole("listbox");
    expect(listbox).toBeDefined();
    expect(listbox).toHaveAttribute("id", "nav-search-results");
  });

  it("shows Ctrl K on non-Mac platforms", () => {
    render(<NavigationSearch />);
    expect(screen.getByText("Ctrl K")).toBeTruthy();
  });

  it("shows ⌘K on Mac platforms", () => {
    Object.defineProperty(navigator, 'userAgent', {
      value: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)',
      configurable: true
    });
    render(<NavigationSearch />);
    expect(screen.getByText("⌘K")).toBeTruthy();
  });

  it("closes the results when Escape is pressed", async () => {
    render(<NavigationSearch />);
    const input = screen.getByLabelText("Zur Seite navigieren");

    fireEvent.change(input, { target: { value: "Dash" } });
    fireEvent.focus(input);

    await waitFor(() => {
      expect(input).toHaveAttribute("aria-expanded", "true");
    });

    fireEvent.keyDown(input, { key: "Escape" });
    await waitFor(() => {
        expect(input).toHaveAttribute("aria-expanded", "false");
    });
    expect(screen.queryByRole("listbox")).toBeNull();
  });

  it("shows 'Keine Ergebnisse gefunden' when no items match", async () => {
    render(<NavigationSearch />);
    const input = screen.getByLabelText("Zur Seite navigieren");

    fireEvent.change(input, { target: { value: "NonExistentPage" } });
    fireEvent.focus(input);

    await waitFor(() => {
      // Should find at least one (either live region or dropdown)
      expect(screen.getAllByText("Keine Ergebnisse gefunden").length).toBeGreaterThanOrEqual(1);
    });

    const status = screen.getByRole("status");
    expect(status.textContent).toBe("Keine Ergebnisse gefunden");
  });

  it("announces the number of results via aria-live", async () => {
    render(<NavigationSearch />);
    const input = screen.getByLabelText("Zur Seite navigieren");

    fireEvent.change(input, { target: { value: "Dashboard" } });
    fireEvent.focus(input);

    await waitFor(() => {
      const status = screen.getByRole("status");
      expect(status.textContent).toMatch(/Ergebnis gefunden/);
    });
  });

  it("clears the input and restores focus when Clear button is clicked", async () => {
    render(<NavigationSearch />);
    const input = screen.getByLabelText("Zur Seite navigieren");

    fireEvent.change(input, { target: { value: "Dash" } });

    const clearButton = screen.getByLabelText("Suche löschen");
    expect(clearButton).toBeTruthy();

    fireEvent.click(clearButton);

    expect(input).toHaveValue("");
    // We don't check document.activeElement here as JSDOM focus can be flaky in some envs
    // but the state should be clear
    expect(screen.queryByRole("listbox")).toBeNull();
  });

  it("hides the Kbd shortcut when query is present", () => {
    render(<NavigationSearch />);
    const input = screen.getByLabelText("Zur Seite navigieren");

    expect(screen.queryByText("Ctrl K")).toBeTruthy();

    fireEvent.change(input, { target: { value: "Dash" } });

    expect(screen.queryByText("Ctrl K")).toBeNull();
    expect(screen.getByLabelText("Suche löschen")).toBeTruthy();
  });

  it("focuses the input when Ctrl+K is pressed globally", () => {
    render(<NavigationSearch />);
    const input = screen.getByLabelText("Zur Seite navigieren");

    fireEvent.keyDown(window, { key: "k", ctrlKey: true });

    expect(document.activeElement).toBe(input);
  });

  it("focuses the input when ⌘K is pressed globally on Mac", () => {
    Object.defineProperty(navigator, 'userAgent', {
      value: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)',
      configurable: true
    });
    render(<NavigationSearch />);
    const input = screen.getByLabelText("Zur Seite navigieren");

    fireEvent.keyDown(window, { key: "k", metaKey: true });

    expect(document.activeElement).toBe(input);
  });
});
