#!/usr/bin/env node
'use strict';
// Live view v1 dos wireframes da lumo-mockup — só Node built-ins, sem deps.
// Uso: node wireframe-server.cjs [<dir-de-wireframes>]   (default: ./escopo/wireframes)
// GET  /      -> .html mais recente do diretório + script de live-reload e
//                barra de aprovar/pedir ajuste injetados no fim do <body>.
// GET  /mtime -> {"file":"<nome>","mtime":<ms>} do .html mais recente.
// POST /event -> grava {ts,file,action,comment} em <dir>/../eventos-wireframe.jsonl
// Bind exclusivo em 127.0.0.1, porta efêmera. Sem auth — decisão deliberada,
// ver references/wireframe-companion.md.

const http = require('http');
const fs = require('fs');
const path = require('path');

const dir = path.resolve(process.argv[2] || './escopo/wireframes');
const eventsFile = path.join(dir, '..', 'eventos-wireframe.jsonl');

function newestHtml() {
  let files;
  try { files = fs.readdirSync(dir).filter((f) => f.toLowerCase().endsWith('.html')); }
  catch (err) { return null; }
  let best = null;
  for (const f of files) {
    const full = path.join(dir, f);
    let stat;
    try { stat = fs.statSync(full); } catch (err) { continue; }
    if (!best || stat.mtimeMs > best.mtime) best = { file: f, full, mtime: stat.mtimeMs };
  }
  return best;
}

const INJECTION = `
<script>
(function () {
  var known = null;
  setInterval(function () {
    fetch('/mtime').then(function (r) { return r.json(); }).then(function (d) {
      if (known === null) { known = d.mtime; return; }
      if (d.mtime !== known) { location.reload(); }
    }).catch(function () {});
  }, 1500);
})();
</script>
<div style="position:fixed;left:0;right:0;bottom:0;z-index:99999;display:flex;gap:10px;
  align-items:center;justify-content:center;padding:10px;background:#222;
  font:14px -apple-system,system-ui,sans-serif;box-shadow:0 -2px 8px rgba(0,0,0,.35)">
  <button id="wf-aprovar" style="padding:8px 16px;border:none;border-radius:4px;
    background:#2e7d32;color:#fff;cursor:pointer;font-weight:600">✓ Aprovar este dashboard</button>
  <button id="wf-ajustar" style="padding:8px 16px;border:none;border-radius:4px;
    background:#c62828;color:#fff;cursor:pointer;font-weight:600">✎ Pedir ajuste</button>
</div>
<script>
(function () {
  function post(action, comment) {
    fetch('/event', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ action: action, comment: comment || null })
    });
  }
  document.getElementById('wf-aprovar').onclick = function (ev) {
    post('aprovar');
    ev.target.textContent = 'Aprovado ✓';
  };
  document.getElementById('wf-ajustar').onclick = function () {
    var c = prompt('O que precisa ajustar?');
    if (c === null) return;
    post('ajustar', c);
  };
})();
</script>
`;

function serveIndex(res) {
  const entry = newestHtml();
  if (!entry) {
    res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' });
    res.end('Nenhum .html encontrado em ' + dir);
    return;
  }
  let html;
  try { html = fs.readFileSync(entry.full, 'utf8'); }
  catch (err) {
    res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });
    res.end('Erro lendo ' + entry.file + ': ' + err.message);
    return;
  }
  html = html.includes('</body>')
    ? html.replace('</body>', INJECTION + '</body>')
    : html + INJECTION;
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
  res.end(html);
}

function serveMtime(res) {
  const entry = newestHtml();
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify(entry ? { file: entry.file, mtime: entry.mtime } : { file: null, mtime: null }));
}

function handleEvent(req, res) {
  let body = '';
  req.on('data', (chunk) => { body += chunk; });
  req.on('end', () => {
    let parsed = {};
    try { parsed = JSON.parse(body || '{}'); } catch (err) { parsed = {}; }
    const entry = newestHtml();
    const line = {
      ts: new Date().toISOString(),
      file: entry ? entry.file : null,
      action: parsed.action || null,
      comment: parsed.comment || null,
    };
    try { fs.appendFileSync(eventsFile, JSON.stringify(line) + '\n'); }
    catch (err) {
      res.writeHead(500, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({ ok: false, error: err.message }));
      return;
    }
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ ok: true }));
  });
}

const server = http.createServer((req, res) => {
  const url = (req.url || '/').split('?')[0];
  if (req.method === 'GET' && url === '/') return serveIndex(res);
  if (req.method === 'GET' && url === '/mtime') return serveMtime(res);
  if (req.method === 'POST' && url === '/event') return handleEvent(req, res);
  res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' });
  res.end('not found');
});

server.listen(0, '127.0.0.1', () => {
  const port = server.address().port;
  console.log('LIVE-VIEW: http://127.0.0.1:' + port + '/');
});
