#!/usr/bin/env python3
"""Quita de D1 los tramos que aparecen repetidos y el repo trae una sola vez.

De donde salen. Los reemplazos masivos y las reinserciones dejaron fragmentos
duplicados dentro de un mismo campo:

    sb/3/15/4     «he is addressed here as the god of the demigods, and because»
                  tres veces seguidas
    cc/adi/13/61  «the trunks of the trunks of»
    cc/madhya/1/44 «(15) the previous the previous attraction» — residuo del
                  reemplazo the -> previous

Por que NO con una expresion regular de repeticion. `((\\w+ ){1,12}?)\\1` sobre un
significado de 50 KB hace backtracking exponencial: se comio diez minutos sin
terminar ni una referencia. Aqui se alinea la lista de palabras del repo contra
la de D1 con `difflib`, que es lineal en la practica, y solo entonces se busca
el tramo sobrante como cadena literal.

Uso:
    python3 quitar_duplicado.py                 # ensayo, todas las del grupo
    python3 quitar_duplicado.py --aplicar
    python3 quitar_duplicado.py --ref cc/adi/13/61
"""
import difflib
import json
import os
import pathlib
import re
import subprocess
import sys

HERE = pathlib.Path(__file__).resolve().parent
ASTRO = HERE.parent.parent
REPO = pathlib.Path('/Users/jaganat/git_projects/vedabase-original')
sys.path.insert(0, str(HERE))
from paridad_completa import pal  # noqa: E402

ENTRE = r'(?:[\s\*_,;:.!?()\[\]"\'’‘“”—–-]|</?em>|</?i>|<br\s*/?>|\\)+'


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 None


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


def main():
    aplicar = '--aplicar' in sys.argv
    solo = sys.argv[sys.argv.index('--ref') + 1] if '--ref' in sys.argv else None
    grupos = json.loads((HERE / 'paridad_clasificada.json').read_text(encoding='utf-8'))
    casos = grupos.get('texto solo en D1', [])
    if solo:
        casos = [x for x in casos if x['ref'] == solo]
    n = saltados = 0
    for x in casos:
        ref = x['ref']
        filas = d1(f"SELECT COALESCE(verse_text,'') v, COALESCE(devanagari,'') d, "
                   f"COALESCE(synonyms,'') s, COALESCE(translation,'') t, "
                   f"COALESCE(purport,'') p FROM verses WHERE ref={q(ref)} AND lang='en'")
        if not filas:
            saltados += 1
            continue
        fila = filas[0]
        a = pal((REPO / x['file']).read_text(encoding='utf-8'))
        b = pal(' '.join((fila['v'], fila['d'], fila['s'], fila['t'], fila['p'])))
        # Un tramo que sale como «delete» aqui y como «insert» alla es el mismo
        # texto cambiado de sitio: el .md pone el verso antes de la glosa y D1
        # lo guarda en otro campo. No es sobrante. Sin descartarlo, el primer
        # bloque era SIEMPRE la transliteracion y no se arreglaba ninguna.
        ops = list(difflib.SequenceMatcher(None, b, a).get_opcodes())
        movidos = {' '.join(a[j1:j2]) for op, i1, i2, j1, j2 in ops
                   if op in ('insert', 'replace') and j2 > j1}
        sobra = None
        for op, i1, i2, j1, j2 in ops:
            if op != 'delete' or i2 <= i1:
                continue
            if ' '.join(b[i1:i2]) in movidos:
                continue
            sobra = b[i1:i2]
            break
        if not sobra or len(' '.join(sobra)) < 3:
            saltados += 1
            continue
        pat = ENTRE.join(re.escape(w) for w in sobra)
        for col in ('purport', 'translation', 'synonyms'):
            val = fila[col[0]]
            m = list(re.finditer(pat, val))
            if len(m) != 1:
                continue
            # se borra el tramo y el separador que lo precede, para no dejar
            # dos espacios ni una coma suelta
            ini = m[0].start()
            while ini > 0 and val[ini - 1] in ' ,;':
                ini -= 1
            nuevo = val[:ini] + val[m[0].end():]
            print(f"  {ref:20} {col:11} - {' '.join(sobra)[:56]!r}")
            if aplicar:
                d1(f"UPDATE verses SET {col}={q(nuevo)} WHERE ref={q(ref)} AND lang='en';")
            n += 1
            break
        else:
            saltados += 1
            print(f"  {ref:20} sin sitio inequivoco: {' '.join(sobra)[:50]!r}")
    print(f'\n  quitados: {n}   saltados: {saltados}')
    if not aplicar:
        print('  (ensayo: anade --aplicar)')
    return 0


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