// @vitest-environment happy-dom
// Tell React this is an `act`-aware test environment so react-query's
// internal state updates flush through without noisy console warnings.
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT =
  true;

import React, { act, useEffect } from "react";
import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
import { MemoryRouter, useLocation } from "react-router-dom";
import { createRoot, type Root } from "react-dom/client";
import { ClaimCard837 } from "@/components/ClaimCard837";
import { ClaimCard835 } from "./Upload";
import { useAppStore } from "@/store";
import type { ClaimOutput, ClaimPayment, ParsedBatch } from "@/types";

// Fixtures — kept tiny, just enough to exercise the drill logic.
const CLAIM_837: ClaimOutput = {
  claim_id: "CLM-PERSISTED",
  subscriber: {
    first_name: "Jane",
    last_name: "Doe",
    member_id: "MEM-1",
  },
  payer: { name: "Test Payer", id: "P1" },
  billing_provider: { npi: "1234567890" },
  claim: {
    total_charge: 100,
    place_of_service: "11",
    frequency_code: "1",
    prior_auth: null,
  },
  service_lines: [
    {
      line_number: 1,
      procedure: { qualifier: "HC", code: "99213", modifiers: [] },
      charge: "100",
      units: "1",
      unit_type: "UN",
      service_date: "2026-06-01",
    },
  ],
  diagnoses: [{ qualifier: "ABK", code: "J20.9" }],
  validation: { passed: true, errors: [], warnings: [] },
};

const CLAIM_835: ClaimPayment = {
  payer_claim_control_number: "PCN-PERSISTED",
  status_code: "1",
  status_label: "Processed as Primary",
  claim_filing_indicator: "CI",
  facility_type: "11",
  frequency_code: "1",
  total_charge: "100",
  total_paid: "80",
  patient_responsibility: "20",
  service_payments: [
    {
      line_number: 1,
      procedure_qualifier: "HC",
      procedure_code: "99213",
      modifiers: [],
      service_date: "2026-06-01",
      units: "1",
      unit_type: "UN",
      charge: "100",
      payment: "80",
      adjustments: [],
    },
  ],
  original_claim_id: null,
};

// Mount the card inside a MemoryRouter so the useNavigate call has
// a router context (without this, clicking the drill link would
// throw "useNavigate may be used only in a Router").
function renderCard(
  element: React.ReactElement,
  initialEntries: string[] = ["/upload"],
): {
  container: HTMLDivElement;
  unmount: () => void;
  tracker: { pathname: string; search: string };
} {
  const container = document.createElement("div");
  document.body.appendChild(container);
  const tracker = { pathname: "/upload", search: "" };
  const Tracker = () => {
    const loc = useLocation();
    useEffect(() => {
      tracker.pathname = loc.pathname;
      tracker.search = loc.search;
    }, [loc.pathname, loc.search]);
    return null;
  };
  const root: Root = createRoot(container);
  act(() => {
    root.render(
      React.createElement(
        MemoryRouter,
        { initialEntries },
        React.createElement(Tracker, null),
        element,
      ),
    );
  });
  return {
    container,
    unmount: () => {
      act(() => root.unmount());
      container.remove();
    },
    tracker,
  };
}

