import React from "react";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { Card, CardHeader, CardTitle, CardContent, CardFooter } from "../Card";

describe("Card", () => {
  // Basic rendering tests
  describe("Rendering", () => {
    it("renders card with children", () => {
      render(<Card>Card content</Card>);
      expect(screen.getByText("Card content")).toBeInTheDocument();
    });

    it("renders with custom className", () => {
      render(<Card className="custom-class">Content</Card>);
      const card = screen.getByText("Content").closest("div");
      expect(card).toHaveClass("custom-class");
    });

    it("renders with different variants", () => {
      const { rerender } = render(<Card variant="default">Default</Card>);
      let card = screen.getByText("Default").closest("div");
      expect(card).toHaveClass("bg-card", "border", "border-border");

      rerender(<Card variant="outline">Outline</Card>);
      card = screen.getByText("Outline").closest("div");
      expect(card).toHaveClass("border-2", "border-border", "bg-background");

      rerender(<Card variant="elevated">Elevated</Card>);
      card = screen.getByText("Elevated").closest("div");
      expect(card).toHaveClass("bg-card", "shadow-md");

      rerender(<Card variant="ghost">Ghost</Card>);
      card = screen.getByText("Ghost").closest("div");
      expect(card).toHaveClass("bg-background");
    });

    it("renders with different padding", () => {
      const { rerender } = render(<Card padding="sm">Small</Card>);
      let card = screen.getByText("Small").closest("div");
      expect(card).toHaveClass("p-4");

      rerender(<Card padding="md">Medium</Card>);
      card = screen.getByText("Medium").closest("div");
      expect(card).toHaveClass("p-6");

      rerender(<Card padding="lg">Large</Card>);
      card = screen.getByText("Large").closest("div");
      expect(card).toHaveClass("p-8");

      rerender(<Card padding="none">None</Card>);
      card = screen.getByText("None").closest("div");
      expect(card).not.toHaveClass("p-4", "p-6", "p-8");
    });
  });

  // Props tests
  describe("Props", () => {
    it("handles hover prop", () => {
      render(<Card hover>Hover content</Card>);
      const card = screen.getByText("Hover content").closest("div");
      expect(card).toHaveClass("hover:shadow-md");
    });

    it("handles clickable prop", () => {
      render(<Card clickable>Clickable content</Card>);
      const card = screen.getByText("Clickable content").closest("div");
      expect(card).toHaveClass("cursor-pointer", "hover:shadow-md");
    });

    it("makes card clickable when onClick is provided", () => {
      const handleClick = jest.fn();
      render(<Card onClick={handleClick}>Click me</Card>);
      const card = screen.getByText("Click me").closest("div");
      expect(card).toHaveClass("cursor-pointer");
    });
  });

  // Interaction tests
  describe("Interactions", () => {
    it("calls onClick when clicked", async () => {
      const handleClick = jest.fn();
      const user = userEvent.setup();
      render(<Card onClick={handleClick}>Click me</Card>);

      await user.click(screen.getByText("Click me"));
      expect(handleClick).toHaveBeenCalledTimes(1);
    });

    it("supports keyboard interaction when clickable", async () => {
      const handleClick = jest.fn();
      const user = userEvent.setup();
      render(
        <Card onClick={handleClick} clickable>
          Clickable
        </Card>
      );

      const card = screen.getByText("Clickable").closest("div");
      expect(card).toHaveAttribute("tabIndex", "0");

      // Focus and press Enter
      card?.focus();
      await user.keyboard("{Enter}");
      expect(handleClick).toHaveBeenCalledTimes(1);

      // Press Space
      await user.keyboard(" ");
      expect(handleClick).toHaveBeenCalledTimes(2);
    });
  });

  // Edge cases
  describe("Edge cases", () => {
    it("forwards ref correctly", () => {
      const ref = React.createRef<HTMLDivElement>();
      render(<Card ref={ref}>Content</Card>);
      expect(ref.current).toBeInstanceOf(HTMLDivElement);
    });
  });
});

