import { render, screen } from "@testing-library/react";
import { describe, expect, test } from "vitest";
import { Avatar, Bubble, BubbleList } from "../src/bubble";

describe("Bubble", () => {
  test("renders text content", () => {
    render(<Bubble text="Hello world" />);
    expect(screen.getByText("Hello world")).toBeInTheDocument();
  });

  test("renders with default size", () => {
    render(<Bubble text="Default size" />);
    const bubble = screen
      .getByText("Default size")
      .closest("[data-slot='bubble']");
    expect(bubble).toHaveClass("px-4", "py-2");
  });

  test("renders with lg size", () => {
    render(<Bubble text="Large size" size="lg" />);
    const bubble = screen
      .getByText("Large size")
      .closest("[data-slot='bubble']");
    expect(bubble).toHaveClass("px-6", "py-3", "text-lg");
  });

  test("renders with sm size", () => {
    render(<Bubble text="Small size" size="sm" />);
    const bubble = screen
      .getByText("Small size")
      .closest("[data-slot='bubble']");
    expect(bubble).toHaveClass("px-3", "py-1", "text-sm");
  });

  test("renders with xs size", () => {
    render(<Bubble text="Extra small" size="xs" />);
    const bubble = screen
      .getByText("Extra small")
      .closest("[data-slot='bubble']");
    expect(bubble).toHaveClass("px-2", "py-1", "text-xs");
  });

  test("renders with md size", () => {
    render(<Bubble text="Medium size" size="md" />);
    const bubble = screen
      .getByText("Medium size")
      .closest("[data-slot='bubble']");
    expect(bubble).toHaveClass("px-4", "py-2", "text-base");
  });

  test("aligns left by default", () => {
    render(<Bubble text="Left aligned" />);
    const bubble = screen
      .getByText("Left aligned")
      .closest("[data-slot='bubble']");
    expect(bubble).toHaveClass("self-start");
  });

  test("aligns right when specified", () => {
    render(<Bubble text="Right aligned" align="right" />);
    const bubble = screen
      .getByText("Right aligned")
      .closest("[data-slot='bubble']");
    expect(bubble).toHaveClass("self-end");
  });

  test("aligns center when specified", () => {
    render(<Bubble text="Center aligned" align="center" />);
    const bubble = screen
      .getByText("Center aligned")
      .closest("[data-slot='bubble']");
    expect(bubble).toHaveClass("self-center");
  });

  test("renders with transparent background", () => {
    render(<Bubble text="Transparent" background="transparent" />);
    const bubble = screen
      .getByText("Transparent")
      .closest("[data-slot='bubble']");
    expect(bubble).toHaveClass("bg-transparent");
  });

  test("renders with solid background", () => {
    render(<Bubble text="Solid" background="solid" />);
    const bubble = screen.getByText("Solid").closest("[data-slot='bubble']");
    expect(bubble).toHaveClass("bg-gray-100", "dark:bg-gray-800");
  });

  test("renders pending state with default indicator", () => {
    render(<Bubble text="test" isPending={true} />);
    const bubble = document.querySelector("[data-slot='bubble']");
    expect(bubble).toBeInTheDocument();
    expect(bubble?.querySelector(".animate-bounce")).toBeTruthy();
  });

  test("renders pending state with custom pending content", () => {
    render(
      <Bubble text="test" isPending={true} pending={<div>Loading...</div>} />,
    );
    expect(screen.getByText("Loading...")).toBeInTheDocument();
  });
});

describe("Avatar", () => {
  test("renders text when no imageUrl", () => {
    render(<Avatar text="John" />);
    expect(screen.getByText("John")).toBeInTheDocument();
  });

  test("renders image when imageUrl provided", () => {
    render(<Avatar text="Jane" imageUrl="https://example.com/avatar.jpg" />);
    const img = screen.getByAltText("Jane");
    expect(img).toHaveAttribute("src", "https://example.com/avatar.jpg");
    expect(img).toHaveClass("object-cover", "rounded-full");
  });

  test("renders with default styles", () => {
    render(<Avatar text="Test" />);
    const avatar = screen.getByText("Test").closest("[data-slot='avatar']");
    expect(avatar).toHaveClass(
      "w-9",
      "h-9",
      "rounded-full",
      "bg-gray-300",
      "dark:bg-gray-800",
    );
  });

  test("renders with custom className", () => {
    render(<Avatar text="Custom" className="w-12 h-12" />);
    const avatar = screen.getByText("Custom").closest("[data-slot='avatar']");
    expect(avatar).toHaveClass("w-12", "h-12");
  });
});

describe("BubbleList", () => {
  const mockMessages = [
    {
      id: "1",
      role: "user" as const,
      parts: [{ type: "text" as const, text: "Hello AI" }],
    },
    {
      id: "2",
      role: "assistant" as const,
      parts: [{ type: "text" as const, text: "Hello human" }],
    },
  ];

  test("renders empty list", () => {
    render(<BubbleList messages={[]} />);
    const container = document.querySelector("[data-slot='bubble-list']");
    expect(container).toBeInTheDocument();
  });

  test("renders messages", () => {
    render(<BubbleList messages={mockMessages} />);
    expect(screen.getByText("Hello AI")).toBeInTheDocument();
    expect(screen.getByText("Hello human")).toBeInTheDocument();
  });

  test("renders footer when provided", () => {
    render(<BubbleList messages={[]} footer={<div>Footer content</div>} />);
    expect(screen.getByText("Footer content")).toBeInTheDocument();
  });

  test("renders pending indicator when isPending is true", () => {
    render(<BubbleList messages={[]} isPending={true} />);
    const pendingBubble = document.querySelector("[data-slot='bubble-item']");
    expect(pendingBubble).toBeTruthy();
  });

  test("renders with right-solid background by default", () => {
    render(<BubbleList messages={mockMessages} />);
    const container = document.querySelector("[data-slot='bubble-list']");
    expect(container).toBeInTheDocument();
  });

  test("renders with assistant avatar", () => {
    render(
      <BubbleList
        messages={mockMessages}
        assistant={{ avatar: { text: "AI" } }}
      />,
    );
    expect(screen.getByText("AI")).toBeInTheDocument();
  });

  test("renders with assistant avatar from string URL", () => {
    render(
      <BubbleList
        messages={mockMessages}
        assistant={{ avatar: { text: "AI Avatar" } }}
      />,
    );
    const avatarContainer = document.querySelector("[data-slot='avatar']");
    expect(avatarContainer?.textContent).toBe("AI Avatar");
  });
});