import type { RegexFlavourId } from "../../../model/flavour";
import type {
  RegexSyntaxRequest,
  RegexSyntaxResult,
  ReplacementSyntaxResult,
  SyntaxCoverage,
} from "../../../model/syntax";
import type {
  RegexSyntaxProvider,
  ReplacementSyntaxRequest,
} from "../../SyntaxProvider";
import {
  lexicalCoverage,
  parseLexicalPattern,
  type LexicalCaptureDialect,
} from "../lexical-captures";
import { parsePythonReplacement } from "./replacement";

const DIALECT: LexicalCaptureDialect = {
  flavour: "python",
  providerId: "regex-tools-python-lexical",
  providerVersion: "0.3.0",
  engineLabel: "CPython 3.14 re",
  extendedFlag: "x",
  quotedLiterals: false,
  namedCapture: (pattern, opener) => {
    const match = /^\(\?P<([A-Za-z_][A-Za-z0-9_]*)>/u.exec(
      pattern.slice(opener),
    );
    return match?.[1]
      ? { name: match[1], end: opener + match[0].length }
      : undefined;
  },
  unsupportedConstructs: [
    "complete structural nesting and quantifier ownership",
    "inline flag scope in normalized explanations",
    "conditionals, assertions and backreferences as structural nodes",
    "non-ASCII Python identifier capture names in lexical metadata",
  ],
};

export class PythonSyntaxProvider implements RegexSyntaxProvider {
  readonly id = DIALECT.providerId;
  readonly version = DIALECT.providerVersion;
  readonly supportedFlavours = ["python"] as const;

  async parsePattern(request: RegexSyntaxRequest): Promise<RegexSyntaxResult> {
    return parseLexicalPattern(request, DIALECT);
  }

  async parseReplacement(
    request: ReplacementSyntaxRequest,
  ): Promise<ReplacementSyntaxResult> {
    if (request.flavour !== "python") {
      throw new Error(`Unsupported replacement flavour: ${request.flavour}`);
    }
    return parsePythonReplacement(request.replacement, request.captureMetadata);
  }

  getCoverage(flavour: RegexFlavourId): SyntaxCoverage {
    return lexicalCoverage(flavour, DIALECT);
  }
}
