// engine/dashboard/templates-layout.ts — Base layout and shared HTML helpers.
// Dark theme, embedded CSS and JS. No external dependencies.
/** Escape HTML special characters to prevent XSS */
export function escapeHtml(str) {
    return str
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;');
}
/** Minimal Markdown → HTML converter (headings, bold, lists, code blocks) */
export function markdownToHtml(md) {
    const lines = md.split('\n');
    const result = [];
    let inCodeBlock = false;
    let inList = false;
    /** Close open list if needed */
    function closeList() {
        if (inList) {
            result.push('</ul>');
            inList = false;
        }
    }
    for (const line of lines) {
        if (line.startsWith('```')) {
            if (inCodeBlock) {
                closeList();
                result.push('</code></pre>');
                inCodeBlock = false;
            }
            else {
                closeList();
                const lang = line.slice(3).trim();
                result.push(`<pre><code class="lang-${escapeHtml(lang)}">`);
                inCodeBlock = true;
            }
            continue;
        }
        if (inCodeBlock) {
            result.push(escapeHtml(line));
            continue;
        }
        // Headings
        if (line.startsWith('### ')) {
            closeList();
            result.push(`<h3>${escapeHtml(line.slice(4))}</h3>`);
            continue;
        }
        if (line.startsWith('## ')) {
            closeList();
            result.push(`<h2>${escapeHtml(line.slice(3))}</h2>`);
            continue;
        }
        if (line.startsWith('# ')) {
            closeList();
            result.push(`<h1>${escapeHtml(line.slice(2))}</h1>`);
            continue;
        }
        // List items
        if (line.startsWith('- ') || line.startsWith('* ')) {
            if (!inList) {
                result.push('<ul>');
                inList = true;
            }
            result.push(`<li>${renderInline(line.slice(2))}</li>`);
            continue;
        }
        closeList();
        // Table rows (basic)
        if (line.startsWith('|')) {
            result.push(`<div class="md-table-row">${escapeHtml(line)}</div>`);
            continue;
        }
        // Horizontal rule
        if (/^---+$/.test(line.trim())) {
            result.push('<hr>');
            continue;
        }
        // Blank line
        if (line.trim() === '') {
            result.push('<br>');
            continue;
        }
        result.push(`<p>${renderInline(line)}</p>`);
    }
    closeList();
    if (inCodeBlock) {
        result.push('</code></pre>');
    }
    return result.join('\n');
}
/** Render inline markdown: bold, inline code, links */
function renderInline(text) {
    // Escape first, then restore safe patterns
    let out = escapeHtml(text);
    // Bold: **text**
    out = out.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
    // Inline code: `code`
    out = out.replace(/`([^`]+)`/g, '<code>$1</code>');
    return out;
}
/** CSS variables and base reset */
function getBaseReset() {
    return `*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
  :root {
    --bg: #0f172a; --surface: #1e293b; --surface2: #334155; --text: #e2e8f0;
    --text-muted: #94a3b8; --accent: #3b82f6; --border: #334155; --radius: 8px;
    --status-draft: #6b7280; --status-review: #d97706; --status-approved: #2563eb;
    --status-implementing: #ea580c; --status-done: #16a34a;
  }
  body { background: var(--bg); color: var(--text); font-family: system-ui,-apple-system,sans-serif;
         font-size: 15px; line-height: 1.6; min-height: 100vh; }
  a { color: var(--accent); text-decoration: none; }
  a:hover { text-decoration: underline; }
  .container { max-width: 1200px; margin: 0 auto; padding: 0 1.5rem; }
  header { background: var(--surface); border-bottom: 1px solid var(--border);
           padding: 1rem 0; margin-bottom: 2rem; }
  header .container { display: flex; align-items: center; justify-content: space-between; }
  header h1 { font-size: 1.25rem; font-weight: 700; color: var(--text); }
  header h1 span { color: var(--accent); }
  .status-indicator { font-size: 0.8rem; color: var(--text-muted); }
  .status-indicator.disconnected { color: #ef4444; }`;
}
/** CSS for cards, grid, spec layout */
function getComponentStyles() {
    return `.card { background: var(--surface); border: 1px solid var(--border);
          border-radius: var(--radius); padding: 1.25rem; }
  .card h2, .card h3 { font-size: 1rem; font-weight: 600; margin-bottom: 0.75rem; }
  .grid { display: grid; gap: 1rem; }
  .grid-2 { grid-template-columns: repeat(2, 1fr); }
  .spec-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1rem; }
  .spec-card { background: var(--surface); border: 1px solid var(--border);
               border-radius: var(--radius); padding: 1rem; cursor: pointer; transition: border-color 0.2s; }
  .spec-card:hover { border-color: var(--accent); }
  .spec-card .spec-id { font-size: 0.75rem; font-weight: 700; letter-spacing: 0.05em;
                        text-transform: uppercase; margin-bottom: 0.25rem; }
  .spec-card .spec-title { font-size: 0.9rem; font-weight: 500; margin-bottom: 0.75rem; color: var(--text); }
  .spec-card .status-badge { display: inline-block; padding: 0.2rem 0.6rem; border-radius: 4px;
                             font-size: 0.72rem; font-weight: 600; text-transform: uppercase;
                             letter-spacing: 0.05em; color: #fff; margin-bottom: 0.75rem; }
  .status-draft .status-badge { background: var(--status-draft); }
  .status-review .status-badge { background: var(--status-review); }
  .status-approved .status-badge { background: var(--status-approved); }
  .status-implementing .status-badge { background: var(--status-implementing); }
  .status-done .status-badge { background: var(--status-done); }
  .progress-bar-wrap { background: var(--surface2); border-radius: 4px; height: 6px; overflow: hidden; }
  .progress-bar-fill { height: 100%; background: var(--accent); border-radius: 4px; transition: width 0.3s; }
  .progress-text { font-size: 0.75rem; color: var(--text-muted); margin-top: 0.35rem;
                   display: flex; justify-content: space-between; }
  .metric-card { background: var(--surface); border: 1px solid var(--border);
                 border-radius: var(--radius); padding: 1rem; text-align: center; }
  .metric-value { font-size: 2rem; font-weight: 700; color: var(--accent); line-height: 1; }
  .metric-label { font-size: 0.78rem; color: var(--text-muted); margin-top: 0.35rem; }`;
}
/** CSS for pages, markdown, responsive */
function getPageStyles() {
    return `.empty-state { text-align: center; padding: 4rem 2rem; color: var(--text-muted); }
  .empty-state h2 { font-size: 1.25rem; margin-bottom: 0.5rem; color: var(--text); }
  .breadcrumb { font-size: 0.85rem; color: var(--text-muted); margin-bottom: 1.5rem; }
  .breadcrumb a { color: var(--text-muted); }
  .breadcrumb a:hover { color: var(--accent); }
  .tabs { display: flex; gap: 0; border-bottom: 1px solid var(--border); margin-bottom: 1.5rem; }
  .tab-btn { padding: 0.6rem 1.2rem; background: none; border: none; color: var(--text-muted);
             cursor: pointer; font-size: 0.9rem; border-bottom: 2px solid transparent;
             transition: color 0.2s; min-height: 44px; }
  .tab-btn.active { color: var(--accent); border-bottom-color: var(--accent); }
  .tab-btn:hover { color: var(--text); }
  .tab-content { display: none; }
  .tab-content.active { display: block; }
  .md-content { max-width: 72ch; }
  .md-content h1 { font-size: 1.5rem; margin: 1.5rem 0 0.75rem; }
  .md-content h2 { font-size: 1.2rem; margin: 1.25rem 0 0.5rem; }
  .md-content h3 { font-size: 1rem; margin: 1rem 0 0.4rem; }
  .md-content p { margin-bottom: 0.6rem; }
  .md-content ul { padding-left: 1.5rem; margin-bottom: 0.6rem; }
  .md-content li { margin-bottom: 0.2rem; }
  .md-content pre { background: #0f172a; border: 1px solid var(--border); border-radius: 6px;
                    padding: 1rem; overflow-x: auto; margin: 0.75rem 0; }
  .md-content code { font-family: 'Fira Mono','Cascadia Code',monospace; font-size: 0.85rem; }
  .md-content strong { font-weight: 700; }
  .md-content hr { border: none; border-top: 1px solid var(--border); margin: 1rem 0; }
  .project-list { display: grid; gap: 1rem; }
  .project-card { background: var(--surface); border: 1px solid var(--border);
                  border-radius: var(--radius); padding: 1.25rem; display: flex;
                  align-items: center; justify-content: space-between;
                  text-decoration: none; color: var(--text); transition: border-color 0.2s; }
  .project-card:hover { border-color: var(--accent); text-decoration: none; }
  .project-info h2 { font-size: 1rem; font-weight: 600; }
  .project-info .meta { font-size: 0.82rem; color: var(--text-muted); margin-top: 0.2rem; }
  .project-stats { text-align: right; font-size: 0.82rem; color: var(--text-muted); }
  .project-stats .done { color: var(--status-done); font-weight: 600; }
  .usage-panel { background: var(--surface); border: 1px solid var(--border);
                 border-radius: var(--radius); padding: 1rem; margin-top: 1.5rem; }
  .usage-panel h3 { font-size: 0.9rem; font-weight: 600; margin-bottom: 0.75rem; color: var(--text-muted); }
  .usage-tier { font-size: 1.1rem; font-weight: 700; color: var(--accent); }
  .trial-warning { color: #f59e0b; font-size: 0.82rem; margin-top: 0.35rem; }
  .trial-critical { color: #ef4444; font-weight: 600; }
  @media (max-width: 768px) {
    .grid-2 { grid-template-columns: 1fr; }
    .spec-grid { grid-template-columns: 1fr; }
    .project-card { flex-direction: column; align-items: flex-start; gap: 0.75rem; }
    .project-stats { text-align: left; }
  }`;
}
/** Base CSS for the dark theme dashboard (assembled from subfunctions) */
export function getBaseStyles() {
    return [getBaseReset(), getComponentStyles(), getPageStyles()].join('\n');
}
/** Client-side JS for auto-refresh polling and tab switching */
export function getClientScript() {
    return `
    (function() {
      var POLL_INTERVAL = 5000;
      var ERROR_INTERVAL = 10000;
      var pollTimer = null;
      var indicator = document.getElementById('status-indicator');

      function setStatus(msg, cls) {
        if (!indicator) return;
        indicator.textContent = msg;
        indicator.className = 'status-indicator' + (cls ? ' ' + cls : '');
      }

      function getCurrentProjectId() {
        var m = window.location.pathname.match(/^\\/project\\/([^\\/]+)/);
        return m ? m[1] : null;
      }

      function updateSpecGrid(specs) {
        var grid = document.getElementById('spec-grid');
        if (!grid || !specs) return;
        specs.forEach(function(spec) {
          var card = document.querySelector('[data-spec-id="' + spec.id + '"]');
          if (!card) return;
          var bar = card.querySelector('.progress-bar-fill');
          var txt = card.querySelector('.progress-pct');
          var crit = card.querySelector('.criteria-text');
          if (bar) bar.style.width = spec.progressPercent + '%';
          if (txt) txt.textContent = spec.progressPercent + '%';
          if (crit) crit.textContent = spec.criteriaImplemented + '/' + spec.criteriaTotal + ' criterios';
        });
      }

      function poll() {
        var projectId = getCurrentProjectId();
        if (!projectId) return;
        setStatus('Actualizando...', '');
        fetch('/api/project/' + projectId)
          .then(function(r) { return r.json(); })
          .then(function(data) {
            setStatus('En línea', '');
            if (data && data.specs) updateSpecGrid(data.specs);
            pollTimer = setTimeout(poll, POLL_INTERVAL);
          })
          .catch(function() {
            setStatus('Desconectado', 'disconnected');
            pollTimer = setTimeout(poll, ERROR_INTERVAL);
          });
      }

      // Tab switching
      document.addEventListener('click', function(e) {
        var btn = e.target && e.target.closest ? e.target.closest('.tab-btn') : null;
        if (!btn) return;
        var target = btn.dataset.tab;
        document.querySelectorAll('.tab-btn').forEach(function(b) { b.classList.remove('active'); });
        document.querySelectorAll('.tab-content').forEach(function(c) { c.classList.remove('active'); });
        btn.classList.add('active');
        var content = document.getElementById('tab-' + target);
        if (content) content.classList.add('active');
      });

      // Start polling only on project detail pages
      if (getCurrentProjectId()) {
        pollTimer = setTimeout(poll, POLL_INTERVAL);
      }
    })();
  `.trim();
}
/** Render the full HTML layout with head/body */
export function renderLayout(title, body) {
    return `<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>${escapeHtml(title)} — Planu Dashboard</title>
  <style>${getBaseStyles()}</style>
</head>
<body>
  <header>
    <div class="container">
      <h1><span>Planu</span> Dashboard</h1>
      <span id="status-indicator" class="status-indicator">En línea</span>
    </div>
  </header>
  <main class="container">
    ${body}
  </main>
  <script>${getClientScript()}</script>
</body>
</html>`;
}
//# sourceMappingURL=templates-layout.js.map