// @vitest-environment happy-dom
// Pure prop-driven component; match the act() convention used by the
// other ClaimDrawer test files (ClaimDrawerHeader / ClaimDrawerSkeleton /
// ClaimDrawerError / ValidationPanel / ServiceLinesTable / DiagnosesList
// / PartiesGrid / RawSegmentsPanel / MatchedRemitCard).
(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 } from "vitest";
import { StateHistoryTimeline } from "./StateHistoryTimeline";
import type { ClaimDetailStateHistoryEvent } from "@/types";

function renderIntoContainer(element: React.ReactElement): {
  container: HTMLDivElement;
  unmount: () => void;
} {
  const container = document.createElement("div");
  document.body.appendChild(container);
  const root: Root = createRoot(container);
  act(() => {
    root.render(element);
  });
  return {
    container,
    unmount: () => {
      act(() => root.unmount());
      container.remove();
    },
  };
}

function makeEvent(
  overrides: Partial<ClaimDetailStateHistoryEvent> = {}
): ClaimDetailStateHistoryEvent {
  return {
    kind: "claim_submitted",
    ts: "2026-06-12T10:30:00Z",
    batchId: null,
    remittanceId: null,
    ...overrides,
  };
}

describe("StateHistoryTimeline", () => {
  it("test_section_label_includes_count", () => {
    const events = [
      makeEvent({ kind: "claim_submitted" }),
      makeEvent({ kind: "claim_accepted" }),
      makeEvent({ kind: "claim_paid" }),
    ];

    const { container, unmount } = renderIntoContainer(
      <StateHistoryTimeline history={events} />
    );

    const label = container.querySelector('[data-testid="section-label"]');
    expect(label).not.toBeNull();

    // `uppercase` is applied via Tailwind CSS, so textContent gives the
    // source-case string "State History"; assert case-insensitively and
    // confirm the visual transform via the className sniff below.
    const text = (label?.textContent ?? "").toLowerCase();
    expect(text).toContain("state history");
    expect(text).toContain("(3)");

    // Eyebrow style (uppercase + tracking) — sniff the className.
    // The shared `.eyebrow` class in index.css consolidates the
    // eyebrow treatment; tests assert it lands on the section label.
    const cls = label?.className ?? "";
    expect(cls).toContain("eyebrow");

    unmount();
  });

  it("test_empty_array_renders_empty_state", () => {
    const { container, unmount } = renderIntoContainer(
      <StateHistoryTimeline history={[]} />
    );

    const empty = container.querySelector('[data-testid="state-history-empty"]');
    expect(empty).not.toBeNull();
    expect(empty?.textContent ?? "").toContain("No history events");

    // No timeline rendered in the empty state.
    expect(
      container.querySelector('[data-testid="state-history-timeline"]')
    ).toBeNull();
    expect(
      container.querySelectorAll('[data-testid="state-history-item"]').length
    ).toBe(0);

    // Section label still present, but with count "(0)".
    const label = container.querySelector('[data-testid="section-label"]');
    expect(label?.textContent ?? "").toContain("(0)");

    unmount();
  });

  it("test_single_event_renders_one_row_with_kind_and_ts", () => {
    const events = [
      makeEvent({ kind: "claim_paid", ts: "2026-06-12T10:30:00Z" }),
    ];

    const { container, unmount } = renderIntoContainer(
      <StateHistoryTimeline history={events} />
    );

    const items = container.querySelectorAll('[data-testid="state-history-item"]');
    expect(items.length).toBe(1);

    const text = items[0].textContent ?? "";
    // Kind rendered (underscore replaced with space, case insensitive).
    expect(text.toLowerCase()).toContain("claim paid");
    // ts formatted via fmt.date — at minimum the year is rendered.
    expect(text).toContain("2026");

    unmount();
  });

  it("test_multiple_events_render_in_input_order", () => {
    const events = [
      makeEvent({ kind: "claim_submitted", ts: "2026-06-10T10:00:00Z" }),
      makeEvent({ kind: "claim_accepted", ts: "2026-06-11T11:00:00Z" }),
      makeEvent({ kind: "remit_received", ts: "2026-06-12T12:00:00Z" }),
      makeEvent({ kind: "claim_paid", ts: "2026-06-13T13:00:00Z" }),
    ];

    const { container, unmount } = renderIntoContainer(
      <StateHistoryTimeline history={events} />
    );

    const items = Array.from(
      container.querySelectorAll('[data-testid="state-history-item"]')
    );
    expect(items.length).toBe(4);

    const kinds = items.map(
      (li) => li.getAttribute("data-kind") ?? ""
    );
    // The backend returns events most-recent-first; the component must
    // render them in input order without resorting, so a re-sorting
    // reordering would be visible here.
    expect(kinds).toEqual([
      "claim_submitted",
      "claim_accepted",
      "remit_received",
      "claim_paid",
    ]);

    unmount();
  });

  it.each([
    [
      "claim_submitted",
      "bg-[color:var(--m-ink-secondary)]",
    ],
    [
      "claim_accepted",
      "bg-[color:var(--m-success)]",
    ],
    [
      "claim_paid",
      "bg-[color:var(--m-success)]",
    ],
    [
      "claim_denied",
      "bg-[color:var(--m-error)]",
    ],
    [
      "manual_match",
      "bg-[color:var(--m-warning)]",
    ],
    [
      "manual_unmatch",
      "bg-[color:var(--m-warning)]",
    ],
    [
      "remit_received",
      "bg-[color:var(--m-accent)]",
    ],
    [
      "something_unknown",
      "bg-[color:var(--m-ink-tertiary)]",
    ],
  ])(
    "test_dot_color_for_kind_%s",
    (kind, expectedClass) => {
      const { container, unmount } = renderIntoContainer(
        <StateHistoryTimeline
          history={[makeEvent({ kind })]}
        />
      );

      const dot = container.querySelector('[data-testid="state-history-dot"]');
      expect(dot).not.toBeNull();
      const cls = dot?.className ?? "";
      expect(cls).toContain(expectedClass);

      unmount();
    }
  );

  it("test_event_with_remittanceId_renders_id", () => {
    const events = [
      makeEvent({
        kind: "remit_received",
        remittanceId: "REM-2026-0007",
      }),
    ];

    const { container, unmount } = renderIntoContainer(
      <StateHistoryTimeline history={events} />
    );

    const id = container.querySelector('[data-testid="history-remit-id"]');
    expect(id).not.toBeNull();
    expect(id?.textContent ?? "").toContain("REM-2026-0007");

    unmount();
  });

  it("test_event_without_remittanceId_does_not_render_id", () => {
    const events = [
      makeEvent({ kind: "claim_submitted", remittanceId: null }),
    ];

    const { container, unmount } = renderIntoContainer(
      <StateHistoryTimeline history={events} />
    );

    expect(
      container.querySelector('[data-testid="history-remit-id"]')
    ).toBeNull();

    unmount();
  });

  it("test_mixed_events_with_and_without_remit_ids", () => {
    const events = [
      makeEvent({ kind: "claim_submitted", remittanceId: null }),
      makeEvent({
        kind: "remit_received",
        remittanceId: "REM-A",
      }),
      makeEvent({ kind: "claim_paid", remittanceId: null }),
      makeEvent({
        kind: "manual_match",
        remittanceId: "REM-B",
      }),
    ];

    const { container, unmount } = renderIntoContainer(
      <StateHistoryTimeline history={events} />
    );

    const items = container.querySelectorAll('[data-testid="state-history-item"]');
    expect(items.length).toBe(4);

    // Per-row presence of the remittance id element.
    expect(
      items[0].querySelector('[data-testid="history-remit-id"]')
    ).toBeNull();
    expect(
      items[1].querySelector('[data-testid="history-remit-id"]')?.textContent ?? ""
    ).toContain("REM-A");
    expect(
      items[2].querySelector('[data-testid="history-remit-id"]')
    ).toBeNull();
    expect(
      items[3].querySelector('[data-testid="history-remit-id"]')?.textContent ?? ""
    ).toContain("REM-B");

    unmount();
  });
});
