import path from 'node:path';
import { mkdir, writeFile, readFile } from 'node:fs/promises';
import { readBody, sendJSON } from '../utils/http.js';
import { toSlug, saveBrief, initSpec, buildSteps } from '../services/specs.js';

export async function handle(req, res, url, ctx) {
  const { cwd, SDD_DIR } = ctx;

  // POST /api/plan
  if (req.method === 'POST' && url.pathname === '/api/plan') {
    try {
      const body = await readBody(req);
      const data = JSON.parse(body);
      const specName = toSlug(data.specName || data.featureName);
      if (data.brief && Object.values(data.brief).some(Boolean)) {
        await saveBrief(specName, { featureName: data.featureName, ...data.brief });
      }
      await initSpec(specName, data.featureName, data.brief);
      const steps = buildSteps(data.featureName, specName, data.projectType, data.includeTasks);
      sendJSON(res, { specName, steps });
    } catch (e) {
      sendJSON(res, { error: e.message }, 500);
    }
    return true;
  }

  // GET /api/resolve-spec?base=slug
  if (req.method === 'GET' && url.pathname === '/api/resolve-spec') {
    try {
      const base = url.searchParams.get('base') || '';
      const specsDir = path.join(cwd, SDD_DIR, 'specs');
      const { readdir, stat } = await import('node:fs/promises');
      const entries = await readdir(specsDir).catch(() => []);
      const matches = entries.filter(e => e === base || e.startsWith(base + '-'));
      if (!matches.length) { sendJSON(res, { specName: base }); return true; }
      let latest = matches[0], latestTime = 0;
      for (const m of matches) {
        try {
          const s = await stat(path.join(specsDir, m, 'spec.json'));
          if (s.mtimeMs > latestTime) { latestTime = s.mtimeMs; latest = m; }
        } catch { /* no spec.json yet */ }
      }
      sendJSON(res, { specName: latest });
    } catch (e) {
      sendJSON(res, { error: e.message }, 500);
    }
    return true;
  }

  // GET /api/files-exist?paths=rel/a.md,rel/b.md
  if (req.method === 'GET' && url.pathname === '/api/files-exist') {
    try {
      const paths = (url.searchParams.get('paths') || '').split(',').filter(Boolean);
      const results = {};
      for (const p of paths) {
        try {
          const content = await readFile(path.join(cwd, p), 'utf8');
          results[p] = content.trim().length > 20;
        } catch { results[p] = false; }
      }
      sendJSON(res, results);
    } catch (e) { sendJSON(res, {}); }
    return true;
  }

  // POST /api/spec-file — write a spec file (used for ADO pull-changes)
  if (req.method === 'POST' && url.pathname === '/api/spec-file') {
    try {
      const { specName, file, content } = JSON.parse(await readBody(req));
      if (!specName || !file || typeof content !== 'string') { sendJSON(res, { error: 'specName, file e content são obrigatórios' }, 400); return true; }
      const safeName = path.basename(file);
      const filePath = path.join(cwd, '.sdd', 'specs', specName, safeName);
      await mkdir(path.dirname(filePath), { recursive: true });
      await writeFile(filePath, content, 'utf8');
      sendJSON(res, { ok: true });
    } catch(e) { sendJSON(res, { error: e.message }, 500); }
    return true;
  }

  // GET /api/steps?specName=X — lê steps.json do disco
  if (req.method === 'GET' && url.pathname === '/api/steps') {
    try {
      const specName = url.searchParams.get('specName');
      if (!specName) { sendJSON(res, { error: 'specName required' }, 400); return true; }
      const raw = await readFile(path.join(cwd, '.sdd', 'specs', specName, 'steps.json'), 'utf8');
      sendJSON(res, JSON.parse(raw));
    } catch { sendJSON(res, { steps: null }); }
    return true;
  }

  // POST /api/steps — salva steps.json no disco
  if (req.method === 'POST' && url.pathname === '/api/steps') {
    try {
      const body = JSON.parse(await readBody(req));
      const { specName } = body;
      if (!specName) { sendJSON(res, { error: 'specName required' }, 400); return true; }
      const dir = path.join(cwd, '.sdd', 'specs', specName);
      await mkdir(dir, { recursive: true });
      await writeFile(path.join(dir, 'steps.json'), JSON.stringify({ ...body, savedAt: new Date().toISOString() }, null, 2), 'utf8');
      sendJSON(res, { ok: true });
    } catch (e) { sendJSON(res, { error: e.message }, 500); }
    return true;
  }

  // GET /api/specs
  if (req.method === 'GET' && url.pathname === '/api/specs') {
    try {
      const { readdir } = await import('node:fs/promises');
      const specsDir = path.join(cwd, SDD_DIR, 'specs');
      const entries = await readdir(specsDir).catch(() => []);
      const specs = [];
      const FILE_STEPS = { init: 'spec.json', requirements: 'requirements.md', design: 'design.md', tasks: 'tasks.md', gap: 'gap-analysis.md' };
      for (const e of entries) {
        const base = path.join(specsDir, e);
        const done = {};
        for (const [k, f] of Object.entries(FILE_STEPS)) {
          try { const c = await readFile(path.join(base, f), 'utf8'); done[k] = c.trim().length > 20; } catch { done[k] = false; }
        }
        let hasSync = false;
        try { await readFile(path.join(base, 'ado-sync.json'), 'utf8'); hasSync = true; } catch {}
        if (done.init || done.requirements) specs.push({ name: e, done, hasSync });
      }
      sendJSON(res, { specs });
    } catch (e) { sendJSON(res, { specs: [] }); }
    return true;
  }

  return false;
}
