#!/usr/bin/env python3
"""Lleva a D1 lo que `leer_palabra_impreso.py` da por decidido.

El aplicador anterior exigia contexto de tres palabras a la izquierda y dos a
la derecha, y colocaba 5 de 17: el contexto viene del repo y D1 difiere tambien
alrededor, asi que el patron no casaba. Aqui se prueba de mas ancho a mas
estrecho y se acepta el primero que aparezca UNA sola vez en el campo:

    3 izq + 2 der  ->  2 + 1  ->  1 + 1  ->  la palabra sola

La condicion de una sola coincidencia es lo que hace seguro bajar hasta la
palabra sola: si «or» sale seis veces en el significado, no se toca.

Uso:
    python3 aplicar_leido.py            # ensayo
    python3 aplicar_leido.py --aplicar
"""
import json
import os
import pathlib
import re
import subprocess
import sys

HERE = pathlib.Path(__file__).resolve().parent
ASTRO = HERE.parent.parent
sys.path.insert(0, str(HERE))
from pagina_de_ref import norm  # noqa: E402

ENTRE = r'(?:[\s]|\*|_|</?em>|</?i>)+'
# Sin limite de palabra, «as» casa dentro de «brāhmaṇas» y el reemplazo
# produce «brāhmaṇto be». Me paso el 15-ago: el script cometio exactamente
# el error que estaba buscando.
LIMITE = r'(?<![\w\u0100-\u1EFF])%s(?![\w\u0100-\u1EFF])'


def q(s):
    return "'" + str(s).replace("'", "''") + "'"


def d1(sql):
    p = subprocess.run(['npx', 'wrangler', 'd1', 'execute', 'vedabase-search-db', '--remote',
                        '--json', '--command', sql], capture_output=True, text=True,
                       cwd=str(ASTRO),
                       env={**os.environ, 'CF_API_TOKEN': '', 'CLOUDFLARE_API_TOKEN': ''})
    try:
        return json.loads(p.stdout)[0]['results']
    except Exception:
        return []


def main():
    aplicar = '--aplicar' in sys.argv
    casos = json.loads((HERE / 'leido_del_impreso.json').read_text(encoding='utf-8'))['D1 equivocado']
    n = saltados = 0
    for x in casos:
        # de mayusculas no puede arbitrar el OCR: se normaliza a minusculas
        if norm(x['repo']) == norm(x['d1']):
            saltados += 1
            continue
        filas = d1(f"SELECT COALESCE(purport,'') p, COALESCE(translation,'') t "
                   f"FROM verses WHERE ref={q(x['ref'])} AND lang='en'")
        if not filas:
            saltados += 1
            continue
        iz = x.get('izq', '').split()
        de = x.get('der', '').split()
        hecho = False
        for ni, nd in ((3, 2), (2, 1), (1, 1), (0, 0)):
            viejo = ' '.join(iz[-ni:] * (ni > 0) + [x['d1']] + de[:nd] * (nd > 0))
            pat = ENTRE.join(re.escape(w) for w in viejo.split())
            for col, val in (('purport', filas[0]['p']), ('translation', filas[0]['t'])):
                m = list(re.finditer(pat, val))
                if len(m) != 1:
                    continue
                tramo = m[0].group(0)
                dentro = re.sub(LIMITE % ENTRE.join(re.escape(w) for w in x['d1'].split()),
                                lambda _: x['repo'], tramo, count=1)
                if dentro == tramo:
                    continue
                print(f"  {x['ref']:16} {col:11} {x['d1'][:22]!r:24} -> {x['repo'][:22]!r}"
                      f"   (contexto {ni}+{nd})")
                if aplicar:
                    d1(f"UPDATE verses SET {col} = "
                       f"{q(val[:m[0].start()] + dentro + val[m[0].end():])} "
                       f"WHERE ref={q(x['ref'])} AND lang='en';")
                n += 1
                hecho = True
                break
            if hecho:
                break
        if not hecho:
            saltados += 1
            print(f"  {x['ref']:16} sin sitio inequivoco, no toco")
    print(f'\n  aplicados: {n}   saltados: {saltados}')
    if not aplicar:
        print('  (ensayo: anade --aplicar)')
    return 0


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