import type { AgentConfig } from "$lib/types/agent-config.js";

/** Escape a value for embedding in a double-quoted TS string literal. */
function q(s: string): string {
  return `"${s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "")}"`;
}

/**
 * Generate a runnable TypeScript file that reconstructs `config` using the
 * public reactive-agents builder API. Mirrors the fields Cortex exposes; the
 * output is meant to be copy-pasted into a project that depends on
 * `reactive-agents`.
 */
export function generateAgentTs(config: AgentConfig, name: string): string {
  const lines: string[] = [];
  lines.push(`import { ReactiveAgents } from "reactive-agents";`);
  lines.push("");
  lines.push(`// Generated by Cortex — agent "${name.replace(/\*\//g, "")}"`);
  lines.push(`const agent = await ReactiveAgents.create()`);

  const chain: string[] = [];
  if (name.trim()) chain.push(`.withName(${q(name)})`);
  if (config.provider) chain.push(`.withProvider(${q(config.provider)})`);

  // Model + sampling params via withModel({ ... })
  const modelParams: string[] = [];
  if (config.model?.trim()) modelParams.push(`model: ${q(config.model)}`);
  if (config.temperature !== undefined) modelParams.push(`temperature: ${config.temperature}`);
  if (config.maxTokens && config.maxTokens > 0) modelParams.push(`maxTokens: ${config.maxTokens}`);
  if (config.numCtx && config.numCtx > 0) modelParams.push(`numCtx: ${config.numCtx}`);
  if (modelParams.length === 1 && modelParams[0]!.startsWith("model: ")) {
    chain.push(`.withModel(${q(config.model)})`);
  } else if (modelParams.length > 0) {
    chain.push(`.withModel({ ${modelParams.join(", ")} })`);
  }

  if (config.systemPrompt?.trim()) chain.push(`.withSystemPrompt(${q(config.systemPrompt)})`);

  // Reasoning: strategy / switching / auditRationale
  const reasoning: string[] = [];
  if (config.strategy && config.strategy !== "reactive") {
    reasoning.push(`defaultStrategy: ${q(config.strategy)}`);
  }
  if (config.strategySwitching) reasoning.push(`enableStrategySwitching: true`);
  if (config.auditRationale) reasoning.push(`auditRationale: true`);
  if (reasoning.length > 0) chain.push(`.withReasoning({ ${reasoning.join(", ")} })`);

  if (config.maxIterations && config.maxIterations > 0) {
    chain.push(`.withMaxIterations(${config.maxIterations})`);
  }

  // Tools
  if (config.tools && config.tools.length > 0) {
    const names = config.tools.map((t) => q(t)).join(", ");
    chain.push(`.withTools({ tools: [${names}] })`);
  } else {
    chain.push(`.withTools()`);
  }

  if (config.memory && (config.memory.working || config.memory.episodic || config.memory.semantic)) {
    const tier = config.memory.episodic || config.memory.semantic ? `"2"` : `"1"`;
    chain.push(`.withMemory(${tier})`);
  }

  if (config.guardrails?.enabled) chain.push(`.withGuardrails()`);

  if (config.persona?.enabled) {
    const p: string[] = [];
    if (config.persona.role?.trim()) p.push(`role: ${q(config.persona.role)}`);
    if (config.persona.tone?.trim()) p.push(`tone: ${q(config.persona.tone)}`);
    chain.push(`.withPersona({ ${p.join(", ")} })`);
  }

  if (config.healthCheck) chain.push(`.withHealthCheck()`);

  // Emit the chain, indented, with .build() last.
  for (const c of chain) lines.push(`  ${c}`);
  lines.push(`  .build();`);
  lines.push("");
  lines.push(`const result = await agent.run("Describe your task here");`);
  lines.push(`console.log(result.output);`);
  lines.push("");

  return lines.join("\n");
}

/** Serialize the agent as a portable JSON config envelope. */
export function generateAgentJson(config: AgentConfig, name: string): string {
  return JSON.stringify({ name, config }, null, 2);
}
