#!/usr/bin/env python3
"""Empuja a D1 las correcciones que se quedaron sin llegar.

Por que no vale resincronizar en bloque. `sincronizar_diff.py` compara dos
versiones del repo y saca los tramos que cambiaron. Contra el estado de hace
catorce horas los tramos salen enormes y ya no anclan en D1, que entretanto se
ha ido actualizando a medias: 377 sin ancla de 391.

Aqui se va caso por caso, con el par (viejo, nuevo) que quedo registrado en
`corrections.jsonl`, y con dos condiciones que no se negocian:

  1. EL REPO MANDA. Solo se empuja si el fichero del repo dice HOY el texto
     nuevo. Si el repo no lo dice —porque se revirtio, como en bg/8/18— no se
     toca D1. Asi una correccion revocada no puede colarse por esta puerta.
  2. ANCLA UNICA. El texto viejo tiene que aparecer exactamente una vez en la
     fila. Si aparece dos veces no se sabe cual, y si no aparece es que D1 dice
     ahi una tercera cosa: una divergencia anterior a este trabajo, que se
     informa y se deja.

Uso: python3 empujar_pendientes_d1.py [--aplicar]
"""
import json, re, os, sys, subprocess, unicodedata, pathlib, collections

HERE = pathlib.Path(__file__).resolve().parent
ASTRO = pathlib.Path('/Users/jaganat/git_projects/astro_vedabase')
REPO = pathlib.Path('/Users/jaganat/git_projects/vedabase-original')
sys.path.insert(0, str(HERE))
from sincronizar_diff import d1, q, patron
from verificar_paridad import ref_de


def sd(s):
    s = unicodedata.normalize('NFD', s or '')
    s = ''.join(c for c in s if unicodedata.category(c) != 'Mn')
    return ' '.join(re.sub(r'[^A-Za-z0-9]+', ' ', s.lower()).split())


def main():
    aplicar = '--aplicar' in sys.argv
    fecha = '2026-08-11'
    pend = []
    for l in open(REPO / 'corrections.jsonl', encoding='utf-8'):
        try: d = json.loads(l)
        except Exception: continue
        if d.get('date') != fecha or not d.get('file'): continue
        par = (d.get('replace') or {}).get('en') or []
        if len(par) != 2 or not par[1]: continue      # las supresiones aparte
        r = ref_de(d['file'])
        if not r: continue
        f = REPO / d['file']
        if not f.exists(): continue
        # condicion 1: el repo tiene que decir HOY el texto nuevo
        if par[1] not in f.read_text(encoding='utf-8'): continue
        pend.append((r, d['file'], par[0], par[1]))
    print(f'correcciones vivas en el repo: {len(pend)}')

    res = collections.Counter(); sinancla = []
    porref = collections.defaultdict(list)
    for r, f, a, b in pend: porref[r].append((a, b))

    for ref, cambios in sorted(porref.items()):
        filas = d1(f"SELECT COALESCE(purport,'') p, COALESCE(translation,'') t, "
                   f"COALESCE(synonyms,'') s, COALESCE(verse_text,'') v, "
                   f"COALESCE(devanagari,'') d "
                   f"FROM verses WHERE ref={q(ref)} AND lang='en'", js=True)
        if not filas: res['sin fila en D1'] += len(cambios); continue
        r0 = filas[0]
        stmts = []
        for a, b in cambios:
            # LAS CINCO COLUMNAS. Mirando solo purport/translation/synonyms, los
            # arreglos del verso y del devanagari salian como «sin ancla» aunque
            # ya estuvieran puestos.
            if sd(b) and sd(b) in sd(' '.join(r0[k] for k in ('p','t','s','v','d'))):
                res['ya estaba en D1'] += 1; continue
            hecho = False
            for campo, val in (('purport', r0['p']), ('translation', r0['t']),
                               ('synonyms', r0['s']), ('verse_text', r0['v']),
                               ('devanagari', r0['d'])):
                ms = list(patron(a).finditer(val))
                if len(ms) != 1: continue
                lit = ms[0].group(0)
                stmts.append(f"UPDATE verses SET {campo}=REPLACE({campo},{q(lit)},{q(b)}) "
                             f"WHERE ref={q(ref)} AND lang='en';")
                hecho = True; break
            if not hecho:
                res['sin ancla unica: D1 dice otra cosa ahi'] += 1
                sinancla.append({'ref': ref, 'viejo': a[:130], 'nuevo': b[:130]})
        if not stmts: continue
        res['empujadas'] += len(stmts)
        print(f'  {ref}: {len(stmts)}')
        if aplicar:
            sql = HERE / '_push.sql'
            sql.write_text('\n'.join(stmts) + '\n', encoding='utf-8')
            p = subprocess.run(['npx', 'wrangler', 'd1', 'execute', 'vedabase-search-db',
                                '--remote', '--file', str(sql)], capture_output=True, text=True,
                               cwd=str(ASTRO),
                               env={**os.environ, 'CF_API_TOKEN': '', 'CLOUDFLARE_API_TOKEN': ''})
            sql.unlink(missing_ok=True)
            if 'rows_written' not in p.stdout:
                res['FALLO en D1'] += 1; print('    FALLO')

    print()
    for k, v in res.most_common(): print(f'  {v:5}  {k}')
    json.dump(sinancla, open(HERE / 'd1_sin_ancla.json', 'w'), ensure_ascii=False, indent=1)
    if not aplicar: print('\n(ensayo: anade --aplicar)')
    return 0


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