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

export interface ComponentContractMetadata {
  name: string;
  kind: PageAst["kind"];
  props: Array<{
    name: string;
    type: string;
    required: boolean;
    default?: string;
    options?: string[];
  }>;
  outputs: Array<{ name: string; payloadName?: string; payloadType?: string }>;
  functions: Array<{
    name: string;
    runtime: string;
    async: boolean;
    parameters: Array<{ name: string; type: string; optional: boolean }>;
    returnType: string;
  }>;
  states: Array<{ name: string; runtime: string; type: string; initializer: string }>;
  computed: Array<{ name: string; type: string; expression: string }>;
  imports: Array<{
    source: string;
    typeOnly: boolean;
    defaultImport?: string;
    namedImports: string[];
  }>;
}

function unionOptions(type: string | undefined): string[] | undefined {
  if (!type || !type.includes("|")) return undefined;
  const values = type
    .split("|")
    .map((part) => part.trim())
    .filter((part) => /^(?:"[^"]*"|'[^']*')$/.test(part))
    .map((part) => part.slice(1, -1));
  return values.length ? values : undefined;
}

export function createComponentContract(ast: PageAst): ComponentContractMetadata {
  return {
    name: ast.name,
    kind: ast.kind,
    props: ast.props.map((prop) => ({
      name: prop.name,
      type: prop.valueType ?? "unknown",
      required: prop.required,
      ...(prop.default !== "undefined" ? { default: prop.default } : {}),
      ...(unionOptions(prop.valueType) ? { options: unionOptions(prop.valueType) } : {}),
    })),
    outputs: ast.outputs.map((output) => ({
      name: output.name,
      ...(output.payload
        ? { payloadName: output.payload.name, payloadType: output.payload.valueType }
        : {}),
    })),
    functions: ast.runtimeFunctions.map((fn) => ({
      name: fn.name,
      runtime: fn.runtime,
      async: fn.async,
      parameters: fn.parameters.map((param) => ({
        name: param.name,
        type: param.valueType ?? "unknown",
        optional: param.optional,
      })),
      returnType: fn.returnType ?? (fn.async ? "Promise<unknown>" : "unknown"),
    })),
    states: ast.states.map((state) => ({
      name: state.name,
      runtime: state.runtime,
      type: state.valueType ?? "unknown",
      initializer: state.expr,
    })),
    computed: ast.computed.map((entry) => ({
      name: entry.name,
      type: entry.valueType ?? "unknown",
      expression: entry.expr,
    })),
    imports: ast.structuredImports.map((entry) => ({
      source: entry.source,
      typeOnly: entry.typeOnly,
      ...(entry.defaultImport ? { defaultImport: entry.defaultImport } : {}),
      namedImports: entry.namedImports.map((named) => named.local),
    })),
  };
}
