"""Settings and system health routes.

Moved from app.admin_dashboard in v4.7.2. The handlers still reuse
legacy helpers to keep this refactor behavior-preserving.
"""
from fastapi import APIRouter
from sqlalchemy import text
from app.db import engine
import app.admin_dashboard as legacy
from app.admin_dashboard import *  # noqa: F401,F403

router = APIRouter()


@router.get("/system", response_class=HTMLResponse)
async def system_health_page():
    metrics = get_system_health_metrics()
    backup = latest_backup_info()

    timers_raw = shell_output(["systemctl", "list-timers", "--all", "--no-pager"])
    clientflow_timers = "\n".join(
        line for line in timers_raw.splitlines()
        if "clientflow" in line.lower()
    )

    services = [
        "clientflow-api.service",
        "clientflow-outbox.timer",
        "clientflow-backup.timer",
        "clientflow-followups.timer",
    ]

    service_rows = ""
    for service in services:
        active = shell_output(["systemctl", "is-active", service])
        enabled = shell_output(["systemctl", "is-enabled", service])
        ok = active in ["active", "inactive"] if service.endswith(".service") else active == "active"
        if service == "clientflow-api.service":
            ok = active == "active"

        service_rows += f"""
        <tr>
            <td><code>{esc(service)}</code></td>
            <td>{status_pill(ok, active)}</td>
            <td>{esc(enabled)}</td>
        </tr>
        """

    def n(key):
        return metrics.get(key) or 0

    db_ok = True
    outbox_ok = n("outbox_failed") == 0
    webhook_ok = n("webhooks_errors_24h") == 0
    backup_ok = bool(backup.get("exists"))

    body = f"""
    <style>
        .system-grid {{
            display:grid;
            grid-template-columns:repeat(4, minmax(180px, 1fr));
            gap:14px;
            margin-bottom:18px;
        }}
        .system-card {{
            background:white;
            border:1px solid #e5e7eb;
            border-radius:16px;
            padding:16px;
        }}
        .system-card span {{
            color:#6b7280;
            font-size:13px;
        }}
        .system-card strong {{
            display:block;
            font-size:28px;
            margin-top:6px;
        }}
        .system-panel {{
            background:white;
            border:1px solid #e5e7eb;
            border-radius:16px;
            padding:16px;
            margin-bottom:16px;
        }}
        .system-panel h2 {{
            margin-top:0;
            font-size:18px;
        }}
        .system-pill {{
            display:inline-block;
            border-radius:999px;
            padding:4px 9px;
            font-size:12px;
            font-weight:700;
        }}
        .pill-ok {{
            background:#dcfce7;
            color:#166534;
            border:1px solid #86efac;
        }}
        .pill-bad {{
            background:#fee2e2;
            color:#991b1b;
            border:1px solid #fecaca;
        }}
        pre.system-pre {{
            background:#111827;
            color:#f9fafb;
            border-radius:12px;
            padding:12px;
            overflow:auto;
            font-size:12px;
        }}
        @media (max-width:1000px) {{
            .system-grid {{ grid-template-columns:1fr 1fr; }}
        }}
    
</style>

    <p>
        <a href="/">← Voltar à visão geral</a>
        ·
        <a href="/system">Sistema</a>
        <a href="/tasks">Kanban</a>
    </p>

    <div class="system-grid">
        <div class="system-card">
            <span>API</span>
            <strong>{status_pill(True, "OK")}</strong>
        </div>
        <div class="system-card">
            <span>Base de dados</span>
            <strong>{status_pill(db_ok, "OK" if db_ok else "ERRO")}</strong>
        </div>
        <div class="system-card">
            <span>Backups</span>
            <strong>{status_pill(backup_ok, "OK" if backup_ok else "FALTA")}</strong>
        </div>
        <div class="system-card">
            <span>Webhooks erros 24h</span>
            <strong>{n("webhooks_errors_24h")}</strong>
        </div>
    </div>

    <div class="system-grid">
        <div class="system-card"><span>Tasks pendentes</span><strong>{n("tasks_pending")}</strong></div>
        <div class="system-card"><span>Tasks 24h</span><strong>{n("tasks_24h")}</strong></div>
        <div class="system-card"><span>Webhooks 24h</span><strong>{n("webhooks_24h")}</strong></div>
        <div class="system-card"><span>Outbox falhada</span><strong>{n("outbox_failed")}</strong></div>
    </div>


    <div class="system-panel">
        <h2>Estado dos serviços/timers</h2>
        <table>
            <thead>
                <tr>
                    <th>Serviço</th>
                    <th>Active</th>
                    <th>Enabled</th>
                </tr>
            </thead>
            <tbody>{service_rows}</tbody>
        </table>
    </div>

    <div class="system-panel">
        <h2>Último backup</h2>
        <table>
            <tbody>
                <tr><th>Existe</th><td>{status_pill(backup_ok, "Sim" if backup_ok else "Não")}</td></tr>
                <tr><th>Ficheiro</th><td><code>{esc(backup.get("file"))}</code></td></tr>
                <tr><th>Tamanho</th><td>{esc(backup.get("size"))}</td></tr>
                <tr><th>Modificado</th><td>{esc(backup.get("mtime"))}</td></tr>
            </tbody>
        </table>
    </div>

    <div class="system-panel">
        <h2>Timers ClientFlow</h2>
        <pre class="system-pre">{esc(clientflow_timers or "Sem timers ClientFlow encontrados.")}</pre>
    </div>

    <div class="system-panel">
        <h2>Resumo técnico</h2>
        <table>
            <tbody>
                <tr><th>Total tasks</th><td>{n("tasks_total")}</td></tr>
                <tr><th>Tasks done</th><td>{n("tasks_done")}</td></tr>
                <tr><th>Tasks failed</th><td>{n("tasks_failed")}</td></tr>
                <tr><th>Webhooks ignorados 24h</th><td>{n("webhooks_ignored_24h")}</td></tr>
                <tr><th>Outbox pending</th><td>{n("outbox_pending")}</td></tr>
                <tr><th>Outbox sent</th><td>{n("outbox_sent")}</td></tr>
            </tbody>
        </table>
    </div>
    """

    return layout("Sistema", "Estado técnico do ClientFlow e integrações.", body, "system")


