#!/usr/bin/env python3
"""Aplica las palabras TRANSCRITAS de la imagen, con sus diacriticos.

Por que existe esta cola. El campo `scan` de los candidatos es la lectura del
OCR, que pierde los diacriticos: escribir 'gosvamin' donde el fichero tiene
'Gosvāmī' destruye las vocales largas. Y la capa de texto del PDF tampoco sirve
—los degrada a ASCII ('riidhikii', 'Kr?ra')—, asi que la unica fuente fiable es
que alguien mire la pagina y ESCRIBA lo que ve.

Eso es lo que traen estos resultados: el campo `impreso`, transcrito a 300-500
dpi. Aqui solo se lleva al fichero, en la ocurrencia que corresponda.

Guardarrailes que se mantienen:
  - la palabra del repo tiene que aparecer UNA sola vez en el fichero; si no, no
    hay forma de saber cual miro el transcriptor y se deja abierta;
  - se respeta la mayuscula inicial del texto;
  - no se toca nada si el transcriptor dijo IGUAL_AL_REPO, NO_LEGIBLE o
    NO_ENCONTRADO.

Uso: python3 aplicar_transcripcion.py [--aplicar] [--desde N]
"""
import json, re, sys, pathlib, collections

HERE = pathlib.Path(__file__).resolve().parent
REPO = pathlib.Path('/Users/jaganat/git_projects/vedabase-original')
LOTES = HERE / 'lotes_imagen'
FECHA = '2026-08-09'


def main():
    aplicar = '--aplicar' in sys.argv
    desde = int(sys.argv[sys.argv.index('--desde') + 1]) if '--desde' in sys.argv else 60

    filas = []
    for f in sorted(LOTES.glob('resultado*.json')):
        n = int(re.search(r'(\d+)', f.name).group(1))
        if n < desde: continue
        for x in json.load(open(f, encoding='utf-8')):
            # Solo los de transcripcion, y solo si traen las DOS piezas. Los
            # lotes nuevos mezclan en el mismo fichero los IMPRESO=REPO (que no
            # llevan `palabra_repo`) y los de la clase delete (que traen
            # `texto_repo` en su lugar); sin este filtro el aplicador reventaba
            # con KeyError en el primero que pasara.
            if x.get('impreso') and x.get('palabra_repo'): filas.append(x)
    if not filas:
        print('sin resultados de transcripcion'); return 1

    vistos = set(); unicas = []
    for x in filas:
        k = (x['file'], x['palabra_repo'], x['pagina'])
        if k in vistos: continue
        vistos.add(k); unicas.append(x)
    print(f'transcripciones: {len(filas)} | sin duplicados: {len(unicas)}')
    res = collections.Counter(x['veredicto'] for x in unicas)

    hechas = []; verd = []
    porfich = collections.defaultdict(list)
    for x in unicas:
        if (x['veredicto'] == 'TRANSCRITO' and x['impreso']
                and x['impreso'] != x['palabra_repo']
                # Solo UNA palabra por UNA palabra. Una transcripcion larga es
                # una restauracion de frase y hay que escribirla a mano: metida
                # en automatico convirtio 'he' en '—though from a lowborn
                # family—' y duplico medio parrafo en cc-madhya-8.36.
                and ' ' not in x['impreso'] and ' ' not in x['palabra_repo']):
            porfich[x['file']].append(x)
        else:
            est = 'DESCARTADO' if x['veredicto'] in ('IGUAL_AL_REPO', 'NO_ENCONTRADO') else 'ABIERTO'
            verd.append((x, est, f"{x['veredicto']} sobre la imagen (p.{x['pagina']}): {x.get('nota','')[:180]}"))

    for fich, lista in sorted(porfich.items()):
        p = REPO / fich
        if not p.exists(): res['sin fichero'] += len(lista); continue
        txt = p.read_text(encoding='utf-8')
        pend = []
        for x in lista:
            # LIMITE DE PALABRA, obligatorio. Buscar por subcadena hizo que
            # 'food' casara dentro de 'foodstuffs' y 'virāṭ' dentro de 'virāṭa',
            # dejando 'foodstuffsstuffs' y 'virāṭaa' (2026-08-09).
            ms = [m for m in re.finditer(rf"\b{re.escape(x['palabra_repo'])}\b", txt)]
            if len(ms) != 1:
                res[f'la palabra aparece {len(ms)} veces: no se puede situar'] += 1
                verd.append((x, 'ABIERTO', f"el impreso dice {x['impreso']!r} (p.{x['pagina']}), pero la "
                                           f"forma del repo aparece {len(ms)} veces en el fichero: "
                                           f"hace falta situarla a mano"))
                continue
            pend.append((ms[0].start(), ms[0].end(), x['palabra_repo'], x['impreso'], x))
        for ini, fin, antes, nuevo, x in sorted(pend, key=lambda y: -y[0]):
            txt = txt[:ini] + nuevo + txt[fin:]
            hechas.append({'file': fich, 'antes': antes, 'despues': nuevo,
                           'page': x['pagina'], 'nota': x.get('nota', '')[:200]})
        if aplicar and pend: p.write_text(txt, encoding='utf-8')

    res['APLICADO con la forma transcrita'] = len(hechas)
    for k, v in res.most_common(): print(f'  {v:5}  {k}')
    if aplicar:
        json.dump(hechas, open(HERE / 'aplicadas_transcripcion.json', 'w'), ensure_ascii=False, indent=1)
        with open(HERE / 'verdicts.jsonl', 'a') as fh:
            for h in hechas:
                fh.write(json.dumps({"repo": h['antes'].lower(), "scan": h['despues'].lower(),
                                     "estado": "VERIFICADO",
                                     "razon": f"TRANSCRITO de la imagen del impreso (p.{h['page']}) con sus "
                                              f"diacriticos, no copiado del OCR: {h['nota']}",
                                     "fecha": FECHA}, ensure_ascii=False) + '\n')
            for x, est, raz in verd:
                fh.write(json.dumps({"repo": x['palabra_repo'].lower(),
                                     "scan": (x.get('impreso') or x['lectura_ocr']).lower(),
                                     "estado": est, "razon": raz, "fecha": FECHA},
                                    ensure_ascii=False) + '\n')
        print('veredictos escritos:', len(hechas) + len(verd))
    return 0


if __name__ == '__main__':
    sys.exit(main())
