// @vitest-environment happy-dom
// React Query's internal state updates need an `act`-aware environment or
// it logs noisy warnings. Match the convention from useClaimDetail.test.ts.
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;

import React, { act } from "react";
import { createRoot, type Root } from "react-dom/client";
import { describe, expect, it, vi } from "vitest";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ClaimDrawerError } from "./ClaimDrawerError";

function renderIntoContainer(element: React.ReactElement): {
  container: HTMLDivElement;
  unmount: () => void;
} {
  const container = document.createElement("div");
  document.body.appendChild(container);
  const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  const root: Root = createRoot(container);
  act(() => {
    root.render(
      React.createElement(QueryClientProvider, { client: qc }, element)
    );
  });
  return {
    container,
    unmount: () => {
      act(() => root.unmount());
      container.remove();
    },
  };
}

describe("ClaimDrawerError", () => {
  it("renders_not_found_message_and_close_button", () => {
    // The container surface marks itself with role=alert; that gives AT
    // a single announcement region to listen for.
    const onClose = vi.fn();
    const { container, unmount } = renderIntoContainer(
      <ClaimDrawerError kind="not_found" onClose={onClose} />
    );

    const root = container.firstElementChild as HTMLElement;
    expect(root.getAttribute("role")).toBe("alert");
    expect(
      root.getAttribute("data-testid")?.includes("not_found")
    ).toBe(true);

    // Message body — case-insensitive substring match against "not found".
    const text = (container.textContent ?? "").toLowerCase();
    expect(text).toContain("not found");

    // Close button is wired up.
    const closeBtn = container.querySelector(
      '[data-testid="error-close"]'
    ) as HTMLButtonElement | null;
    expect(closeBtn).not.toBeNull();
    expect(closeBtn?.textContent?.toLowerCase()).toContain("close");
    expect(onClose).not.toHaveBeenCalled();
    act(() => {
      closeBtn?.click();
    });
    expect(onClose).toHaveBeenCalledTimes(1);

    unmount();
  });

  it("renders_network_message_and_retry_button", () => {
    const onRetry = vi.fn();
    const onClose = vi.fn();
    const { container, unmount } = renderIntoContainer(
      <ClaimDrawerError kind="network" onRetry={onRetry} onClose={onClose} />
    );

    // Message body — at least one of the three hints ("network",
    // "connection", "try again") should appear, case-insensitive.
    const text = (container.textContent ?? "").toLowerCase();
    expect(
      text.includes("network") ||
        text.includes("connection") ||
        text.includes("try again")
    ).toBe(true);

    // Retry button fires onRetry.
    const retryBtn = container.querySelector(
      '[data-testid="error-retry"]'
    ) as HTMLButtonElement | null;
    expect(retryBtn).not.toBeNull();
    act(() => {
      retryBtn?.click();
    });
    expect(onRetry).toHaveBeenCalledTimes(1);

    // Close still fires onClose.
    const closeBtn = container.querySelector(
      '[data-testid="error-close"]'
    ) as HTMLButtonElement | null;
    expect(closeBtn).not.toBeNull();
    act(() => {
      closeBtn?.click();
    });
    expect(onClose).toHaveBeenCalledTimes(1);

    unmount();
  });

  it("omits_retry_button_when_onRetry_not_provided", () => {
    const onClose = vi.fn();
    const { container, unmount } = renderIntoContainer(
      <ClaimDrawerError kind="network" onClose={onClose} />
    );

    // No retry button when handler not supplied — no point promising
    // a retry the caller can't fulfill.
    const retryBtn = container.querySelector('[data-testid="error-retry"]');
    expect(retryBtn).toBeNull();

    unmount();
  });

  it("close_button_always_present", () => {
    // not_found branch.
    const onCloseNF = vi.fn();
    const { container: c1, unmount: u1 } = renderIntoContainer(
      <ClaimDrawerError kind="not_found" onClose={onCloseNF} />
    );
    expect(
      c1.querySelector('[data-testid="error-close"]')
    ).not.toBeNull();
    u1();

    // network branch (with retry).
    const onRetry = vi.fn();
    const onCloseNet = vi.fn();
    const { container: c2, unmount: u2 } = renderIntoContainer(
      <ClaimDrawerError
        kind="network"
        onRetry={onRetry}
        onClose={onCloseNet}
      />
    );
    expect(
      c2.querySelector('[data-testid="error-close"]')
    ).not.toBeNull();
    u2();

    // network branch (no retry) — close still required.
    const onCloseNet2 = vi.fn();
    const { container: c3, unmount: u3 } = renderIntoContainer(
      <ClaimDrawerError kind="network" onClose={onCloseNet2} />
    );
    expect(
      c3.querySelector('[data-testid="error-close"]')
    ).not.toBeNull();
    u3();
  });
});