import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi } from "vitest";
import type {
  ReplacementContributionPreview,
  ReplacementPreview,
} from "../regex/replacement/replacement-preview";
import { ReplacementPreviewPanel } from "./ReplacementPreviewPanel";

const contribution: ReplacementContributionPreview = {
  id: "replacement-contribution-1-token-1",
  matchNumber: 1,
  token: {
    id: "token-1",
    kind: "numbered-capture",
    raw: "$1",
    range: { startUtf16: 1, endUtf16: 3 },
    explanation: "Insert numbered capture 1",
    captureNumber: 1,
  },
  valuePreview: "a",
  valueLengthUtf16: 1,
  valueLengthExact: true,
  valueTruncated: false,
  sourceRange: { startUtf16: 0, endUtf16: 1 },
  outputRange: { startUtf16: 1, endUtf16: 2 },
};

const preview: ReplacementPreview = {
  matches: [
    {
      id: "replacement-match-1",
      matchNumber: 1,
      originalRange: { startUtf16: 0, endUtf16: 1 },
      originalPreview: "a",
      originalLengthUtf16: 1,
      originalTruncated: false,
      replacementPreview: "[a]",
      replacementLengthUtf16: 3,
      replacementLengthExact: true,
      replacementTruncated: false,
      outputRange: { startUtf16: 0, endUtf16: 3 },
      contributions: [contribution],
    },
  ],
  totalMatches: 1,
  totalContributions: 1,
  renderedContributions: 1,
  truncated: false,
};

describe("ReplacementPreviewPanel", () => {
  it("shows original, replacement and changed ranges and selects a contribution", async () => {
    const onSelect = vi.fn();
    render(
      <ReplacementPreviewPanel
        preview={preview}
        onSelectContribution={onSelect}
      />,
    );

    expect(screen.getByText("Original match")).toBeInTheDocument();
    expect(screen.getByText("Replacement result")).toBeInTheDocument();
    expect(screen.getByText(/source 0…1 → output 0…3/u)).toBeInTheDocument();
    await userEvent.click(
      screen.getByRole("button", {
        name: /Insert numbered capture 1/u,
      }),
    );
    expect(onSelect).toHaveBeenCalledWith(contribution);
  });
});
