import { describe, expect, it, vi } from "vitest";
import { render, screen } from "~/test-utils.js";
import userEvent from "@testing-library/user-event";
import { FilterChips, type Chip } from "./FilterChips.js";

describe("FilterChips", () => {
  describe("rendering", () => {
    it("renders nothing when chips array is empty", () => {
      const { container } = render(<FilterChips chips={[]} onClearAll={vi.fn()} />);
      expect(container).toBeEmptyDOMElement();
    });

    it("renders chip labels when chips are provided", () => {
      const chips: Chip[] = [
        { label: "Active", onRemove: vi.fn() },
        { label: "Design", onRemove: vi.fn() },
      ];
      render(<FilterChips chips={chips} onClearAll={vi.fn()} />);
      expect(screen.getByText("Active")).toBeInTheDocument();
      expect(screen.getByText("Design")).toBeInTheDocument();
    });

    it("renders a remove button for each chip", () => {
      const chips: Chip[] = [
        { label: "Active", onRemove: vi.fn() },
        { label: "Design", onRemove: vi.fn() },
      ];
      render(<FilterChips chips={chips} onClearAll={vi.fn()} />);
      expect(screen.getByRole("button", { name: "Remove filter: Active" })).toBeInTheDocument();
      expect(screen.getByRole("button", { name: "Remove filter: Design" })).toBeInTheDocument();
    });

    it("renders the 'Clear all' button when chips are present", () => {
      const chips: Chip[] = [{ label: "Active", onRemove: vi.fn() }];
      render(<FilterChips chips={chips} onClearAll={vi.fn()} />);
      expect(screen.getByRole("button", { name: "Clear all" })).toBeInTheDocument();
    });

    it("does not render 'Clear all' when chips array is empty", () => {
      render(<FilterChips chips={[]} onClearAll={vi.fn()} />);
      expect(screen.queryByRole("button", { name: "Clear all" })).not.toBeInTheDocument();
    });

    it("renders a single chip correctly", () => {
      const chips: Chip[] = [{ label: "Pending", onRemove: vi.fn() }];
      render(<FilterChips chips={chips} onClearAll={vi.fn()} />);
      expect(screen.getByText("Pending")).toBeInTheDocument();
      expect(screen.getByRole("button", { name: "Remove filter: Pending" })).toBeInTheDocument();
    });
  });

  describe("interactions", () => {
    it("calls onRemove of the correct chip when its remove button is clicked", async () => {
      const user = userEvent.setup();
      const handleRemoveActive = vi.fn();
      const handleRemoveDesign = vi.fn();
      const chips: Chip[] = [
        { label: "Active", onRemove: handleRemoveActive },
        { label: "Design", onRemove: handleRemoveDesign },
      ];
      render(<FilterChips chips={chips} onClearAll={vi.fn()} />);

      await user.click(screen.getByRole("button", { name: "Remove filter: Active" }));
      expect(handleRemoveActive).toHaveBeenCalledOnce();
      expect(handleRemoveDesign).not.toHaveBeenCalled();
    });

    it("calls onRemove for the second chip independently", async () => {
      const user = userEvent.setup();
      const handleRemoveActive = vi.fn();
      const handleRemoveDesign = vi.fn();
      const chips: Chip[] = [
        { label: "Active", onRemove: handleRemoveActive },
        { label: "Design", onRemove: handleRemoveDesign },
      ];
      render(<FilterChips chips={chips} onClearAll={vi.fn()} />);

      await user.click(screen.getByRole("button", { name: "Remove filter: Design" }));
      expect(handleRemoveDesign).toHaveBeenCalledOnce();
      expect(handleRemoveActive).not.toHaveBeenCalled();
    });

    it("calls onClearAll when the Clear all button is clicked", async () => {
      const user = userEvent.setup();
      const handleClearAll = vi.fn();
      const chips: Chip[] = [{ label: "Active", onRemove: vi.fn() }];
      render(<FilterChips chips={chips} onClearAll={handleClearAll} />);

      await user.click(screen.getByRole("button", { name: "Clear all" }));
      expect(handleClearAll).toHaveBeenCalledOnce();
    });

    it("does not call other handlers when Clear all is clicked", async () => {
      const user = userEvent.setup();
      const handleRemove = vi.fn();
      const handleClearAll = vi.fn();
      const chips: Chip[] = [{ label: "Active", onRemove: handleRemove }];
      render(<FilterChips chips={chips} onClearAll={handleClearAll} />);

      await user.click(screen.getByRole("button", { name: "Clear all" }));
      expect(handleRemove).not.toHaveBeenCalled();
    });
  });

  describe("conditional rendering on chip changes", () => {
    it("shows chips after transitioning from empty to non-empty", () => {
      const chips: Chip[] = [{ label: "Active", onRemove: vi.fn() }];
      const { rerender } = render(<FilterChips chips={[]} onClearAll={vi.fn()} />);
      expect(screen.queryByText("Active")).not.toBeInTheDocument();

      rerender(<FilterChips chips={chips} onClearAll={vi.fn()} />);
      expect(screen.getByText("Active")).toBeInTheDocument();
    });

    it("hides when all chips are removed", () => {
      const chips: Chip[] = [{ label: "Active", onRemove: vi.fn() }];
      const { rerender } = render(<FilterChips chips={chips} onClearAll={vi.fn()} />);
      expect(screen.getByText("Active")).toBeInTheDocument();

      rerender(<FilterChips chips={[]} onClearAll={vi.fn()} />);
      expect(screen.queryByText("Active")).not.toBeInTheDocument();
      expect(screen.queryByRole("button", { name: "Clear all" })).not.toBeInTheDocument();
    });
  });

  describe("chip remove button aria-label", () => {
    it("uses the chip label in the aria-label", () => {
      const chips: Chip[] = [{ label: "In Progress", onRemove: vi.fn() }];
      render(<FilterChips chips={chips} onClearAll={vi.fn()} />);
      expect(
        screen.getByRole("button", { name: "Remove filter: In Progress" }),
      ).toBeInTheDocument();
    });
  });
});
