import { createRef } from "react";

import { render, screen } from "@testing-library/react";
import { describe, expect, it } from "vitest";

import { AppCard } from "@/components/ui/app-card";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Separator } from "@/components/ui/separator";
import { Textarea } from "@/components/ui/textarea";
import { Container } from "@/components/layout/container";
import { HeroBadge } from "@/components/layout/hero-badge";
import { SectionHeading } from "@/components/home/section-heading";

describe("Badge", () => {
  it("renders children and default variant classes", () => {
    render(<Badge>New</Badge>);
    const badge = screen.getByText("New");
    expect(badge).toHaveClass("bg-primary");
  });

  it("applies a chosen variant and merges custom classNames", () => {
    render(<Badge variant="success" className="custom-class">OK</Badge>);
    const badge = screen.getByText("OK");
    expect(badge).toHaveClass("bg-status-success-soft");
    expect(badge).toHaveClass("custom-class");
  });

  it("passes through arbitrary props", () => {
    render(<Badge data-testid="b" title="tip">X</Badge>);
    expect(screen.getByTestId("b")).toHaveAttribute("title", "tip");
  });
});

describe("Input", () => {
  it("forwards the ref and renders attributes", () => {
    const ref = createRef<HTMLInputElement>();
    render(<Input ref={ref} type="email" placeholder="you@example.com" disabled />);
    const input = screen.getByPlaceholderText("you@example.com");
    expect(ref.current).toBe(input);
    expect(input).toHaveAttribute("type", "email");
    expect(input).toBeDisabled();
  });

  it("merges custom classes", () => {
    render(<Input className="w-20" aria-label="field" />);
    expect(screen.getByLabelText("field")).toHaveClass("w-20");
  });
});

describe("Textarea", () => {
  it("forwards the ref and renders a default value", () => {
    const ref = createRef<HTMLTextAreaElement>();
    render(<Textarea ref={ref} defaultValue="hello" aria-label="msg" />);
    const textarea = screen.getByLabelText("msg");
    expect(ref.current).toBe(textarea);
    expect(textarea).toHaveValue("hello");
  });
});

describe("Label", () => {
  it("associates with a control via htmlFor", () => {
    render(<Label htmlFor="name">Name</Label>);
    expect(screen.getByText("Name")).toHaveAttribute("for", "name");
  });
});

describe("Separator", () => {
  it("defaults to a horizontal separator", () => {
    const { container } = render(<Separator />);
    expect(container.firstChild).toHaveClass("h-px", "w-full");
  });

  it("supports a vertical orientation", () => {
    const { container } = render(<Separator orientation="vertical" />);
    expect(container.firstChild).toHaveClass("h-full", "w-px");
  });
});

describe("Card family", () => {
  it("composes header, title, description and content", () => {
    render(
      <Card>
        <CardHeader>
          <CardTitle>Title</CardTitle>
          <CardDescription>Desc</CardDescription>
        </CardHeader>
        <CardContent>Body</CardContent>
      </Card>,
    );
    expect(screen.getByRole("heading", { name: "Title" })).toBeInTheDocument();
    expect(screen.getByText("Desc")).toBeInTheDocument();
    expect(screen.getByText("Body")).toBeInTheDocument();
  });
});

describe("AppCard", () => {
  it("renders a single-layer card with its children", () => {
    render(<AppCard layer="single">Single</AppCard>);
    expect(screen.getByText("Single")).toBeInTheDocument();
  });

  it("renders a double-layer card (default) with its children", () => {
    render(<AppCard>Double</AppCard>);
    expect(screen.getByText("Double")).toBeInTheDocument();
  });
});

describe("Container", () => {
  it("applies the size variant classes", () => {
    const { container } = render(<Container size="narrow">Body</Container>);
    expect(container.firstChild).toHaveClass("max-w-narrow");
  });

  it("renders as a child element when asChild is set", () => {
    render(
      <Container asChild>
        <section data-testid="as-child">X</section>
      </Container>,
    );
    expect(screen.getByTestId("as-child").tagName).toBe("SECTION");
  });
});

describe("HeroBadge", () => {
  it("renders children and optional trailing content", () => {
    render(<HeroBadge trailing={<span>→</span>}>Available</HeroBadge>);
    expect(screen.getByText("Available")).toBeInTheDocument();
    expect(screen.getByText("→")).toBeInTheDocument();
  });
});

describe("SectionHeading", () => {
  it("renders eyebrow, title and description", () => {
    render(<SectionHeading eyebrow="Work" title="Projects" description="What I build" />);
    expect(screen.getByText("Work")).toBeInTheDocument();
    expect(screen.getByRole("heading", { name: "Projects" })).toBeInTheDocument();
    expect(screen.getByText("What I build")).toBeInTheDocument();
  });

  it("centers content when align is center", () => {
    const { container } = render(
      <SectionHeading eyebrow="E" title="T" description="D" align="center" />,
    );
    expect(container.firstChild).toHaveClass("text-center");
  });
});