describe("ClaimCard837 / ClaimCard835 drill link (SP21 Phase 5 Task 5.7)", () => {
  beforeEach(() => {
    // Reset parsedBatches to empty by default — individual tests
    // populate it as needed.
    useAppStore.setState({ parsedBatches: [] });
  });

  afterEach(() => {
    useAppStore.setState({ parsedBatches: [] });
  });

  it("ClaimCard837: renders the drill link when the claim_id is in a persisted batch", async () => {
    // Pre-populate the store with a parsed batch that contains this
    // claim id, then expand the card and verify the link is present.
    const persisted: ParsedBatch = {
      id: "batch-1",
      kind: "837p",
      inputFilename: "test.837",
      parsedAt: "2026-06-21T12:00:00Z",
      claimCount: 1,
      passed: 1,
      failed: 0,
      claimIds: ["CLM-PERSISTED"],
      summary: { total_claims: 1, passed: 1, failed: 0 },
    };
    useAppStore.setState({ parsedBatches: [persisted] });

    const { container, unmount } = renderCard(
      React.createElement(ClaimCard837, { claim: CLAIM_837 }),
    );

    // Expand the card.
    const header = container.querySelector("button[aria-expanded]");
    await act(async () => {
      (header as HTMLButtonElement).click();
      await Promise.resolve();
    });

    // The drill link should now be visible.
    const link = container.querySelector('[data-testid="upload-claim-drill"]');
    expect(link).not.toBeNull();
    expect(link?.textContent).toContain("See claim in detail");
    unmount();
  });

  it("ClaimCard837: does NOT render the drill link when the claim_id is not persisted", async () => {
    // Streaming-only claim — the parsedBatches slice is empty, so
    // the link must be absent (clicking would 404 ClaimDrawer).
    const { container, unmount } = renderCard(
      React.createElement(ClaimCard837, { claim: CLAIM_837 }),
    );

    const header = container.querySelector("button[aria-expanded]");
    await act(async () => {
      (header as HTMLButtonElement).click();
      await Promise.resolve();
    });

    expect(
      container.querySelector('[data-testid="upload-claim-drill"]'),
    ).toBeNull();
    unmount();
  });

  it("ClaimCard837: clicking the drill link navigates to /claims?claim=ID", async () => {
    const persisted: ParsedBatch = {
      id: "batch-1",
      kind: "837p",
      inputFilename: "test.837",
      parsedAt: "2026-06-21T12:00:00Z",
      claimCount: 1,
      passed: 1,
      failed: 0,
      claimIds: ["CLM-PERSISTED"],
      summary: { total_claims: 1, passed: 1, failed: 0 },
    };
    useAppStore.setState({ parsedBatches: [persisted] });

    const { container, unmount, tracker } = renderCard(
      React.createElement(ClaimCard837, { claim: CLAIM_837 }),
    );

    const header = container.querySelector("button[aria-expanded]");
    await act(async () => {
      (header as HTMLButtonElement).click();
      await Promise.resolve();
    });

    const link = container.querySelector(
      '[data-testid="upload-claim-drill"]',
    ) as HTMLButtonElement;
    await act(async () => {
      link.click();
      await Promise.resolve();
    });

    expect(tracker.pathname).toBe("/claims");
    expect(tracker.search).toBe("?claim=CLM-PERSISTED");
    unmount();
  });

  it("ClaimCard835: renders the drill link when the PCN is persisted", async () => {
    const persisted: ParsedBatch = {
      id: "batch-1",
      kind: "835",
      inputFilename: "test.835",
      parsedAt: "2026-06-21T12:00:00Z",
      claimCount: 1,
      passed: 1,
      failed: 0,
      claimIds: ["PCN-PERSISTED"],
      summary: { total_claims: 1, passed: 1, failed: 0 },
    };
    useAppStore.setState({ parsedBatches: [persisted] });

    const { container, unmount, tracker } = renderCard(
      React.createElement(ClaimCard835, { claim: CLAIM_835 }),
    );

    const header = container.querySelector("button[aria-expanded]");
    await act(async () => {
      (header as HTMLButtonElement).click();
      await Promise.resolve();
    });

    const link = container.querySelector('[data-testid="upload-remit-drill"]');
    expect(link).not.toBeNull();
    await act(async () => {
      (link as HTMLButtonElement).click();
      await Promise.resolve();
    });

    // 835 cards drill to /remittances?remit=PCN (not /claims), since
    // the RemitDrawer is the right surface for the payment side.
    expect(tracker.pathname).toBe("/remittances");
    expect(tracker.search).toBe("?remit=PCN-PERSISTED");
    unmount();
  });

  it("ClaimCard835: does NOT render the drill link when the PCN is not persisted", async () => {
    const { container, unmount } = renderCard(
      React.createElement(ClaimCard835, { claim: CLAIM_835 }),
    );

    const header = container.querySelector("button[aria-expanded]");
    await act(async () => {
      (header as HTMLButtonElement).click();
      await Promise.resolve();
    });

    expect(
      container.querySelector('[data-testid="upload-remit-drill"]'),
    ).toBeNull();
    unmount();
  });
});