import path from 'node:path';
import { mkdir, writeFile } from 'node:fs/promises';
import { readBody, sendJSON } from '../utils/http.js';
import { parseRequirementsForQA } from '../services/ado-api.js';
import { adoAddQAComment, parseWorkItemId } from '../services/ado-api.js';
import { authSignals } from '../server/job-store.js';
import { startParallelQaRun } from '../server/chrome-cdp.js';
import { generateScenariosFromDiff, generateTestStepsWithClaude } from '../server/chrome-cdp.js';

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

  // POST /api/qa/report — gera relatório HTML formal
  if (req.method === 'POST' && url.pathname === '/api/qa/report') {
    try {
      const { results, specName } = JSON.parse(await readBody(req));
      const summary = results?.summary || {};
      const scenarios = results?.scenarios || [];
      const ts = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
      const passRate = summary.total ? Math.round((summary.pass || 0) * 100 / summary.total) : 0;
      const rows = scenarios.map((sc, i) => {
        const icon = sc.status === 'pass' ? '✓' : sc.status === 'fail' ? '✗' : '○';
        const color = sc.status === 'pass' ? '#16a34a' : sc.status === 'fail' ? '#dc2626' : '#ca8a04';
        return `<tr><td style="padding:8px 12px;border:1px solid #e5e7eb;text-align:center;font-weight:600">${i+1}</td><td style="padding:8px 12px;border:1px solid #e5e7eb">${sc.title || ''}</td><td style="padding:8px 12px;border:1px solid #e5e7eb;font-weight:600;color:${color};text-align:center">${icon} ${(sc.status||'').toUpperCase()}</td><td style="padding:8px 12px;border:1px solid #e5e7eb;font-size:12px;color:#6b7280">${sc.evidence || sc.error || ''}</td></tr>`;
      }).join('');
      const reportHtml = `<!DOCTYPE html><html lang="pt-BR"><head><meta charset="UTF-8"><title>Relatório QA${specName ? ' — '+specName : ''}</title></head><body style="font-family:system-ui,sans-serif;max-width:960px;margin:0 auto;padding:40px 24px;color:#111"><h1 style="font-size:22px;font-weight:700;margin-bottom:4px">Relatório de Qualidade — SDD-FP</h1><p style="color:#6b7280;font-size:13px;margin-bottom:32px">Gerado em ${new Date().toLocaleString('pt-BR')}${specName ? ' · Spec: '+specName : ''}</p><div style="display:flex;gap:16px;margin-bottom:32px"><div style="border:2px solid #6366f1;border-radius:10px;padding:16px 24px;text-align:center"><div style="font-size:28px;font-weight:700;color:#6366f1">${summary.total||0}</div><div style="font-size:12px;color:#6b7280">Total</div></div><div style="border:2px solid #16a34a;border-radius:10px;padding:16px 24px;text-align:center"><div style="font-size:28px;font-weight:700;color:#16a34a">${summary.pass||0}</div><div style="font-size:12px;color:#6b7280">Passou</div></div><div style="border:2px solid #dc2626;border-radius:10px;padding:16px 24px;text-align:center"><div style="font-size:28px;font-weight:700;color:#dc2626">${summary.fail||0}</div><div style="font-size:12px;color:#6b7280">Falhou</div></div><div style="border:2px solid #6366f1;border-radius:10px;padding:16px 24px;text-align:center"><div style="font-size:28px;font-weight:700;color:#6366f1">${passRate}%</div><div style="font-size:12px;color:#6b7280">Taxa de Sucesso</div></div></div><table style="width:100%;border-collapse:collapse"><thead><tr style="background:#f9fafb"><th style="padding:10px 12px;border:1px solid #e5e7eb;text-align:left">#</th><th style="padding:10px 12px;border:1px solid #e5e7eb;text-align:left">Cenário</th><th style="padding:10px 12px;border:1px solid #e5e7eb;text-align:center">Status</th><th style="padding:10px 12px;border:1px solid #e5e7eb;text-align:left">Evidência</th></tr></thead><tbody>${rows}</tbody></table></body></html>`;
      const qaDir = path.join(cwd, '.sdd', 'qa');
      await mkdir(qaDir, { recursive: true });
      const fname = `report-${ts}.html`;
      await writeFile(path.join(qaDir, fname), reportHtml, 'utf8');
      sendJSON(res, { html: reportHtml, filename: fname, filePath: path.join('.sdd', 'qa', fname) });
    } catch(e) { sendJSON(res, { error: e.message }, 500); }
    return true;
  }

  // POST /api/qa/generate-plan
  if (req.method === 'POST' && url.pathname === '/api/qa/generate-plan') {
    try {
      const { specName } = JSON.parse(await readBody(req));
      const scenarios = await parseRequirementsForQA(specName, cwd);
      sendJSON(res, { scenarios });
    } catch (e) { sendJSON(res, { error: e.message }, 500); }
    return true;
  }

  // GET /api/qa/detect-local
  if (req.method === 'GET' && url.pathname === '/api/qa/detect-local') {
    const { createConnection } = await import('node:net');
    const PORTS = [3000, 3001, 3002, 4000, 4200, 5000, 5173, 5174, 8000, 8080, 8888, 9000];
    const check = (port) => new Promise(resolve => {
      const sock = createConnection({ port, host: '127.0.0.1' });
      sock.setTimeout(300);
      sock.on('connect', () => { sock.destroy(); resolve(true); });
      sock.on('error', () => resolve(false));
      sock.on('timeout', () => { sock.destroy(); resolve(false); });
    });
    const results = await Promise.all(PORTS.map(async p => ({ port: p, open: await check(p) })));
    const services = results.filter(r => r.open).map(r => ({ port: r.port, url: 'http://localhost:' + r.port }));
    sendJSON(res, { services });
    return true;
  }

  // GET /api/qa/git-changed-files
  if (req.method === 'GET' && url.pathname === '/api/qa/git-changed-files') {
    try {
      const { execSync: execS } = await import('node:child_process');
      let raw = '';
      try {
        let base;
        try { base = execS('git merge-base HEAD origin/main', { cwd, encoding: 'utf8', stdio: ['ignore','pipe','ignore'] }).trim(); } catch {}
        if (!base) try { base = execS('git merge-base HEAD main', { cwd, encoding: 'utf8', stdio: ['ignore','pipe','ignore'] }).trim(); } catch {}
        if (base) {
          raw = execS(`git diff --name-status ${base}`, { cwd, encoding: 'utf8', stdio: ['ignore','pipe','ignore'] });
        }
      } catch {}
      if (!raw.trim()) {
        try {
          raw = execS('git status --short', { cwd, encoding: 'utf8', stdio: ['ignore','pipe','ignore'] })
            .replace(/^\?\?/gm, 'A');
        } catch {}
      }
      const NOISE = [/package-lock\.json$/, /yarn\.lock$/, /\.lock$/, /\.env/, /^dist\//, /^build\//, /node_modules\//, /\.(png|jpg|jpeg|svg|gif|ico|woff|woff2|ttf|eot|map)$/i];
      const files = raw.trim().split('\n').filter(Boolean).map(line => {
        const parts = line.trim().split(/\s+/);
        const status = parts[0]?.[0] || 'M';
        const filePath = parts.slice(1).join(' ') || parts[0];
        return { status, path: filePath, noise: NOISE.some(re => re.test(filePath)) };
      }).filter(f => f.path && f.path !== f.status);
      sendJSON(res, { files });
    } catch (e) { sendJSON(res, { files: [], error: e.message }); }
    return true;
  }

  // POST /api/qa/generate-plan-from-diff
  if (req.method === 'POST' && url.pathname === '/api/qa/generate-plan-from-diff') {
    try {
      const { filePaths } = JSON.parse(await readBody(req));
      if (!filePaths?.length) { sendJSON(res, { error: 'Nenhum arquivo selecionado' }, 400); return true; }
      const scenarios = await generateScenariosFromDiff(filePaths, cwd);
      sendJSON(res, { scenarios });
    } catch (e) { sendJSON(res, { error: e.message }, 500); }
    return true;
  }

  // POST /api/qa/preview-steps
  if (req.method === 'POST' && url.pathname === '/api/qa/preview-steps') {
    try {
      const { scenarios, urls } = JSON.parse(await readBody(req));
      const creds = (urls || []).filter(u => u.username).map(u => ({ env: u.env, username: u.username, password: u.password }));
      const steps = await generateTestStepsWithClaude(
        scenarios.map((s, i) => ({ ...s, scenarioId: s.scenarioId ?? i })),
        urls || [], creds
      );
      sendJSON(res, { scenarios: steps });
    } catch (e) { sendJSON(res, { error: e.message }, 500); }
    return true;
  }

  // POST /api/qa/run
  if (req.method === 'POST' && url.pathname === '/api/qa/run') {
    try {
      const { specName, urls, scenarios } = JSON.parse(await readBody(req));
      const scenariosWithId = scenarios.map((s, i) => ({ ...s, scenarioId: s.scenarioId ?? i }));
      const jobId = startParallelQaRun(specName || 'qa', urls, scenariosWithId, { headless: true, port: 9224 });
      sendJSON(res, { jobId });
    } catch (e) { sendJSON(res, { error: e.message }, 500); }
    return true;
  }

  // POST /api/qa/ado-post-results
  if (req.method === 'POST' && url.pathname === '/api/qa/ado-post-results') {
    try {
      const { orgUrl, project, pat, workItemUrl, results } = JSON.parse(await readBody(req));
      if (!orgUrl || !project || !pat || !workItemUrl || !results) {
        sendJSON(res, { error: 'Campos obrigatórios: orgUrl, project, pat, workItemUrl, results' }, 400); return true;
      }
      const workItemId = parseWorkItemId(workItemUrl);
      if (!workItemId) { sendJSON(res, { error: 'Não foi possível extrair o ID do work item da URL informada' }, 400); return true; }
      await adoAddQAComment(orgUrl, project, pat, workItemId, results);
      sendJSON(res, { ok: true, workItemId });
    } catch (e) { sendJSON(res, { error: e.message }, 500); }
    return true;
  }

  // POST /api/qa/auth-ready/:jobId — user signals they finished logging in
  if (req.method === 'POST' && url.pathname.startsWith('/api/qa/auth-ready/')) {
    const jobId = url.pathname.split('/').pop();
    const resolve = authSignals.get(jobId);
    if (resolve) { resolve(); sendJSON(res, { ok: true }); }
    else { sendJSON(res, { error: 'Nenhuma autenticação pendente para este job' }, 404); }
    return true;
  }

  // POST /api/qa/demo-parallel — 9 hardcoded scenarios for parallelism demo
  if (req.method === 'POST' && url.pathname === '/api/qa/demo-parallel') {
    const DEMO_SCENARIOS = [
      { scenarioId: 0, title: 'Wikipedia — Inteligência Artificial', steps: [
        { action: 'navigate', url: 'https://en.wikipedia.org/wiki/Artificial_intelligence' },
        { action: 'wait', ms: 1500 },
        { action: 'screenshot', label: 'wikipedia-ai' },
      ]},
      { scenarioId: 1, title: 'GitHub — Trending Repos', steps: [
        { action: 'navigate', url: 'https://github.com/trending' },
        { action: 'wait', ms: 1500 },
        { action: 'screenshot', label: 'github-trending' },
      ]},
      { scenarioId: 2, title: 'DuckDuckGo — Busca Node.js', steps: [
        { action: 'navigate', url: 'https://duckduckgo.com/?q=Node.js+javascript+runtime' },
        { action: 'wait', ms: 1500 },
        { action: 'screenshot', label: 'duckduckgo-nodejs' },
      ]},
      { scenarioId: 3, title: 'MDN — JavaScript Docs', steps: [
        { action: 'navigate', url: 'https://developer.mozilla.org/en-US/docs/Web/JavaScript' },
        { action: 'wait', ms: 1500 },
        { action: 'screenshot', label: 'mdn-js' },
      ]},
      { scenarioId: 4, title: 'Hacker News — Tech Feed', steps: [
        { action: 'navigate', url: 'https://news.ycombinator.com' },
        { action: 'wait', ms: 1500 },
        { action: 'screenshot', label: 'hackernews' },
      ]},
      { scenarioId: 5, title: 'Stack Overflow — JavaScript', steps: [
        { action: 'navigate', url: 'https://stackoverflow.com/questions/tagged/javascript' },
        { action: 'wait', ms: 1500 },
        { action: 'screenshot', label: 'stackoverflow-js' },
      ]},
      { scenarioId: 6, title: 'npm — Pacote Express', steps: [
        { action: 'navigate', url: 'https://www.npmjs.com/package/express' },
        { action: 'wait', ms: 1500 },
        { action: 'screenshot', label: 'npm-express' },
      ]},
      { scenarioId: 7, title: 'Can I Use — CSS Grid', steps: [
        { action: 'navigate', url: 'https://caniuse.com/css-grid' },
        { action: 'wait', ms: 1500 },
        { action: 'screenshot', label: 'caniuse-cssgrid' },
      ]},
      { scenarioId: 8, title: 'DevDocs — API Reference', steps: [
        { action: 'navigate', url: 'https://devdocs.io' },
        { action: 'wait', ms: 1500 },
        { action: 'screenshot', label: 'devdocs' },
      ]},
    ];
    const jobId = startParallelQaRun('demo', [], DEMO_SCENARIOS, { port: 9223, headless: true });
    sendJSON(res, { jobId });
    return true;
  }

  return false;
}
