#!/usr/bin/env python3
"""Empuja a D1 las correcciones vivas del repo que D1 no tiene, sea de la fecha
que sea.

`empujar_pendientes_d1.py` hacia esto para un dia concreto. Al montar la tabla de
notas aparecio que 389 correcciones anteriores nunca habian llegado —370 de ellas
de una sola tanda, la del 9 de agosto—, asi que la comprobacion tiene que ser
sobre TODO el ledger y no sobre la fecha de hoy. Se descubrio por casualidad: al
comprobar que el ancla de cada nota existiera en D1, doce no aparecian, y no era
que el ancla estuviese mal sino que la correccion no habia llegado.

Las dos condiciones no cambian:

  1. EL REPO MANDA. Solo se empuja si el fichero del repo dice HOY el texto
     nuevo. Asi una correccion revertida 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; si no aparece, es que D1 dice
     ahi una tercera cosa —una divergencia anterior a este trabajo—, y eso se
     informa y se deja.

Uso: python3 empujar_todas_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):
    """Normaliza SIN borrar la escritura india.

    Con la version que reducia a [A-Za-z0-9], el devanagari y el bengali
    desaparecian enteros: `sd(nuevo)` quedaba vacio, la comprobacion de «ya
    estaba» no podia dispararse y las diez correcciones de escritura india
    salian como «sin ancla unica» aunque ya estuvieran puestas en D1. Es el
    mismo fallo que hubo en `verificar_correcciones_d1.py`."""
    s = unicodedata.normalize('NFC', s or '')
    return ' '.join(re.sub(r'[^A-Za-z0-9ऀ-ॿঀ-৿]+', ' ',
                           s.lower()).split())


def main():
    aplicar = '--aplicar' in sys.argv
    pend = collections.defaultdict(list)
    for l in open(REPO / 'corrections.jsonl', encoding='utf-8'):
        try:
            d = json.loads(l)
        except Exception:
            continue
        par = (d.get('replace') or {}).get('en') or []
        if len(par) != 2 or not par[1] or not d.get('file'):
            continue
        f = REPO / d['file']
        if not f.exists() or par[1] not in f.read_text(encoding='utf-8'):
            continue
        r = ref_de(d['file'])
        if not r:
            continue
        # `ref_de` es el mapeo del auditor; D1 usa otro prefijo para Easy Journey
        pend[re.sub(r'^ejotp/', 'ej/', r)].append((par[0], par[1]))
    print(f'referencias con correcciones vivas en el repo: {len(pend)}')

    res = collections.Counter()
    sinancla = []
    refs = sorted(pend)
    for i, ref in enumerate(refs, 1):
        filas = d1(f"SELECT COALESCE(purport,'') p, COALESCE(translation,'') t, "
                   f"COALESCE(synonyms,'') s, COALESCE(verse_text,'') v, "
                   f"COALESCE(devanagari,'') d FROM verses "
                   f"WHERE ref={q(ref)} AND lang='en'", js=True)
        if not filas:
            res['sin fila en D1'] += len(pend[ref])
            continue
        r0 = filas[0]
        stmts = []
        for a, b in pend[ref]:
            # LAS CINCO COLUMNAS: mirando solo prosa, 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'] += 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
                stmts.append(f"UPDATE verses SET {campo}=REPLACE({campo},{q(ms[0].group(0))},"
                             f"{q(b)}) 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[:120], 'nuevo': b[:120]})
        if not stmts:
            continue
        res['empujadas'] += len(stmts)
        if aplicar:
            f = HERE / '_push_all.sql'
            f.write_text('\n'.join(stmts) + '\n', encoding='utf-8')
            p = subprocess.run(['npx', 'wrangler', 'd1', 'execute', 'vedabase-search-db',
                                '--remote', '--file', str(f)], capture_output=True, text=True,
                               cwd=str(ASTRO),
                               env={**os.environ, 'CF_API_TOKEN': '', 'CLOUDFLARE_API_TOKEN': ''})
            f.unlink(missing_ok=True)
            if 'rows_written' not in p.stdout:
                res['FALLO en D1'] += 1
                print(f'  FALLO {ref}')
        if i % 100 == 0:
            print(f'  {i}/{len(refs)}', flush=True)

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


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