#!/usr/bin/env python3
"""Genera reports/fresh/review_alta.html desde reports/fresh/CANDIDATES_alta.json.
Visor de revisión: tarjetas con diff (rojo=D1 actual / verde=escaneo original),
filtro por libro, marcar/desmarcar visibles y export JSON de aprobados.
Borde ámbar = libro con divergencia densa (densidad de candidatos alta por 1k
palabras D1 >= UMBRAL) -> probable revisión de edición completa, no edits sueltos.
"""
import json, os, html, re
BASE = os.path.dirname(os.path.abspath(__file__))
UMBRAL_DENS = 2.0  # candidatos alta / 1000 palabras D1 -> marca ámbar

cands = json.load(open(os.path.join(BASE, 'reports/fresh/CANDIDATES_alta.json'), encoding='utf-8'))

# --- densidad por grupo (mismo cálculo que triage_fresh.py) ---
ALIAS = {'rvidya': 'rv', 'ejop': 'ej'}
d1w = {}
for f in ('/tmp/fp_small.json', '/tmp/fp_cc.json', '/tmp/fp_sb.json'):
    for r in json.load(open(f))[0]['results']:
        b = r['book']
        n = len(((r.get('translation') or '') + ' ' + (r.get('purport') or '')).split())
        if b == 'sb':   g = 'sb' + r['ref'].split('/')[1]
        elif b == 'cc': g = 'cc_' + r['ref'].split('/')[1]
        else:           g = b
        d1w[g] = d1w.get(g, 0) + n

from collections import Counter
per_grp = Counter(c['group'] for c in cands)
dens = {}
for g, k in per_grp.items():
    w = d1w.get(ALIAS.get(g, g), 0)
    dens[g] = round(1000 * k / max(w, 1), 1)
amber = {g for g, dv in dens.items() if dv >= UMBRAL_DENS}

groups = sorted(per_grp)
e = html.escape

# --- tarjetas ---
cards = []
for i, c in enumerate(cands):
    cls = 'card ed' if c['group'] in amber else 'card'
    chg = (f"…{e(c.get('cb',''))} <del>{e(c['veda'])}</del> "
           f"<ins>{e(c['gold'])}</ins> {e(c.get('ca',''))}…")
    cards.append(
        f'<div class="{cls}" data-g="{e(c["group"])}" data-idx="{i}">'
        f'<label class=hd><input type=checkbox> <b>{e(c["ref"])}</b> · '
        f'{e(c["col"])} · <span class=g>{e(c["group"])}</span></label>'
        f'<div class=chg>{chg}</div></div>')

opts = ''.join(f'<option>{e(g)}</option>' for g in groups)
DATA = json.dumps([{k: c.get(k, '') for k in ('ref','col','veda','gold','cb','group')}
                   for c in cands], ensure_ascii=False)

doc = f"""<!doctype html><html lang=es><head><meta charset=utf-8><title>Pasada fresca scan↔D1 — candidatos alta</title>
<style>body{{font:14px/1.5 -apple-system,sans-serif;margin:0;background:#f5f5f4;color:#1c1917}}
header{{position:sticky;top:0;background:#fff;border-bottom:2px solid #e7e5e4;padding:10px 16px;z-index:9}}
h1{{font-size:16px;margin:0 0 4px}}.muted{{color:#78716c;font-size:12.5px}}
.controls{{margin-top:6px;display:flex;gap:8px;align-items:center;flex-wrap:wrap}}
select,button{{padding:4px 9px;border:1px solid #d6d3d1;border-radius:6px;background:#fff;font-size:13px;cursor:pointer}}
.wrap{{max-width:1050px;margin:0 auto;padding:12px}}
.card{{background:#fff;border:1px solid #e7e5e4;border-left:4px solid #16a34a;border-radius:7px;padding:8px 11px;margin:6px 0}}
.card.ed{{border-left-color:#f59e0b}}
.hd{{font-size:13px;display:block;cursor:pointer}}.g{{color:#a8a29e;font-size:11px}}
.chg{{margin-top:5px;font-size:13.5px}}
del{{background:#fee2e2;padding:0 2px}}ins{{background:#dcfce7;text-decoration:none;padding:0 2px;font-weight:600}}
#out{{width:100%;height:100px;font:11px monospace;display:none;margin-top:6px}}
.count{{font-weight:600}}</style></head><body>
<header><h1>Pasada fresca escaneo↔D1 — {len(cands)} candidatos de confianza alta</h1>
<div class=muted><del>rojo</del>=D1 actual · <ins>verde</ins>=escaneo original. Borde ámbar = libro con divergencia densa (dens≥{UMBRAL_DENS}/1k; probable revisión de edición completa, no edits sueltos). Reescrituras largas aparecen fragmentadas en diffs contiguos del mismo ref.</div>
<div class=controls>Libro: <select id=fg onchange=flt()><option value=''>todos</option>{opts}</select>
<button onclick=all(true)>Marcar visibles</button><button onclick=all(false)>Desmarcar</button>
<button onclick=exp()>Exportar aprobados</button><span class=count id=cnt></span></div>
<textarea id=out readonly></textarea></header>
<div class=wrap>{''.join(cards)}</div>
<script>const DATA={DATA};
function cs(){{return [...document.querySelectorAll('.card')]}}
function flt(){{const g=fg.value;cs().forEach(c=>c.style.display=(!g||c.dataset.g==g)?'':'none');upd()}}
function all(v){{cs().forEach(c=>{{if(c.style.display!=='none')c.querySelector('input').checked=v}});upd()}}
function upd(){{cnt.textContent=cs().filter(c=>c.querySelector('input').checked).length+' aprobados'}}
function exp(){{const a=cs().filter(c=>c.querySelector('input').checked).map(c=>DATA[+c.dataset.idx]);out.style.display='block';out.value=JSON.stringify(a);out.select()}}
document.addEventListener('change',e=>{{if(e.target.type=='checkbox')upd()}});upd();</script></body></html>"""

out = os.path.join(BASE, 'reports/fresh/review_alta.html')
open(out, 'w', encoding='utf-8').write(doc)
print(f"escrito {out}: {len(cands)} tarjetas, {len(groups)} libros")
print("ámbar (densos):", ' '.join(f'{g}({dens[g]})' for g in sorted(amber, key=lambda x:-dens[x])) or '—')
