import { render } from "@testing-library/react";
import { colors, Tag } from "../Tag";
import { TagButton } from "../TagButton";

describe("rendering", () => {
  describe("initial state", () => {
    it("has default className tag", () => {
      const { getByText } = render(<Tag>Tag</Tag>);
      expect(getByText("Tag")).toHaveClass("tag");
    });
  });

  describe("passed props", () => {
    it("renders children", () => {
      const { getByText } = render(<Tag>Tag</Tag>);
      expect(getByText("Tag")).toBeInTheDocument();
    });

    it("renders children as node", () => {
      const { getByTestId } = render(
        <Tag>
          <span data-testid="child">Children</span>
        </Tag>,
      );
      expect(getByTestId("child")).toBeInTheDocument();
    });

    colors.map((color) => {
      it(`has tag--${color} class when ${color}`, () => {
        const { getByText } = render(
          <Tag color={color} key={color}>
            Tag
          </Tag>,
        );
        expect(getByText("Tag")).toHaveClass(`tag--${color}`);
      });
    });

    it("passes other props", () => {
      const { getByTestId } = render(<Tag data-testid="test">Tag</Tag>);
      expect(getByTestId("test")).toBeInTheDocument();
    });

    describe("size prop", () => {
      it("adds tag--small class when size is small", () => {
        const { getByText } = render(<Tag size="small">Small Tag</Tag>);
        expect(getByText("Small Tag")).toHaveClass("tag--small");
      });

      it("adds tag--large class when size is large", () => {
        const { getByText } = render(<Tag size="large">Large Tag</Tag>);
        expect(getByText("Large Tag")).toHaveClass("tag--large");
      });
    });

    describe("interactive functionality", () => {
      describe("onClick prop", () => {
        it("renders as button when onClick is provided", () => {
          const handleClick = vi.fn();
          const { getByRole } = render(
            <Tag onClick={handleClick}>Clickable Tag</Tag>,
          );
          expect(getByRole("button")).toBeInTheDocument();
          expect(getByRole("button")).toHaveClass("tag");
        });

        it("calls onClick when clicked", () => {
          const handleClick = vi.fn();
          const { getByRole } = render(
            <Tag onClick={handleClick}>Clickable Tag</Tag>,
          );
          getByRole("button").click();
          expect(handleClick).toHaveBeenCalledTimes(1);
        });

        it("does not call onClick when disabled", () => {
          const handleClick = vi.fn();
          const { getByRole } = render(
            <Tag onClick={handleClick} isDisabled>
              Disabled Clickable Tag
            </Tag>,
          );
          expect(getByRole("button")).toBeDisabled();
          expect(getByRole("button")).toHaveAttribute("aria-disabled", "true");
        });

        it("has button type set to 'button'", () => {
          const handleClick = vi.fn();
          const { getByRole } = render(
            <Tag onClick={handleClick}>Clickable Tag</Tag>,
          );
          expect(getByRole("button")).toHaveAttribute("type", "button");
        });
      });

      describe("href prop", () => {
        it("renders as anchor when href is provided", () => {
          const { getByRole } = render(<Tag href="/test">Link Tag</Tag>);
          expect(getByRole("link")).toBeInTheDocument();
          expect(getByRole("link")).toHaveClass("tag");
        });

        it("sets href attribute correctly", () => {
          const { getByRole } = render(<Tag href="/test-url">Link Tag</Tag>);
          expect(getByRole("link")).toHaveAttribute("href", "/test-url");
        });

        it("supports external links with target attribute", () => {
          const { getByRole } = render(
            <Tag href="https://example.com" target="_blank">
              External Link
            </Tag>,
          );
          expect(getByRole("link")).toHaveAttribute(
            "href",
            "https://example.com",
          );
          expect(getByRole("link")).toHaveAttribute("target", "_blank");
        });

        it("sets aria-disabled when isDisabled is true", () => {
          const { getByRole } = render(
            <Tag href="/test" isDisabled>
              Disabled Link Tag
            </Tag>,
          );
          expect(getByRole("link")).toHaveAttribute("aria-disabled", "true");
        });

        it("supports other anchor attributes", () => {
          const { getByRole } = render(
            <Tag href="/test" rel="noopener" title="Test link">
              Link with attributes
            </Tag>,
          );
          expect(getByRole("link")).toHaveAttribute("rel", "noopener");
          expect(getByRole("link")).toHaveAttribute("title", "Test link");
        });
      });

      describe("default rendering", () => {
        it("renders as span when neither onClick nor href is provided", () => {
          const { getByText } = render(<Tag>Default Tag</Tag>);
          expect(getByText("Default Tag").tagName).toBe("SPAN");
        });
      });
    });

    describe("action button", () => {
      it("renders with action button", () => {
        const { getByRole } = render(
          <Tag actionButton={<TagButton iconName="close" ariaLabel="Close" />}>
            Tag with button
          </Tag>,
        );
        expect(getByRole("button")).toBeInTheDocument();
      });

      it("passes size prop to action button", () => {
        const { getByRole } = render(
          <Tag
            size="large"
            actionButton={<TagButton iconName="close" ariaLabel="Close" />}
          >
            Large Tag with button
          </Tag>,
        );
        expect(getByRole("button")).toHaveClass("tag__action--large");
      });

      it("passes isDisabled prop to action button", () => {
        const { getByRole } = render(
          <Tag
            isDisabled
            actionButton={<TagButton iconName="close" ariaLabel="Close" />}
          >
            Disabled Tag with button
          </Tag>,
        );
        expect(getByRole("button")).toHaveAttribute("aria-disabled", "true");
      });
    });
  });
});
