import { describe, it, expect, beforeEach, vi } from "vitest";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { QuickCapture } from "@/components/QuickCapture";
import { useCaptureStore } from "@/stores/capture-store";
import { invoke } from "@tauri-apps/api";

describe("QuickCapture", () => {
  beforeEach(() => {
    useCaptureStore.setState({
      isOpen: true,
      isSubmitting: false,
      lastCapturedId: null,
      error: null,
    });
    vi.clearAllMocks();
  });

  describe("rendering", () => {
    it("renders nothing when closed", () => {
      useCaptureStore.setState({ isOpen: false });
      const { container } = render(<QuickCapture />);
      expect(container.firstChild).toBeNull();
    });

    it("renders overlay when open", () => {
      render(<QuickCapture />);
      expect(screen.getByPlaceholderText("Capture a thought...")).toBeInTheDocument();
    });

    it("auto-focuses the input", () => {
      render(<QuickCapture />);
      const input = screen.getByPlaceholderText("Capture a thought...");
      expect(input).toHaveFocus();
    });

    it("shows a submit button", () => {
      render(<QuickCapture />);
      expect(screen.getByRole("button", { name: /capture/i })).toBeInTheDocument();
    });
  });

  describe("submission", () => {
    it("calls quick_capture on Enter", async () => {
      const user = userEvent.setup();
      render(<QuickCapture />);

      const input = screen.getByPlaceholderText("Capture a thought...");
      await user.type(input, "Fix the login bug{enter}");

      await waitFor(() => {
        expect(invoke).toHaveBeenCalledWith("quick_capture", {
          title: "Fix the login bug",
        });
      });
    });

    it("calls quick_capture on button click", async () => {
      const user = userEvent.setup();
      render(<QuickCapture />);

      const input = screen.getByPlaceholderText("Capture a thought...");
      await user.type(input, "New feature idea");
      await user.click(screen.getByRole("button", { name: /capture/i }));

      await waitFor(() => {
        expect(invoke).toHaveBeenCalledWith("quick_capture", {
          title: "New feature idea",
        });
      });
    });

    it("does not submit empty input", async () => {
      const user = userEvent.setup();
      render(<QuickCapture />);

      const input = screen.getByPlaceholderText("Capture a thought...");
      await user.type(input, "{enter}");

      expect(invoke).not.toHaveBeenCalledWith("quick_capture", expect.anything());
    });

    it("does not submit whitespace-only input", async () => {
      const user = userEvent.setup();
      render(<QuickCapture />);

      const input = screen.getByPlaceholderText("Capture a thought...");
      await user.type(input, "   {enter}");

      expect(invoke).not.toHaveBeenCalledWith("quick_capture", expect.anything());
    });

    it("closes overlay on successful capture", async () => {
      const user = userEvent.setup();
      render(<QuickCapture />);

      const input = screen.getByPlaceholderText("Capture a thought...");
      await user.type(input, "Quick thought{enter}");

      await waitFor(() => {
        expect(useCaptureStore.getState().isOpen).toBe(false);
      });
    });

    it("shows error on failed capture", async () => {
      (invoke as ReturnType<typeof vi.fn>).mockRejectedValueOnce({
        code: "BEADS_UNAVAILABLE",
        message: "br CLI not found",
        recoverable: true,
      });

      const user = userEvent.setup();
      render(<QuickCapture />);

      const input = screen.getByPlaceholderText("Capture a thought...");
      await user.type(input, "Doomed thought{enter}");

      await waitFor(() => {
        expect(screen.getByRole("alert")).toBeInTheDocument();
      });
    });

    it("disables input during submission", async () => {
      // Make invoke hang
      (invoke as ReturnType<typeof vi.fn>).mockImplementationOnce(
        () => new Promise(() => {})
      );

      const user = userEvent.setup();
      render(<QuickCapture />);

      const input = screen.getByPlaceholderText("Capture a thought...");
      await user.type(input, "Slow thought{enter}");

      await waitFor(() => {
        expect(input).toBeDisabled();
      });
    });
  });

  describe("dismissal", () => {
    it("closes on Escape", async () => {
      const user = userEvent.setup();
      render(<QuickCapture />);

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

      expect(useCaptureStore.getState().isOpen).toBe(false);
    });

    it("closes on backdrop click", async () => {
      const user = userEvent.setup();
      render(<QuickCapture />);

      // Click the backdrop (the outer overlay div)
      const backdrop = screen.getByTestId("capture-backdrop");
      await user.click(backdrop);

      expect(useCaptureStore.getState().isOpen).toBe(false);
    });
  });

  describe("error display", () => {
    it("shows error message from store", () => {
      useCaptureStore.setState({ error: "br CLI not found" });
      render(<QuickCapture />);

      expect(screen.getByRole("alert")).toHaveTextContent("br CLI not found");
    });

    it("clears error when user types", async () => {
      useCaptureStore.setState({ error: "previous error" });
      const user = userEvent.setup();
      render(<QuickCapture />);

      const input = screen.getByPlaceholderText("Capture a thought...");
      await user.type(input, "a");

      expect(useCaptureStore.getState().error).toBeNull();
    });
  });
});