@router.get("/settings", response_class=HTMLResponse)
@router.get("/configuracoes", response_class=HTMLResponse)
async def settings_page():
    return RedirectResponse("/settings/workflow", status_code=303)


@router.get("/system/health", response_class=HTMLResponse)
async def system_health_operational_page():
    health = get_system_health_summary()
    settings_info = health.get("settings") or {}
    timers = health.get("timers") or {}
    outbox = health.get("outbox") or {}
    documents = health.get("documents") or {}
    operational_metrics = health.get("operational_metrics") or {}

    def m(key: str) -> int:
        try:
            return int(operational_metrics.get(key) or 0)
        except Exception:
            return 0

    timer_rows = ""
    for name, item in timers.items():
        ok = bool(item.get("ok"))
        chip = "cf-chip-green" if ok else "cf-chip-orange"
        timer_rows += f"""
        <tr><td>{esc(name)}</td><td><code>{esc(item.get('unit') or '—')}</code></td><td><span class="cf-chip {chip}">{esc(item.get('active_state') or 'unknown')}</span></td></tr>
        """

    outbox_rows = ""
    for target, by_status in outbox.items():
        cells = "".join(f'<span class="cf-chip cf-chip-gray me-1">{esc(status)}: {esc(total)}</span>' for status, total in by_status.items())
        outbox_rows += f"<tr><td>{esc(target)}</td><td>{cells}</td></tr>"
    if not outbox_rows:
        outbox_rows = '<tr><td colspan="2" class="text-secondary py-4">Sem dados de outbox.</td></tr>'

    doc_rows = ""
    for kind, by_status in documents.items():
        cells = "".join(f'<span class="cf-chip cf-chip-gray me-1">{esc(status)}: {esc(total)}</span>' for status, total in by_status.items())
        doc_rows += f"<tr><td>{esc(kind)}</td><td>{cells}</td></tr>"
    if not doc_rows:
        doc_rows = '<tr><td colspan="2" class="text-secondary py-4">Sem documentos.</td></tr>'

    db_ok = bool((health.get("database") or {}).get("ok"))
    critical_count = (0 if db_ok else 1) + m("outbox_processing_stale") + m("outbox_stale") + m("outbox_blocked_or_failed") + m("chatwoot_incoming_pending")
    warning_count = m("ambiguous_opportunity_tasks") + m("open_opportunities_without_fiscal_customer") + m("active_incomplete_fiscal_customers") + m("products_missing_external_code")
    if critical_count:
        production_state = "Crítico"
        production_class = "critical"
        production_hint = "corrigir bloqueios antes de automatizar"
    elif warning_count:
        production_state = "Atenção"
        production_class = "warn"
        production_hint = "existem validações operacionais pendentes"
    else:
        production_state = "OK"
        production_class = "ok"
        production_hint = "sem bloqueios críticos visíveis"

    body = f"""
    <section class="cf-health-status {production_class} mb-3">
      <div class="d-flex flex-wrap justify-content-between align-items-center gap-3">
        <div><div class="small text-secondary fw-bold text-uppercase">Estado para operação</div><strong class="h3 mb-0">{production_state}</strong><div class="small text-secondary">{production_hint}</div></div>
        <div class="d-flex flex-wrap gap-2"><span class="cf-chip cf-chip-red">Críticos: {esc(critical_count)}</span><span class="cf-chip cf-chip-orange">Atenção: {esc(warning_count)}</span></div>
      </div>
    </section>

    <section class="cf-kpi-grid">
      {kpi_card('Estado geral', esc(health.get('status')), None, 'OK' if db_ok else 'ver base de dados', 'bi-heart-pulse', 'cf-kpi-tone-green' if db_ok else 'cf-kpi-tone-red')}
      {kpi_card('Jasmin', 'ativo' if settings_info.get('jasmin_enabled') else 'inativo', None, f"{esc(settings_info.get('jasmin_company_key') or '—')} · {esc(settings_info.get('jasmin_quotation_serie') or '—')}", 'bi-receipt')}
      {kpi_card('Packlink', 'ativo' if settings_info.get('packlink_enabled') else 'inativo', None, f"serviço {esc(settings_info.get('packlink_default_service_id') or '—')}", 'bi-truck')}
      {kpi_card('Ambiente', esc(settings_info.get('env') or '—'), None, esc(settings_info.get('app_name') or 'ClientFlow'), 'bi-sliders')}
    </section>

    <section class="cf-kpi-grid mt-3">
      {kpi_card('Tasks pendentes', esc(m('tasks_pending')), '/operations', f"done 24h: {esc(m('tasks_done_24h'))}", 'bi-list-task')}
      {kpi_card('Ambíguas', esc(m('ambiguous_opportunity_tasks')), '/operations?scope=ambiguas', 'associação por confirmar', 'bi-person-exclamation', 'cf-kpi-tone-orange' if m('ambiguous_opportunity_tasks') else 'cf-kpi-tone-green')}
      {kpi_card('Outbox stale', esc(m('outbox_stale') or m('outbox_processing_stale')), '/outbox?status=stale', f"modo: {esc(settings_info.get('outbox_stale_recovery_mode') or 'manual_only')}", 'bi-hourglass-split', 'cf-kpi-tone-red' if (m('outbox_stale') or m('outbox_processing_stale')) else 'cf-kpi-tone-green')}
      {kpi_card('Ações operador 24h', esc(m('operator_actions_24h')), '/events', 'auditoria operacional', 'bi-shield-check')}
    </section>

    <section class="cf-kpi-grid mt-3">
      {kpi_card('Oportunidades sem cliente fiscal', esc(m('open_opportunities_without_fiscal_customer')), '/operations?scope=ambiguas', 'associação por confirmar', 'bi-person-vcard', 'cf-kpi-tone-orange' if m('open_opportunities_without_fiscal_customer') else 'cf-kpi-tone-green')}
      {kpi_card('Clientes fiscais incompletos', esc(m('active_incomplete_fiscal_customers')), '/customers', 'em oportunidades ativas', 'bi-exclamation-diamond', 'cf-kpi-tone-orange' if m('active_incomplete_fiscal_customers') else 'cf-kpi-tone-green')}
      {kpi_card('Produtos sem código externo', esc(m('products_missing_external_code')), '/products', 'podem bloquear Jasmin', 'bi-box-seam', 'cf-kpi-tone-orange' if m('products_missing_external_code') else 'cf-kpi-tone-green')}
      {kpi_card('Último webhook Chatwoot', esc('—' if not m('seconds_since_last_chatwoot_webhook') else str(m('seconds_since_last_chatwoot_webhook')) + 's'), '/events', f"eventos: {esc(m('chatwoot_events_total'))}", 'bi-chat-dots')}
    </section>

    <section class="cf-kpi-grid mt-3">
      {kpi_card('Chatwoot inbound pendente', esc(m('chatwoot_incoming_pending')), '/events', f"inbound 24h: {esc(m('chatwoot_incoming_24h'))}", 'bi-inbox', 'cf-kpi-tone-red' if m('chatwoot_incoming_pending') else 'cf-kpi-tone-green')}
    </section>

    <div class="row g-3">
      <div class="col-xl-6"><section class="card cf-card"><div class="card-body p-0"><div class="p-3 border-bottom"><h2 class="cf-section-title">Timers systemd</h2><div class="small text-secondary">Estado best-effort dos timers da outbox.</div></div><div class="cf-table-wrap border-0 rounded-0"><table class="table cf-table"><thead><tr><th>Integração</th><th>Unidade</th><th>Estado</th></tr></thead><tbody>{timer_rows}</tbody></table></div></div></section></div>
      <div class="col-xl-6"><section class="card cf-card"><div class="card-body p-0"><div class="p-3 border-bottom"><h2 class="cf-section-title">Outbox por sistema</h2></div><div class="cf-table-wrap border-0 rounded-0"><table class="table cf-table"><thead><tr><th>Sistema</th><th>Estados</th></tr></thead><tbody>{outbox_rows}</tbody></table></div></div></section></div>
      <div class="col-xl-6"><section class="card cf-card"><div class="card-body p-0"><div class="p-3 border-bottom"><h2 class="cf-section-title">Documentos comerciais</h2></div><div class="cf-table-wrap border-0 rounded-0"><table class="table cf-table"><thead><tr><th>Tipo</th><th>Estados</th></tr></thead><tbody>{doc_rows}</tbody></table></div></div></section></div>
      <div class="col-xl-6"><section class="card cf-card"><div class="card-body"><h2 class="cf-section-title mb-3">Base de dados</h2><p class="mb-2">Estado: <span class="cf-chip {'cf-chip-green' if db_ok else 'cf-chip-red'}">{'OK' if db_ok else 'Erro'}</span></p><pre class="cf-copy-box">{esc((health.get('database') or {}).get('error') or 'Sem erros reportados.')}</pre></div></section></div>
    </div>
    """
    return layout("Saúde operacional", "Base de dados, integrações, timers e contadores", body, "system")



