import { describe, expect, it } from "vitest";
import { JavaSyntaxProvider } from "./JavaSyntaxProvider";

const provider = new JavaSyntaxProvider();

describe("Java lexical syntax provider", () => {
  it("finds ordinary and Java-named captures without counting lookbehind", async () => {
    const result = await provider.parsePattern({
      flavour: "java",
      pattern: String.raw`(?<word>\w+)(?:\s+)(?<=(\d))`,
      flags: [],
      options: {},
    });

    expect(result.accepted).toBe(true);
    expect(result.coverage.status).toBe("partial");
    expect(result.captures).toEqual([
      expect.objectContaining({ number: 1, name: "word" }),
      expect.objectContaining({ number: 2 }),
    ]);
  });

  it("ignores quoted literals, classes and comments-mode text", async () => {
    const result = await provider.parsePattern({
      flavour: "java",
      pattern: String.raw`\Q(captured-looking)\E [(] # (ignored)
      (kept)`,
      flags: ["x"],
      options: {},
    });

    expect(result.captures).toHaveLength(1);
  });

  it("tokenizes TeaVM replacements and rejects its known named-reference gap", async () => {
    const result = await provider.parseReplacement({
      flavour: "java",
      replacement: "${word}-$1-\\$",
      captureMetadata: [
        {
          number: 1,
          name: "word",
          range: { startUtf16: 0, endUtf16: 9 },
          repeated: false,
        },
      ],
    });

    expect(result.accepted).toBe(false);
    expect(result.tokens.map((token) => token.kind)).toEqual([
      "named-capture",
      "literal",
      "numbered-capture",
      "literal",
      "engine-special",
    ]);
    expect(result.diagnostics).toEqual([
      expect.objectContaining({
        code: "engine-compatibility",
        severity: "error",
      }),
    ]);
  });

  it("treats only one digit after $ as a TeaVM capture reference", async () => {
    const result = await provider.parseReplacement({
      flavour: "java",
      replacement: "$12",
      captureMetadata: [
        {
          number: 1,
          range: { startUtf16: 0, endUtf16: 3 },
          repeated: false,
        },
      ],
    });

    expect(result.accepted).toBe(true);
    expect(result.tokens).toEqual([
      expect.objectContaining({ kind: "numbered-capture", raw: "$1" }),
      expect.objectContaining({ kind: "literal", raw: "2" }),
    ]);
  });
});
