import type { PageAst } from "@wrnexus/syntax";

function safe(name: string): string {
  return /^[A-Za-z_$][\w$]*$/.test(name) ? name : JSON.stringify(name);
}

export function componentContract(ast: PageAst): string {
  const typeSource = ast.types
    .map((entry) => entry.trim())
    .filter(Boolean)
    .join("\n\n");
  const props = ast.props
    .map(
      (prop) =>
        `  readonly ${safe(prop.name)}${prop.required ? "" : "?"}: ${prop.valueType ?? "unknown"};`,
    )
    .join("\n");
  const outputs = ast.outputs
    .map(
      (output) =>
        `  ${safe(output.name)}(${output.payload ? `${output.payload.name}${output.payload.optional ? "?" : ""}: ${output.payload.valueType}` : ""}): void;`,
    )
    .join("\n");
  const callable = ast.runtimeFunctions
    .filter((fn) => fn.runtime !== "legacy")
    .map(
      (fn) =>
        `  ${safe(fn.name)}(${fn.parameters.map((param) => `${param.name}${param.optional ? "?" : ""}: ${param.valueType ?? "unknown"}`).join(", ")}): ${fn.returnType ?? (fn.async ? "Promise<unknown>" : "unknown")};`,
    )
    .join("\n");
  return `${typeSource ? `${typeSource}\n\n` : ""}export interface ${ast.name}Props {\n${props}\n}\n\nexport interface ${ast.name}Outputs {\n${outputs}\n}\n\nexport interface ${ast.name}Functions {\n${callable}\n}\n\nexport interface ${ast.name}Contract {\n  props: ${ast.name}Props;\n  outputs: ${ast.name}Outputs;\n  functions: ${ast.name}Functions;\n}\n`;
}

export function storeContract(ast: PageAst): string {
  const state = ast.states
    .filter((entry) => entry.runtime !== "server")
    .map((entry) => `  readonly ${safe(entry.name)}: ${entry.valueType ?? "unknown"};`)
    .join("\n");
  const computed = ast.computed
    .map((entry) => `  readonly ${safe(entry.name)}: ${entry.valueType ?? "unknown"};`)
    .join("\n");
  const actions = ast.runtimeFunctions
    .filter((fn) => fn.runtime !== "server")
    .map(
      (fn) =>
        `  ${safe(fn.name)}(${fn.parameters.map((param) => `${param.name}${param.optional ? "?" : ""}: ${param.valueType ?? "unknown"}`).join(", ")}): ${fn.returnType ?? (fn.async ? "Promise<unknown>" : "unknown")};`,
    )
    .join("\n");
  return `export interface ${ast.name}State {\n${state}\n}\n\nexport interface ${ast.name}Computed {\n${computed}\n}\n\nexport interface ${ast.name}Actions {\n${actions}\n}\n\nexport interface ${ast.name}Instance extends ${ast.name}State, ${ast.name}Computed, ${ast.name}Actions {\n  reset(): void;\n  snapshot(): Readonly<${ast.name}State>;\n}\n`;
}