describe("CardHeader", () => {
  it("renders with children", () => {
    render(<CardHeader>Header content</CardHeader>);
    expect(screen.getByText("Header content")).toBeInTheDocument();
  });

  it("renders with custom className", () => {
    render(<CardHeader className="custom-header">Header</CardHeader>);
    const header = screen.getByText("Header");
    expect(header).toHaveClass("custom-header");
  });

  it("has proper default styling", () => {
    render(<CardHeader>Header</CardHeader>);
    const header = screen.getByText("Header");
    expect(header).toHaveClass("flex", "flex-col", "space-y-1.5", "p-6");
  });

  it("forwards ref correctly", () => {
    const ref = React.createRef<HTMLDivElement>();
    render(<CardHeader ref={ref}>Header</CardHeader>);
    expect(ref.current).toBeInstanceOf(HTMLDivElement);
  });
});

describe("CardTitle", () => {
  it("renders with children", () => {
    render(<CardTitle>Title content</CardTitle>);
    expect(screen.getByText("Title content")).toBeInTheDocument();
  });

  it("renders with custom className", () => {
    render(<CardTitle className="custom-title">Title</CardTitle>);
    const title = screen.getByText("Title");
    expect(title).toHaveClass("custom-title");
  });

  it("renders with different heading levels", () => {
    const { rerender } = render(<CardTitle as="h1">Title</CardTitle>);
    let title = screen.getByText("Title");
    expect(title.tagName).toBe("H1");

    rerender(<CardTitle as="h2">Title</CardTitle>);
    title = screen.getByText("Title");
    expect(title.tagName).toBe("H2");

    rerender(<CardTitle as="h3">Title</CardTitle>);
    title = screen.getByText("Title");
    expect(title.tagName).toBe("H3");
  });

  it("defaults to h3", () => {
    render(<CardTitle>Default Title</CardTitle>);
    const title = screen.getByText("Default Title");
    expect(title.tagName).toBe("H3");
  });

  it("forwards ref correctly", () => {
    const ref = React.createRef<HTMLHeadingElement>();
    render(<CardTitle ref={ref}>Title</CardTitle>);
    expect(ref.current).toBeInstanceOf(HTMLHeadingElement);
  });
});

describe("CardContent", () => {
  it("renders with children", () => {
    render(<CardContent>Content here</CardContent>);
    expect(screen.getByText("Content here")).toBeInTheDocument();
  });

  it("renders with custom className", () => {
    render(<CardContent className="custom-content">Content</CardContent>);
    const content = screen.getByText("Content");
    expect(content).toHaveClass("custom-content");
  });

  it("has proper default styling", () => {
    render(<CardContent>Content</CardContent>);
    const content = screen.getByText("Content");
    expect(content).toHaveClass("p-6", "pt-0");
  });

  it("handles noPadding prop", () => {
    render(<CardContent noPadding>No padding</CardContent>);
    const content = screen.getByText("No padding");
    expect(content).not.toHaveClass("p-6", "pt-0");
  });

  it("forwards ref correctly", () => {
    const ref = React.createRef<HTMLDivElement>();
    render(<CardContent ref={ref}>Content</CardContent>);
    expect(ref.current).toBeInstanceOf(HTMLDivElement);
  });
});

describe("CardFooter", () => {
  it("renders with children", () => {
    render(<CardFooter>Footer content</CardFooter>);
    expect(screen.getByText("Footer content")).toBeInTheDocument();
  });

  it("renders with custom className", () => {
    render(<CardFooter className="custom-footer">Footer</CardFooter>);
    const footer = screen.getByText("Footer");
    expect(footer).toHaveClass("custom-footer");
  });

  it("has proper default styling", () => {
    render(<CardFooter>Footer</CardFooter>);
    const footer = screen.getByText("Footer");
    expect(footer).toHaveClass("flex", "items-center", "p-6", "pt-0");
  });

  it("handles different justify options", () => {
    const { rerender } = render(<CardFooter justify="start">Start</CardFooter>);
    let footer = screen.getByText("Start");
    expect(footer).toHaveClass("justify-start");

    rerender(<CardFooter justify="center">Center</CardFooter>);
    footer = screen.getByText("Center");
    expect(footer).toHaveClass("justify-center");

    rerender(<CardFooter justify="end">End</CardFooter>);
    footer = screen.getByText("End");
    expect(footer).toHaveClass("justify-end");

    rerender(<CardFooter justify="between">Between</CardFooter>);
    footer = screen.getByText("Between");
    expect(footer).toHaveClass("justify-between");
  });

  it("forwards ref correctly", () => {
    const ref = React.createRef<HTMLDivElement>();
    render(<CardFooter ref={ref}>Footer</CardFooter>);
    expect(ref.current).toBeInstanceOf(HTMLDivElement);
  });
});
