import { render, screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import type { ExtractionNode } from "../regex/model/match";
import { ExtractionTree } from "./ExtractionTree";

function node(
  id: string,
  children: readonly ExtractionNode[] = [],
): ExtractionNode {
  return {
    id,
    kind: "capture",
    label: id,
    value: id,
    status: "participated",
    children,
    provenance: "engine-result",
  };
}

describe("ExtractionTree", () => {
  it("bounds descendants when the cutoff occurs below an ancestor", () => {
    const nested = node(
      "nested",
      Array.from({ length: 2_100 }, (_, index) => node(`child-${index}`)),
    );
    const roots = [node("root", [nested])];
    const { container } = render(
      <ExtractionTree
        nodes={roots}
        onSelect={vi.fn()}
        repeatedCaptureNumbers={new Set()}
      />,
    );

    expect(container.querySelectorAll('[role="treeitem"]')).toHaveLength(2_000);
    expect(roots[0]?.children[0]?.children).toHaveLength(2_100);
  });

  it("labels UI-only value truncation without changing engine status", () => {
    const value = "x".repeat(101);
    render(
      <ExtractionTree
        nodes={[{ ...node("capture"), value }]}
        onSelect={vi.fn()}
        repeatedCaptureNumbers={new Set()}
      />,
    );

    expect(screen.getByRole("treeitem")).toHaveTextContent(
      /… \(101 UTF-16 units total; UI preview\).*participated/u,
    );
  });

  it("distinguishes a bounded engine prefix from the exact capture range", () => {
    render(
      <ExtractionTree
        nodes={[
          {
            ...node("capture"),
            value: "x".repeat(101),
            status: "truncated",
            range: { startUtf16: 10, endUtf16: 70_010 },
            nativeRange: { start: 10, end: 70_010, unit: "utf16" },
          },
        ]}
        onSelect={vi.fn()}
        repeatedCaptureNumbers={new Set()}
      />,
    );

    expect(screen.getByRole("treeitem")).toHaveTextContent(
      /engine value prefix: 101 of 70,000 UTF-16 units; UI shows the first 100.*UTF-16 range: 10…70010.*native range: 10…70010 utf16/u,
    );
  });
});
