/// <reference types="@testing-library/jest-dom" />
import React from "react";
import { Checklist } from "./index";

import { render, screen } from "@testing-library/react";

jest.mock("@shared/components/list", () => ({
  List: ({
    children,
    className,
  }: {
    children: React.ReactNode;
    className?: string;
  }) => (
    <ul data-testid="list" className={className}>
      {children}
    </ul>
  ),
  ListItem: ({
    children,
    className,
  }: {
    children: React.ReactNode;
    className?: string;
  }) => (
    <li data-testid="list-item" className={className}>
      {children}
    </li>
  ),
}));

jest.mock("@shared/components/material-icon", () => ({
  MaterialIcon: ({
    name,
    size,
    color,
    className,
  }: {
    name: string;
    size?: number;
    color?: string;
    className?: string;
  }) => (
    <span
      data-testid={`icon-${name}`}
      data-size={size}
      data-color={color}
      className={className}
    >
      {name}
    </span>
  ),
}));

jest.mock("@shared/components/text", () => ({
  Text: ({
    children,
  }: {
    children: React.ReactNode;
    as?: React.ElementType;
  }) => <div data-testid="text-component">{children}</div>,
}));

jest.mock("@shared/utils/cx", () => ({
  cx: (...args: unknown[]) => args.filter(Boolean).join(" "),
}));

describe("Checklist", () => {
  describe("rendering", () => {
    it("renders null when items is empty", () => {
      const { container } = render(<Checklist items={[]} />);
      expect(container.firstChild).toBeNull();
    });

    it("renders null when items is undefined", () => {
      const { container } = render(
        <Checklist items={undefined as unknown as React.ReactNode[]} />
      );
      expect(container.firstChild).toBeNull();
    });

    it("renders a list with items", () => {
      render(<Checklist items={["Item 1", "Item 2", "Item 3"]} />);
      const listItems = screen.getAllByTestId("list-item");
      expect(listItems).toHaveLength(3);
    });

    it("renders item text content", () => {
      render(<Checklist items={["First item", "Second item"]} />);
      expect(screen.getByText("First item")).toBeInTheDocument();
      expect(screen.getByText("Second item")).toBeInTheDocument();
    });

    it("renders ReactNode items", () => {
      render(
        <Checklist
          items={[
            <strong key="1">Bold item</strong>,
            <em key="2">Italic item</em>,
          ]}
        />
      );
      expect(screen.getByText("Bold item")).toBeInTheDocument();
      expect(screen.getByText("Italic item")).toBeInTheDocument();
    });

    it("applies displayName correctly", () => {
      expect(Checklist.displayName).toBe("Checklist");
    });
  });

  describe("icons", () => {
    it("renders check icons by default", () => {
      render(<Checklist items={["Item 1"]} />);
      expect(screen.getByTestId("icon-check")).toBeInTheDocument();
    });

    it("renders custom icon name", () => {
      render(<Checklist items={["Item 1"]} listIconName="check" />);
      expect(screen.getByTestId("icon-check")).toBeInTheDocument();
    });

    it("does not render icons when listIconName is disc", () => {
      render(<Checklist items={["Item 1"]} listIconName="disc" />);
      expect(screen.queryByTestId("icon-check")).not.toBeInTheDocument();
      expect(screen.queryByTestId("icon-disc")).not.toBeInTheDocument();
    });

    it("passes correct iconSize to MaterialIcon", () => {
      render(<Checklist items={["Item"]} iconSize={32} />);
      const icon = screen.getByTestId("icon-check");
      expect(icon).toHaveAttribute("data-size", "32");
    });

    it("uses default iconSize of 20", () => {
      render(<Checklist items={["Item"]} />);
      const icon = screen.getByTestId("icon-check");
      expect(icon).toHaveAttribute("data-size", "20");
    });
  });

  describe("icon colors", () => {
    it("applies green color by default", () => {
      render(<Checklist items={["Item"]} />);
      const icon = screen.getByTestId("icon-check");
      expect(icon).toHaveAttribute("data-color", "#209A61");
    });

    it("applies yellow color", () => {
      render(<Checklist items={["Item"]} iconColor="yellow" />);
      const icon = screen.getByTestId("icon-check");
      expect(icon).toHaveAttribute("data-color", "#F5FF36");
    });

    it("applies blue color", () => {
      render(<Checklist items={["Item"]} iconColor="blue" />);
      const icon = screen.getByTestId("icon-check");
      expect(icon).toHaveAttribute("data-color", "#0393BA");
    });
  });

  describe("icon position", () => {
    it("applies items-center by default (center position)", () => {
      render(<Checklist items={["Item"]} />);
      const listItem = screen.getByTestId("list-item");
      expect(listItem.className).toContain("items-center");
    });

    it("applies items-start for top position", () => {
      render(<Checklist items={["Item"]} iconPosition="top" />);
      const listItem = screen.getByTestId("list-item");
      expect(listItem.className).toContain("items-start");
    });

    it("applies mt-1 to icon when position is top", () => {
      render(<Checklist items={["Item"]} iconPosition="top" />);
      const icon = screen.getByTestId("icon-check");
      expect(icon.className).toContain("mt-1");
    });

    it("does not apply mt-1 to icon when position is center", () => {
      render(<Checklist items={["Item"]} iconPosition="center" />);
      const icon = screen.getByTestId("icon-check");
      expect(icon.className).not.toContain("mt-1");
    });
  });

  describe("classNames", () => {
    it("applies listContainerClassName to the List", () => {
      render(
        <Checklist items={["Item"]} listContainerClassName="custom-list" />
      );
      const list = screen.getByTestId("list");
      expect(list.className).toContain("custom-list");
    });

    it("applies listItemClassName to ListItems", () => {
      render(
        <Checklist
          items={["Item 1", "Item 2"]}
          listItemClassName="custom-item"
        />
      );
      const items = screen.getAllByTestId("list-item");
      items.forEach(item => {
        expect(item.className).toContain("custom-item");
      });
    });

    it("applies iconClassName to the icon", () => {
      render(<Checklist items={["Item"]} iconClassName="custom-icon" />);
      const icon = screen.getByTestId("icon-check");
      expect(icon.className).toContain("custom-icon");
    });
  });

  describe("list variant", () => {
    it("uses unstyled variant when icons are shown", () => {
      render(<Checklist items={["Item"]} />);
      // With icons (default check), the list items should have flex class
      const listItem = screen.getByTestId("list-item");
      expect(listItem.className).toContain("flex");
    });

    it("does not apply flex class when using disc variant", () => {
      render(<Checklist items={["Item"]} listIconName="disc" />);
      const listItem = screen.getByTestId("list-item");
      expect(listItem.className).not.toContain("flex");
    });
  });
});
