// @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).
(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 { RawSegmentsPanel } from "./RawSegmentsPanel";

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();
    },
  };
}

describe("RawSegmentsPanel", () => {
  it("test_section_label_includes_count", () => {
    const segments = [
      ["ISA", "00", "          ", "00", "          ", "ZZ", "SUBMITTERID    ", "ZZ", "RECEIVERID     ", "260615", "1200", "^", "00501", "000000001", "0", "P", ":"],
      ["GS", "HC", "SUBMITTERID", "RECEIVERID", "20260615", "1200", "1", "X", "005010X222A1"],
      ["ST", "837", "0001", "005010X222A1"],
    ];

    const { container, unmount } = renderIntoContainer(
      <RawSegmentsPanel rawSegments={segments} />
    );

    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 "Raw Segments"; assert case-insensitively and
    // confirm the visual transform via the className sniff below.
    const text = (label?.textContent ?? "").toLowerCase();
    expect(text).toContain("raw segments");
    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_collapsed_by_default", () => {
    const segments = [
      ["ISA", "00", "          "],
      ["GS", "HC", "X"],
    ];

    const { container, unmount } = renderIntoContainer(
      <RawSegmentsPanel rawSegments={segments} />
    );

    const details = container.querySelector("details");
    expect(details).not.toBeNull();
    // The HTML `open` attribute is absent (not just `false`) when
    // collapsed — assert the attribute is literally missing.
    expect(details?.hasAttribute("open")).toBe(false);

    unmount();
  });

  it("test_clicking_summary_expands_the_panel", () => {
    const segments = [
      ["ISA", "00"],
      ["GS", "HC"],
    ];

    const { container, unmount } = renderIntoContainer(
      <RawSegmentsPanel rawSegments={segments} />
    );

    const details = container.querySelector("details");
    const summary = container.querySelector("summary");
    expect(details).not.toBeNull();
    expect(summary).not.toBeNull();
    // Pre-click: collapsed.
    expect(details?.hasAttribute("open")).toBe(false);

    // Click the summary to expand.
    act(() => {
      summary?.dispatchEvent(
        new MouseEvent("click", { bubbles: true, cancelable: true })
      );
    });

    expect(details?.open).toBe(true);

    unmount();
  });

  it("test_expanded_panel_renders_segments_with_star_separator", () => {
    const segments = [
      ["ISA", "00", "          ", "00", "          ", "ZZ", "SUBMITTERID    "],
      ["GS", "HC", "SUBMITTERID", "RECEIVERID", "20260615", "1200", "1", "X", "005010X222A1"],
    ];

    const { container, unmount } = renderIntoContainer(
      <RawSegmentsPanel rawSegments={segments} />
    );

    const details = container.querySelector("details");
    const summary = container.querySelector("summary");
    expect(summary).not.toBeNull();
    act(() => {
      summary?.dispatchEvent(
        new MouseEvent("click", { bubbles: true, cancelable: true })
      );
    });
    expect(details?.open).toBe(true);

    const pre = container.querySelector('[data-testid="raw-segments-pre"]');
    expect(pre).not.toBeNull();
    const text = pre?.textContent ?? "";

    // First segment: elements joined by "*" on a single line.
    expect(text).toContain("ISA*00*");
    expect(text).toContain("SUBMITTERID    ");
    // Second segment also rendered.
    expect(text).toContain("GS*HC*SUBMITTERID*RECEIVERID*20260615*1200*1*X*005010X222A1");

    // Lines are separated — newlines in the rendered text.
    const lines = text.split("\n");
    expect(lines.length).toBeGreaterThanOrEqual(2);

    unmount();
  });

  it("test_empty_array_renders_count_and_empty_state", () => {
    const { container, unmount } = renderIntoContainer(
      <RawSegmentsPanel rawSegments={[]} />
    );

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

    // Empty-state body is present.
    const empty = container.querySelector('[data-testid="raw-segments-empty"]');
    expect(empty).not.toBeNull();
    expect(empty?.textContent ?? "").toContain("No segments");

    // The <pre> with segments is NOT rendered in the empty state.
    expect(
      container.querySelector('[data-testid="raw-segments-pre"]')
    ).toBeNull();

    // The <details>/<summary> are still present so the user can see
    // the section header even when there's nothing inside.
    const details = container.querySelector("details");
    expect(details).not.toBeNull();
    const summary = container.querySelector("summary");
    expect(summary).not.toBeNull();

    unmount();
  });

  it("test_uses_monospace_font_for_pre_block", () => {
    const segments = [["ST", "837", "0001"]];

    const { container, unmount } = renderIntoContainer(
      <RawSegmentsPanel rawSegments={segments} />
    );

    const summary = container.querySelector("summary");
    act(() => {
      summary?.dispatchEvent(
        new MouseEvent("click", { bubbles: true, cancelable: true })
      );
    });

    const pre = container.querySelector('[data-testid="raw-segments-pre"]');
    expect(pre).not.toBeNull();
    // The mono styling is either via class or inline style; sniff both.
    const cls = pre?.className ?? "";
    const style = pre?.getAttribute("style") ?? "";
    const isMono =
      cls.includes("font-mono") ||
      style.includes("--m-font-mono") ||
      style.includes("font-mono");
    expect(isMono).toBe(true);

    unmount();
  });
});
