/**
 * Tests for ReasonPrompt component.
 *
 * TDD: These tests define the expected behavior before implementation.
 */

import { describe, it, expect, vi, beforeEach } from "vitest";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { ReasonPrompt } from "@/components/ReasonPrompt";

describe("ReasonPrompt", () => {
  const defaultProps = {
    action: "set_focus",
    itemTitle: "Review MR !847",
    onSubmit: vi.fn(),
    onCancel: vi.fn(),
  };

  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("renders with action context", () => {
    render(<ReasonPrompt {...defaultProps} />);

    expect(
      screen.getByText(/Setting focus to.*Review MR !847/i)
    ).toBeInTheDocument();
  });

  it("captures text input", async () => {
    const user = userEvent.setup();
    const onSubmit = vi.fn();
    render(<ReasonPrompt {...defaultProps} onSubmit={onSubmit} />);

    await user.type(
      screen.getByRole("textbox"),
      "Sarah pinged me, she is blocked"
    );
    await user.click(screen.getByRole("button", { name: /confirm/i }));

    expect(onSubmit).toHaveBeenCalledWith(
      expect.objectContaining({
        reason: "Sarah pinged me, she is blocked",
      })
    );
  });

  it("allows selecting quick tags", async () => {
    const user = userEvent.setup();
    const onSubmit = vi.fn();
    render(<ReasonPrompt {...defaultProps} onSubmit={onSubmit} />);

    await user.click(screen.getByRole("button", { name: /blocking/i }));
    await user.click(screen.getByRole("button", { name: /urgent/i }));
    await user.click(screen.getByRole("button", { name: /confirm/i }));

    expect(onSubmit).toHaveBeenCalledWith(
      expect.objectContaining({
        tags: expect.arrayContaining(["blocking", "urgent"]),
      })
    );
  });

  it("toggles tag off when clicked again", async () => {
    const user = userEvent.setup();
    const onSubmit = vi.fn();
    render(<ReasonPrompt {...defaultProps} onSubmit={onSubmit} />);

    const blockingTag = screen.getByRole("button", { name: /blocking/i });

    // Select then deselect
    await user.click(blockingTag);
    await user.click(blockingTag);
    await user.click(screen.getByRole("button", { name: /confirm/i }));

    expect(onSubmit).toHaveBeenCalledWith(
      expect.objectContaining({
        tags: [],
      })
    );
  });

  it("allows skipping reason", async () => {
    const user = userEvent.setup();
    const onSubmit = vi.fn();
    render(<ReasonPrompt {...defaultProps} onSubmit={onSubmit} />);

    await user.click(screen.getByRole("button", { name: /skip reason/i }));

    expect(onSubmit).toHaveBeenCalledWith({
      reason: null,
      tags: [],
    });
  });

  it("trims whitespace from reason", async () => {
    const user = userEvent.setup();
    const onSubmit = vi.fn();
    render(<ReasonPrompt {...defaultProps} onSubmit={onSubmit} />);

    await user.type(screen.getByRole("textbox"), "  spaced reason  ");
    await user.click(screen.getByRole("button", { name: /confirm/i }));

    expect(onSubmit).toHaveBeenCalledWith(
      expect.objectContaining({
        reason: "spaced reason",
      })
    );
  });

  it("treats empty reason as null", async () => {
    const user = userEvent.setup();
    const onSubmit = vi.fn();
    render(<ReasonPrompt {...defaultProps} onSubmit={onSubmit} />);

    // Just click confirm without typing
    await user.click(screen.getByRole("button", { name: /confirm/i }));

    expect(onSubmit).toHaveBeenCalledWith(
      expect.objectContaining({
        reason: null,
      })
    );
  });

  it("cancels on Escape key", async () => {
    const user = userEvent.setup();
    const onCancel = vi.fn();
    render(<ReasonPrompt {...defaultProps} onCancel={onCancel} />);

    await user.keyboard("{Escape}");

    expect(onCancel).toHaveBeenCalled();
  });

  it("displays all quick tag options", () => {
    render(<ReasonPrompt {...defaultProps} />);

    expect(screen.getByRole("button", { name: /blocking/i })).toBeInTheDocument();
    expect(screen.getByRole("button", { name: /urgent/i })).toBeInTheDocument();
    expect(screen.getByRole("button", { name: /context switch/i })).toBeInTheDocument();
    expect(screen.getByRole("button", { name: /energy/i })).toBeInTheDocument();
  });

  it("shows different titles for different actions", () => {
    const { rerender } = render(
      <ReasonPrompt {...defaultProps} action="defer" itemTitle="Issue #42" />
    );
    expect(screen.getByText(/Deferring.*Issue #42/i)).toBeInTheDocument();

    rerender(
      <ReasonPrompt {...defaultProps} action="skip" itemTitle="MR !100" />
    );
    expect(screen.getByText(/Skipping.*MR !100/i)).toBeInTheDocument();
  });
});