@router.get("/settings/workflow", response_class=HTMLResponse)
@router.get("/configuracao/fluxo-operacional", response_class=HTMLResponse)
async def workflow_settings_page():
    from app.domain.opportunity_flow import load_company_profile

    profile = load_company_profile("blif")
    stage_rows = "".join(
        f"<tr><td><code>{esc(item.get('code'))}</code></td><td>{esc(item.get('label'))}</td></tr>"
        for item in profile.commercial_stages
        if isinstance(item, dict)
    ) or '<tr><td colspan="2" class="text-secondary py-4">Sem fases configuradas.</td></tr>'
    payment_rows = "".join(f"<tr><td><code>{esc(k)}</code></td><td>{esc(v)}</td></tr>" for k, v in profile.payment_terms.items())
    delivery_rows = "".join(f"<tr><td><code>{esc(k)}</code></td><td>{esc(v)}</td></tr>" for k, v in profile.delivery_terms.items())
    action_rows = "".join(
        f"<tr><td><code>{esc(code)}</code></td><td>{esc((cfg or {}).get('label') if isinstance(cfg, dict) else cfg)}</td><td class='text-secondary small'>{esc((cfg or {}).get('description') if isinstance(cfg, dict) else '')}</td></tr>"
        for code, cfg in profile.actions.items()
    )
    right_cards = profile.ui.get("opportunity_cards", {}).get("right", []) if isinstance(profile.ui, dict) else []
    left_cards = profile.ui.get("opportunity_cards", {}).get("left", []) if isinstance(profile.ui, dict) else []
    body = f'''
    <a class="cf-row-link d-inline-flex mb-3" href="/system">← Voltar ao sistema</a>
    <section class="card cf-card mb-3"><div class="card-body p-4">
      <div class="d-flex flex-wrap justify-content-between gap-3 align-items-start">
        <div>
          <h1 class="h3 fw-bold mb-2">Fluxo operacional</h1>
          <div class="text-secondary">Configuração controlada do perfil ativo da empresa. As regras críticas continuam protegidas no backend.</div><div class="mt-3"><a class="btn btn-outline-primary btn-sm" href="/settings/workflow/audit">Abrir auditor de coerência</a></div>
        </div>
        <div class="text-end"><span class="cf-chip cf-chip-blue">{esc(profile.name)}</span><div class="small text-secondary mt-2">{esc(profile.version)}</div></div>
      </div>
    </div></section>
    <div class="row g-3">
      <div class="col-xl-6"><section class="card cf-card h-100"><div class="card-body p-4"><h2 class="cf-section-title mb-3">Defaults</h2><dl class="row mb-0"><dt class="col-5">Pagamento</dt><dd class="col-7">{esc(profile.defaults.get('payment_terms') or '—')}</dd><dt class="col-5">Entrega</dt><dd class="col-7">{esc(profile.defaults.get('delivery_terms') or '—')}</dd><dt class="col-5">Follow-up</dt><dd class="col-7">{esc(profile.defaults.get('follow_up_delay_days') or '—')} dias</dd></dl></div></section></div>
      <div class="col-xl-6"><section class="card cf-card h-100"><div class="card-body p-4"><h2 class="cf-section-title mb-3">Cards da oportunidade</h2><div class="small text-secondary fw-bold">Coluna operação</div><div class="mb-2">{esc(' → '.join(map(str, right_cards)) or '—')}</div><div class="small text-secondary fw-bold">Coluna contexto</div><div>{esc(' → '.join(map(str, left_cards)) or '—')}</div></div></section></div>
      <div class="col-xl-6"><section class="card cf-card h-100"><div class="card-body p-4"><h2 class="cf-section-title mb-3">Condições de pagamento</h2><table class="table cf-table"><tbody>{payment_rows}</tbody></table></div></section></div>
      <div class="col-xl-6"><section class="card cf-card h-100"><div class="card-body p-4"><h2 class="cf-section-title mb-3">Tipos de entrega</h2><table class="table cf-table"><tbody>{delivery_rows}</tbody></table></div></section></div>
      <div class="col-12"><section class="card cf-card"><div class="card-body p-4"><h2 class="cf-section-title mb-3">Fases comerciais</h2><table class="table cf-table"><thead><tr><th>Código</th><th>Nome</th></tr></thead><tbody>{stage_rows}</tbody></table></div></section></div>
      <div class="col-12"><section class="card cf-card"><div class="card-body p-4"><h2 class="cf-section-title mb-3">Ações do motor</h2><table class="table cf-table"><thead><tr><th>Código</th><th>Nome</th><th>Descrição</th></tr></thead><tbody>{action_rows}</tbody></table></div></section></div>
    </div>
    '''
    return layout("Fluxo operacional", "Perfil de empresa e defaults do workflow", body, "settings")


