import { describe, it, expect, vi } from "vitest";
import { renderToStaticMarkup } from "react-dom/server";

// SSE hook + the server action are deliberately stubbed. The action's
// optimistic result is provided by feeding `useActionState` a manual
// initial state via the mock's exported helper.
const sendTestActionMock = vi.fn();
vi.mock("@/actions/groups", () => ({
  sendTestAction: (...args: unknown[]) => sendTestActionMock(...args),
}));

// Capture the handlers the form passes to useEvents so we can fire
// `send_test.done` ourselves and observe the state transition.
const eventHandlers: {
  "send_test.done"?: (e: { groupId: string; ok: boolean; error: string | null }) => void;
} = {};
vi.mock("@/hooks/use-events", () => ({
  useEvents: (handlers: typeof eventHandlers) => {
    Object.assign(eventHandlers, handlers);
  },
}));

import { SendTestForm } from "./send-test-form";

describe("SendTestForm — initial render", () => {
  it("renders the textarea and submit button, no status pill yet", () => {
    const html = renderToStaticMarkup(<SendTestForm groupId="g-1" />);
    expect(html).toMatch(/<textarea[^>]*name="text"/);
    expect(html).toMatch(/<button[^>]*type="submit"/);
    expect(html).toContain("Send Test");
    // No success / error / in-flight pill on first render.
    expect(html).not.toContain("Sent ✓");
    expect(html).not.toContain("Sending");
    expect(html).not.toContain("role=\"alert\"");
  });

  it("includes the groupId as a hidden input the action will read", () => {
    const html = renderToStaticMarkup(<SendTestForm groupId="abc-uuid" />);
    expect(html).toMatch(/<input[^>]+type="hidden"[^>]+name="groupId"[^>]+value="abc-uuid"/);
  });
});

describe("SendTestForm — wires `send_test.done` events", () => {
  it("registers a `send_test.done` handler with useEvents on render", () => {
    // Reset the captured handlers between tests.
    delete eventHandlers["send_test.done"];

    renderToStaticMarkup(<SendTestForm groupId="g-1" />);

    expect(typeof eventHandlers["send_test.done"]).toBe("function");
  });

  it("the handler ignores events for OTHER groups (won't move our state)", () => {
    // We can't easily inspect React state from SSR markup, but we can
    // at least verify the handler accepts and discards an event with a
    // mismatched groupId without throwing.
    delete eventHandlers["send_test.done"];
    renderToStaticMarkup(<SendTestForm groupId="g-1" />);
    expect(() =>
      eventHandlers["send_test.done"]?.({
        groupId: "g-2",
        ok: true,
        error: null,
      }),
    ).not.toThrow();
  });

  it("the handler accepts a matching success event without throwing", () => {
    delete eventHandlers["send_test.done"];
    renderToStaticMarkup(<SendTestForm groupId="g-1" />);
    expect(() =>
      eventHandlers["send_test.done"]?.({
        groupId: "g-1",
        ok: true,
        error: null,
      }),
    ).not.toThrow();
  });

  it("the handler accepts a matching failure event without throwing", () => {
    delete eventHandlers["send_test.done"];
    renderToStaticMarkup(<SendTestForm groupId="g-1" />);
    expect(() =>
      eventHandlers["send_test.done"]?.({
        groupId: "g-1",
        ok: false,
        error: "Account not connected",
      }),
    ).not.toThrow();
  });
});
