/*
Unit tests for the Link component:
- Rendering:
  - Renders with default props and checks for default class and attributes.
  - Renders children correctly, including nested elements.
  - Applies custom className when provided.
  - Renders as anchor tag by default and as button when tag prop is set.
- Color Variants:
  - Applies correct class for each color variant (default, orange, black).
  - Combines color with inverse class when both are set.
- Props Forwarding:
  - Forwards additional HTML attributes (target, rel, aria-label, etc.).
  - Forwards event handlers (onClick, onMouseEnter, etc.).
- Warning Messages:
  - Shows warning when anchor tag is used without href.
  - Does not show warning for button tag or anchor with href.
- Edge Cases:
  - Handles empty children.
  - Handles null and undefined props gracefully.
  - Handles complex nested children.
- Accessibility:
  - Has correct role when rendered as link or button.
  - Supports keyboard navigation (click event).
- Component Display Name:
  - Has correct display name 'Link'.
*/
import { fireEvent, render, screen } from "@testing-library/react";
import "@testing-library/jest-dom/vitest";

import { Link } from "../";

// Mock console.warn to test warning messages
const originalWarn = console.warn;
beforeEach(() => {
  console.warn = vi.fn();
});

afterEach(() => {
  console.warn = originalWarn;
});

describe("Link Component", () => {
  describe("Rendering", () => {
    it("renders with default props", () => {
      render(
        <Link href="/test" data-testid="link">
          Test Link
        </Link>,
      );
      const link = screen.getByTestId("link");

      expect(link).toBeInTheDocument();
      expect(link).toHaveClass("link");
      expect(link).toHaveAttribute("href", "/test");
      expect(link).toHaveTextContent("Test Link");
    });

    it("renders children correctly", () => {
      render(
        <Link href="/">
          <span>Custom</span> <strong>Content</strong>
        </Link>,
      );

      expect(screen.getByText("Custom")).toBeInTheDocument();
      expect(screen.getByText("Content")).toBeInTheDocument();
    });

    it("applies custom className", () => {
      render(
        <Link href="/" className="custom-class" data-testid="link">
          Test
        </Link>,
      );
      const link = screen.getByTestId("link");
      expect(link).toHaveClass("link", "custom-class");
    });

    it("renders as anchor tag by default", () => {
      render(
        <Link href="/" data-testid="link">
          Test
        </Link>,
      );
      const link = screen.getByTestId("link");
      expect(link.tagName).toBe("A");
      expect(link).toHaveAttribute("href", "/");
    });

    it("renders as button when tag prop is set to button", () => {
      render(
        <Link tag="button" data-testid="link">
          Test
        </Link>,
      );
      const button = screen.getByTestId("link");
      expect(button.tagName).toBe("BUTTON");
      expect(button).not.toHaveAttribute("href");
    });
  });

  describe("Color Scheme", () => {
    it("applies underline class when isUnderline is true", () => {
      render(
        <Link href="/" isUnderline data-testid="link">
          Underlined link
        </Link>,
      );
      const link = screen.getByTestId("link");
      expect(link).toHaveClass("underline");
    });

    it("applies normal class when isNormal is true", () => {
      render(
        <Link href="/" isNormal data-testid="link">
          Normal link
        </Link>,
      );
      const link = screen.getByTestId("link");
      expect(link).toHaveClass("normal");
    });
  });

  describe("Props Forwarding", () => {
    it("forwards additional HTML attributes", () => {
      render(
        <Link
          href="/"
          data-testid="link"
          target="_blank"
          rel="noopener noreferrer"
          aria-label="External link"
        >
          External link
        </Link>,
      );

      const link = screen.getByTestId("link");
      expect(link).toHaveAttribute("target", "_blank");
      expect(link).toHaveAttribute("rel", "noopener noreferrer");
      expect(link).toHaveAttribute("aria-label", "External link");
    });

    it("forwards event handlers", () => {
      const handleClick = vi.fn();
      const handleMouseEnter = vi.fn();

      render(
        <Link
          href="/"
          data-testid="link"
          onClick={handleClick}
          onMouseEnter={handleMouseEnter}
        >
          Clickable link
        </Link>,
      );

      const link = screen.getByTestId("link");

      fireEvent.click(link);
      expect(handleClick).toHaveBeenCalledTimes(1);

      fireEvent.mouseEnter(link);
      expect(handleMouseEnter).toHaveBeenCalledTimes(1);
    });
  });

  describe("Warning Messages", () => {
    it("shows warning when anchor tag is used without href", () => {
      render(<Link tag="a">Link without href</Link>);

      expect(console.warn).toHaveBeenCalledWith(
        "Anchor element requires a valid address. Provide a valid, navigable address as the href value. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#href",
      );
    });

    it("does not show warning when button tag is used without href", () => {
      render(<Link tag="button">Button link</Link>);

      expect(console.warn).not.toHaveBeenCalled();
    });

    it("does not show warning when anchor tag has href", () => {
      render(<Link href="/">Link with href</Link>);

      expect(console.warn).not.toHaveBeenCalled();
    });
  });

  describe("Edge Cases", () => {
    it("handles empty children", () => {
      render(<Link href="/" data-testid="link" />);

      const link = screen.getByTestId("link");
      expect(link).toBeInTheDocument();
      expect(link).toHaveClass("link");
    });

    it("handles null and undefined props gracefully", () => {
      render(
        <Link href="/" data-testid="link" color={null} className={null}>
          Test
        </Link>,
      );

      const link = screen.getByTestId("link");
      expect(link).toBeInTheDocument();
      expect(link).toHaveClass("link");
    });

    it("handles complex nested children", () => {
      render(
        <Link href="/" data-testid="link">
          <div>
            <span>Nested</span>
            <strong>Content</strong>
            <em>Here</em>
          </div>
        </Link>,
      );

      const link = screen.getByTestId("link");
      expect(link).toBeInTheDocument();
      expect(screen.getByText("Nested")).toBeInTheDocument();
      expect(screen.getByText("Content")).toBeInTheDocument();
      expect(screen.getByText("Here")).toBeInTheDocument();
    });
  });

  describe("Accessibility", () => {
    it("has correct role when rendered as link", () => {
      render(<Link href="/">Accessible link</Link>);

      expect(screen.getByRole("link")).toBeInTheDocument();
    });

    it("has correct role when rendered as button", () => {
      render(<Link tag="button">Accessible button</Link>);

      expect(screen.getByRole("button")).toBeInTheDocument();
    });

    it("supports keyboard navigation", () => {
      const handleClick = vi.fn();

      render(
        <Link href="/" onClick={handleClick} data-testid="link">
          Keyboard accessible
        </Link>,
      );

      const link = screen.getByTestId("link");

      // Test click event
      fireEvent.click(link);
      expect(handleClick).toHaveBeenCalledTimes(1);
    });
  });

  describe("Component Display Name", () => {
    it("has correct display name", () => {
      expect(Link.displayName).toBe("Link");
    });
  });
});