@router.get("/settings/workflow/audit", response_class=HTMLResponse)
@router.get("/admin/workflow/audit", response_class=HTMLResponse)
async def workflow_audit_page():
    """Lightweight coherence audit for workflow/operator UX regressions."""
    findings = []
    try:
        with engine.begin() as conn:
            rows = conn.execute(text("""
                SELECT
                  o.id::text,
                  o.title,
                  o.stage,
                  o.customer_name,
                  o.updated_at,
                  COUNT(*) FILTER (WHERE t.status = 'pending')::int AS pending_tasks,
                  COUNT(*) FILTER (WHERE t.status = 'pending' AND t.action_code = 'CONFIRM_PAYMENT')::int AS pending_confirm_payment,
                  COUNT(*) FILTER (WHERE t.status = 'pending' AND t.action_code = 'SEND_INVOICE')::int AS pending_send_invoice,
                  COUNT(*) FILTER (WHERE d.document_kind = 'invoice')::int AS invoices,
                  COUNT(*) FILTER (WHERE d.document_kind = 'quotation')::int AS quotes,
                  COUNT(*) FILTER (WHERE ol.system = 'clientflow' AND ol.external_type = 'payment' AND ol.status = 'confirmed')::int AS payments_confirmed,
                  COUNT(*) FILTER (WHERE lower(coalesce(t.note,'')) LIKE '%fatura por emitir%')::int AS stale_invoice_note,
                  COUNT(*) FILTER (WHERE lower(coalesce(t.note,'')) LIKE '%pró-forma%' OR lower(coalesce(t.action,'')) LIKE '%pró-forma%')::int AS visible_proforma_task
                FROM opportunities o
                LEFT JOIN tasks t ON t.opportunity_id = o.id
                LEFT JOIN commercial_documents d ON d.opportunity_id = o.id
                LEFT JOIN operation_links ol ON ol.opportunity_id = o.id
                WHERE coalesce(o.status, 'open') <> 'closed'
                GROUP BY o.id, o.title, o.stage, o.customer_name, o.updated_at
                ORDER BY o.updated_at DESC NULLS LAST
                LIMIT 300
            """)).mappings().all()
    except Exception as exc:
        rows = []
        findings.append({"severity": "alto", "code": "audit_query_failed", "title": "Auditoria indisponível", "detail": str(exc), "url": "/system"})

    try:
        from app.jasmin_fiscal_sync_service import audit_jasmin_fiscal_gaps
        findings.extend(audit_jasmin_fiscal_gaps(limit=150))
    except Exception as exc:
        findings.append({"severity": "baixo", "code": "jasmin_fiscal_audit_unavailable", "title": "Auditoria Jasmin fiscal indisponível", "detail": str(exc), "url": "/settings/workflow/audit"})

    for row in rows:
        url = f"/opportunities/{row.get('id')}"
        title = row.get("title") or row.get("customer_name") or row.get("id")
        if int(row.get("payments_confirmed") or 0) > 0 and int(row.get("pending_confirm_payment") or 0) > 0:
            findings.append({"severity": "alto", "code": "payment_confirmed_but_confirm_task", "title": title, "detail": "Pagamento confirmado mas ainda existe task pendente de confirmar pagamento.", "url": url})
        if int(row.get("invoices") or 0) > 0 and int(row.get("stale_invoice_note") or 0) > 0:
            findings.append({"severity": "médio", "code": "invoice_exists_but_task_says_to_issue", "title": title, "detail": "Fatura associada mas alguma task ainda diz 'fatura por emitir'.", "url": url})
        if int(row.get("visible_proforma_task") or 0) > 0:
            findings.append({"severity": "baixo", "code": "legacy_proforma_word_visible", "title": title, "detail": "Texto histórico ainda contém 'pró-forma'; normalizar para orçamento para pagamento.", "url": url})
        if int(row.get("payments_confirmed") or 0) > 0 and int(row.get("invoices") or 0) == 0 and str(row.get("stage") or "").upper() not in {"PAYMENT_CONFIRMED", "WAITING_PAYMENT", "REVIEW"}:
            findings.append({"severity": "médio", "code": "payment_confirmed_without_invoice", "title": title, "detail": "Pagamento confirmado sem fatura associada; verificar próxima ação.", "url": url})

    severity_order = {"alto": 0, "médio": 1, "baixo": 2}
    findings.sort(key=lambda f: (severity_order.get(str(f.get("severity")), 9), str(f.get("title") or "")))
    rows_html = ""
    for f in findings[:200]:
        sev = str(f.get("severity") or "baixo")
        chip = "cf-chip-red" if sev == "alto" else ("cf-chip-orange" if sev == "médio" else "cf-chip-gray")
        rows_html += f"""
        <tr>
          <td><span class="cf-chip {chip}">{esc(sev)}</span></td>
          <td><code>{esc(f.get('code'))}</code></td>
          <td><a class="cf-row-link" href="{esc(f.get('url') or '#')}">{esc(f.get('title') or 'Oportunidade')}</a><div class="small text-secondary">{esc(f.get('detail') or '')}</div></td>
        </tr>
        """
    if not rows_html:
        rows_html = '<tr><td colspan="3" class="text-secondary py-4">Sem incoerências encontradas nos primeiros processos analisados.</td></tr>'
    body = f'''
    <a class="cf-row-link d-inline-flex mb-3" href="/settings/workflow">← Voltar ao fluxo operacional</a>
    <section class="card cf-card mb-3"><div class="card-body p-4">
      <h1 class="h3 fw-bold mb-2">Auditor de coerência do fluxo</h1>
      <div class="text-secondary">Deteta sinais de regressão entre pagamentos, faturas, tarefas antigas e textos legados. Esta primeira versão é read-only.</div>
      <div class="mt-3"><span class="cf-chip cf-chip-blue">{len(findings)} achado(s)</span></div>
    </div></section>
    <section class="card cf-card"><div class="card-body p-0">
      <div class="p-3 border-bottom"><h2 class="cf-section-title">Achados</h2><div class="small text-secondary">Prioriza alto/médio antes de operar novas ações financeiras.</div></div>
      <div class="cf-table-wrap border-0 rounded-0"><table class="table cf-table"><thead><tr><th>Severidade</th><th>Código</th><th>Processo</th></tr></thead><tbody>{rows_html}</tbody></table></div>
    </div></section>
    '''
    return layout("Auditor de fluxo", "Coerência operacional", body, "settings")
