import { describe, it, expect, vi, beforeEach } from "vitest";
import { render, screen, fireEvent, act } from "@testing-library/react";
import { CodeBlock } from "./code-block";

describe("CodeBlock", () => {
  beforeEach(() => {
    Object.assign(navigator, {
      clipboard: {
        writeText: vi.fn().mockResolvedValue(undefined),
      },
    });
  });

  it("renders code content", () => {
    render(<CodeBlock code="const x = 1;" language="javascript" />);
    const codeBlock = screen.getByLabelText("javascript code example");
    expect(codeBlock).toHaveTextContent("const x = 1;");
  });

  it("displays language label", () => {
    render(<CodeBlock code="print('hello')" language="python" />);
    expect(screen.getByText("python")).toBeInTheDocument();
  });

  it("defaults to python language", () => {
    render(<CodeBlock code="x = 1" />);
    expect(screen.getByText("python")).toBeInTheDocument();
  });

  it("has accessible copy button with aria-label", () => {
    render(<CodeBlock code="test" />);
    const button = screen.getByRole("button", {
      name: /copy code to clipboard/i,
    });
    expect(button).toBeInTheDocument();
  });

  it("copies code to clipboard on click", async () => {
    render(<CodeBlock code="const x = 1;" />);
    const button = screen.getByRole("button", {
      name: /copy code to clipboard/i,
    });

    await act(async () => {
      fireEvent.click(button);
    });

    expect(navigator.clipboard.writeText).toHaveBeenCalledWith("const x = 1;");
  });

  it("copies code to clipboard on Enter key", async () => {
    render(<CodeBlock code="const x = 1;" />);
    const button = screen.getByRole("button", {
      name: /copy code to clipboard/i,
    });

    await act(async () => {
      fireEvent.keyDown(button, { key: "Enter" });
    });

    expect(navigator.clipboard.writeText).toHaveBeenCalledWith("const x = 1;");
  });

  it("copies code to clipboard on Space key", async () => {
    render(<CodeBlock code="const x = 1;" />);
    const button = screen.getByRole("button", {
      name: /copy code to clipboard/i,
    });

    await act(async () => {
      fireEvent.keyDown(button, { key: " " });
    });

    expect(navigator.clipboard.writeText).toHaveBeenCalledWith("const x = 1;");
  });

  it("shows 'Copied!' text after copying", async () => {
    vi.useFakeTimers();
    render(<CodeBlock code="test" />);
    const button = screen.getByRole("button", {
      name: /copy code to clipboard/i,
    });

    await act(async () => {
      fireEvent.click(button);
      await Promise.resolve();
    });

    expect(screen.getByText("Copied!")).toBeInTheDocument();

    await act(async () => {
      vi.advanceTimersByTime(2000);
    });

    expect(screen.getByText("Copy")).toBeInTheDocument();
    vi.useRealTimers();
  });
});
