// @vitest-environment happy-dom
// React's `act` warnings need an act-aware environment; mirror the other
// hook tests in this repo (`useClaimDetail`, `useReconciliation`, ...).
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;

import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { act, cleanup, renderHook, waitFor } from "@testing-library/react";
import { useInboxLanes } from "./useInboxLanes";
import { useTailStore } from "@/store/tail-store";
import type { Claim } from "@/types";

// ---------------------------------------------------------------------------
// SP6 T19: tail-driven refetch.
//
// The hook opens the SP5 claim/remit tail streams and refetches the lane
// payload whenever the tail-store grows (i.e. a new `item` event arrived
// via SSE). We mock `useTailStream` so the test doesn't open a real SSE
// connection, and drive the tail store directly via `useTailStore.setState`
// to simulate what `useTailStream` would have dispatched on an `item`.
// ---------------------------------------------------------------------------

vi.mock("./useTailStream", () => ({
  useTailStream: vi.fn(() => ({
    status: "live",
    lastEventAt: null,
    error: null,
    forceReconnect: vi.fn(),
  })),
}));

afterEach(() => {
  cleanup();
  vi.unstubAllGlobals();
  vi.useRealTimers();
});

function emptyLanesPayload() {
  return {
    ok: true,
    json: async () => ({
      rejected: [],
      // SP14: payer-rejected lane was added to the working surface.
      payer_rejected: [],
      candidates: [],
      unmatched: [],
      done_today: [],
    }),
  };
}

function makeClaim(id: string): Claim {
  return {
    id,
    patientName: "Test Patient",
    providerNpi: "1234567890",
    payerName: "Aetna",
    cptCode: "99213",
    billedAmount: 100,
    receivedAmount: 0,
    status: "submitted",
    submissionDate: "2026-06-20T00:00:00Z",
  };
}

describe("useInboxLanes", () => {
  beforeEach(() => {
    // Each test starts with an empty tail store so length-delta detection
    // fires cleanly on the first simulated `item`.
    useTailStore.getState().reset("claims");
    useTailStore.getState().reset("remittances");
  });

  it("loads lanes on mount", async () => {
    vi.stubGlobal("fetch", vi.fn().mockResolvedValue(emptyLanesPayload()));
    const { result } = renderHook(() => useInboxLanes());
    await waitFor(() => expect(result.current.loading).toBe(false));
    expect(result.current.lanes).toEqual({
      rejected: [],
      payer_rejected: [],
      candidates: [],
      unmatched: [],
      done_today: [],
    });
  });

  it("exposes an error when fetch fails", async () => {
    vi.stubGlobal(
      "fetch",
      vi.fn().mockResolvedValue({ ok: false, status: 500, json: async () => ({}) }),
    );
    const { result } = renderHook(() => useInboxLanes());
    await waitFor(() => expect(result.current.error).not.toBeNull());
    expect(result.current.error?.message).toMatch(/500/);
  });

  it("refetches when a claim arrives via the tail store", async () => {
    const fetchMock = vi.fn().mockResolvedValue(emptyLanesPayload());
    vi.stubGlobal("fetch", fetchMock);

    const { result } = renderHook(() => useInboxLanes());
    await waitFor(() => expect(result.current.loading).toBe(false));
    expect(fetchMock).toHaveBeenCalledTimes(1);

    // Simulate a new claim `item` event from the SP5 stream by writing
    // directly into the tail store — that's what the dispatcher in
    // `useTailStream` does on a real `item` event.
    act(() => {
      useTailStore.getState().addClaim(makeClaim("CLP-NEW"));
    });

    // The hook should debounce-trigger a refetch within ~500ms. We give
    // it a generous timeout to avoid flakiness on slow CI.
    await waitFor(
      () => expect(fetchMock.mock.calls.length).toBeGreaterThan(1),
      { timeout: 1500 },
    );

    // Cleanup: avoid the debounce timer from firing into an unmounted
    // hook (which would log a warning under react-dom 18).
    await act(async () => {
      result.current.refetch;
    });
  });
});
