import { describe, it, expect, vi, beforeEach } from "vitest";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { FocusCard } from "@/components/FocusCard";
import type { FocusItem } from "@/lib/types";
import { makeFocusItem as makeItem } from "../helpers/fixtures";

/** FocusCard tests use a richer default with context quote and requestedBy set. */
function makeFocusItem(overrides: Partial<FocusItem> = {}): FocusItem {
  return makeItem({
    contextQuote: "Can you take a look? I need this for the release tomorrow",
    requestedBy: "sarah",
    ...overrides,
  });
}

describe("FocusCard", () => {
  const onStart = vi.fn();
  const onDefer1h = vi.fn();
  const onDeferTomorrow = vi.fn();
  const onSkip = vi.fn();

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

  function renderCard(item: FocusItem = makeFocusItem()) {
    return render(
      <FocusCard
        item={item}
        onStart={onStart}
        onDefer1h={onDefer1h}
        onDeferTomorrow={onDeferTomorrow}
        onSkip={onSkip}
      />
    );
  }

  describe("rendering", () => {
    it("displays the item title", () => {
      renderCard();
      expect(
        screen.getByText("Fix authentication token refresh logic")
      ).toBeInTheDocument();
    });

    it("displays the type badge", () => {
      renderCard();
      expect(screen.getByText(/MR REVIEW/i)).toBeInTheDocument();
    });

    it("displays the project path and IID", () => {
      renderCard();
      expect(screen.getByText(/!847/)).toBeInTheDocument();
      expect(screen.getByText(/platform\/core/)).toBeInTheDocument();
    });

    it("displays the context quote when present", () => {
      renderCard();
      expect(
        screen.getByText(/Can you take a look/)
      ).toBeInTheDocument();
    });

    it("displays who requested attention", () => {
      renderCard();
      expect(screen.getByText(/@sarah/)).toBeInTheDocument();
    });

    it("hides context section when no quote", () => {
      renderCard(makeFocusItem({ contextQuote: null, requestedBy: null }));
      expect(screen.queryByText(/@/)).not.toBeInTheDocument();
    });

    it("shows issue type badge for issues", () => {
      renderCard(makeFocusItem({ type: "issue", iid: 42 }));
      expect(screen.getByText(/ISSUE/i)).toBeInTheDocument();
      expect(screen.getByText(/#42/)).toBeInTheDocument();
    });

    it("shows authored MR badge", () => {
      renderCard(makeFocusItem({ type: "mr_authored" }));
      expect(screen.getByText(/MR AUTHORED/i)).toBeInTheDocument();
    });
  });

  describe("action buttons", () => {
    it("calls onStart when Start button is clicked", async () => {
      const user = userEvent.setup();
      renderCard();

      await user.click(screen.getByRole("button", { name: /start/i }));
      expect(onStart).toHaveBeenCalledOnce();
    });

    it("calls onDefer1h when 1 hour button is clicked", async () => {
      const user = userEvent.setup();
      renderCard();

      await user.click(screen.getByRole("button", { name: /1 hour/i }));
      expect(onDefer1h).toHaveBeenCalledOnce();
    });

    it("calls onDeferTomorrow when Tomorrow button is clicked", async () => {
      const user = userEvent.setup();
      renderCard();

      await user.click(screen.getByRole("button", { name: /tomorrow/i }));
      expect(onDeferTomorrow).toHaveBeenCalledOnce();
    });

    it("calls onSkip when Skip button is clicked", async () => {
      const user = userEvent.setup();
      renderCard();

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

  describe("keyboard shortcuts", () => {
    it("triggers Start on Enter key", async () => {
      const user = userEvent.setup();
      renderCard();

      await user.keyboard("{Enter}");
      expect(onStart).toHaveBeenCalledOnce();
    });

    it("triggers Skip on Cmd+S", async () => {
      const user = userEvent.setup();
      renderCard();

      await user.keyboard("{Meta>}s{/Meta}");
      expect(onSkip).toHaveBeenCalledOnce();
    });
  });
});

describe("FocusCard empty state", () => {
  it("shows empty state message when no item", () => {
    render(
      <FocusCard
        item={null}
        onStart={vi.fn()}
        onDefer1h={vi.fn()}
        onDeferTomorrow={vi.fn()}
        onSkip={vi.fn()}
      />
    );

    expect(screen.getByText(/all clear/i)).toBeInTheDocument();
  });
});
