import { parseLLMJson } from '../json-utils.mjs';
import { generateRefinedInstructions, refineInstructions } from '../refined-instructions.mjs';

export const name = 'app-build';
export const description = 'Build a complete application from a description using a multi-stage pipeline';

export async function execute(ctx) {
  const appDescription = ctx.args?.topic || ctx.args?.task || ctx.args?.target || 'a useful web application';

  // ─── STAGE 1: PLAN ───────────────────────────────────────────────────────
  ctx.addEvent('skill', 'agent', 'App Build: Planning...', { stage: 'plan' });

  const planPrompt = `You are a software architect. The user wants to build the following application:

"${appDescription}"

Produce a detailed JSON build plan for a complete, self-contained web application.
The app should be split into focused files (HTML pages, CSS, JavaScript modules, data files, etc.).
Aim for 3–7 files that together form a coherent, working application.

Return ONLY valid JSON (no markdown fences, no explanation):
{
  "name": "app-name-slug",
  "description": "One sentence describing the app",
  "files": [
    { "path": "index.html", "description": "Main entry point / landing page", "type": "html" },
    { "path": "app.js", "description": "Core application logic", "type": "javascript" },
    { "path": "style.css", "description": "Global styles", "type": "css" }
  ]
}`;

  const planRaw = await ctx.askLLM(planPrompt, { model: ctx.pickModel('powerful') });
  const planResult = parseLLMJson(planRaw);

  if (!planResult.ok || !Array.isArray(planResult.data?.files) || planResult.data.files.length === 0) {
    ctx.addEvent('error', 'agent', 'App Build: Plan parsing failed', { stage: 'plan', error: planResult.message });
    return { success: false, error: 'Failed to parse build plan' };
  }

  const plan = planResult.data;
  ctx.addEvent('skill', 'agent', `App Build: Plan ready — ${plan.files.length} files`, {
    stage: 'plan',
    appName: plan.name,
    files: plan.files.map(f => f.path)
  });

  // ─── STAGE 2: BUILD ───────────────────────────────────────────────────────
  const writtenFiles = [];

  for (const file of plan.files) {
    ctx.addEvent('skill', 'agent', `App Build: Building ${file.path}...`, { stage: 'build', file: file.path });

    // Base prompt for this file
    let filePrompt = `You are building "${plan.description}".

Generate the complete content for this file:
  Path: ${file.path}
  Purpose: ${file.description}
  Type: ${file.type}

Context — all files in this app:
${plan.files.map(f => `  - ${f.path}: ${f.description}`).join('\n')}

Previously built files (reference for imports/links):
${writtenFiles.length > 0 ? writtenFiles.map(f => `  - ${f.path} (at /${f.publicPath || f.path})`).join('\n') : '  (none yet)'}

Requirements:
- Write ONLY the file content, no explanation, no markdown fences
- Use relative paths when referencing other files in the app
- Make it production-quality: clean, functional, well-structured
- Include all necessary inline code for this file to work`;

    // Run through the refined-instructions pipeline when available
    try {
      const deps = { askLLM: ctx.askLLM, pickModel: ctx.pickModel };
      const communicated = await generateRefinedInstructions(
        `${file.description} (file: ${file.path}, part of: ${plan.description})`,
        deps
      );
      const refined = await refineInstructions(communicated, deps);
      filePrompt = `${filePrompt}\n\nRefined build specification:\n${refined}`;
    } catch {
      // refined-instructions pipeline unavailable — use base prompt as-is
    }

    const content = await ctx.askLLM(filePrompt, { model: ctx.pickModel('powerful') });

    // Strip accidental markdown fences
    const clean = content
      .replace(/^```[\w]*\s*\n?/i, '')
      .replace(/\n?\s*```\s*$/i, '')
      .trim();

    const written = await ctx.writeOutputFile(file.path, clean);
    writtenFiles.push({ path: file.path, publicPath: written?.publicPath || file.path, name: written?.name || file.path });
    ctx.addEvent('file', 'agent', `App Build: Created ${written?.name || file.path}`, { stage: 'build', path: written?.publicPath });
  }

  // ─── STAGE 3: PUBLISH ────────────────────────────────────────────────────
  ctx.addEvent('skill', 'agent', 'App Build: Publishing index...', { stage: 'publish' });

  const fileLinks = writtenFiles
    .map(f => `          <li><a href="${f.publicPath || f.path}">${f.name || f.path}</a></li>`)
    .join('\n');

  const indexContent = `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>${plan.name || 'App Build Output'}</title>
  <style>
    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
    body {
      font-family: system-ui, -apple-system, sans-serif;
      background: #0f0f13;
      color: #e2e8f0;
      min-height: 100vh;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      padding: 2rem;
    }
    .card {
      background: rgba(255,255,255,0.05);
      border: 1px solid rgba(255,255,255,0.1);
      border-radius: 1rem;
      padding: 2.5rem 3rem;
      max-width: 640px;
      width: 100%;
      backdrop-filter: blur(12px);
    }
    h1 { font-size: 1.8rem; font-weight: 700; margin-bottom: 0.5rem; color: #a78bfa; }
    p.desc { color: #94a3b8; margin-bottom: 2rem; line-height: 1.6; }
    h2 { font-size: 1rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: #64748b; margin-bottom: 1rem; }
    ul { list-style: none; display: flex; flex-direction: column; gap: 0.5rem; }
    li a {
      display: block;
      padding: 0.75rem 1rem;
      background: rgba(167,139,250,0.08);
      border: 1px solid rgba(167,139,250,0.2);
      border-radius: 0.5rem;
      color: #c4b5fd;
      text-decoration: none;
      font-size: 0.95rem;
      transition: background 0.15s, border-color 0.15s;
    }
    li a:hover { background: rgba(167,139,250,0.18); border-color: rgba(167,139,250,0.4); }
    .badge {
      display: inline-block;
      background: #7c3aed;
      color: #fff;
      font-size: 0.7rem;
      padding: 0.15rem 0.5rem;
      border-radius: 999px;
      margin-left: 0.5rem;
      vertical-align: middle;
    }
  </style>
</head>
<body>
  <div class="card">
    <h1>${plan.name || 'App Build Output'} <span class="badge">App Build</span></h1>
    <p class="desc">${plan.description || appDescription}</p>
    <h2>Files</h2>
    <ul>
${fileLinks}
    </ul>
  </div>
</body>
</html>`;

  const indexWritten = await ctx.writeOutputFile('index.html', indexContent);
  ctx.addEvent('file', 'agent', `App Build: Published index — ${writtenFiles.length} files`, {
    stage: 'publish',
    path: indexWritten?.publicPath
  });

  return { success: true, filesCreated: plan.files.length, appName: plan.name };
}

export default { name, description, execute };
