#!/usr/bin/env python3
"""Alinea el repo con D1 en los idiomas traducidos, tramo a tramo.

Por que en esta direccion y no al reves. En ingles la fuente de verdad es el
repo, porque esta cotejado contra los escaneos del impreso. En los idiomas
traducidos NO hay escaneo con que arbitrar: las diferencias entre repo y D1 no
son de fidelidad al papel sino dos traducciones distintas de la misma frase. El
16-ago se decidio que en ese caso manda D1, que es lo que ya leen los usuarios.

Que NO toca. Los tramos con escritura india o con diacriticos sanscritos: esos
SI son arbitrables contra el escaneo ingles —el devanagari y los terminos son
los mismos en todos los idiomas— y merecen mirarse uno a uno, no sincronizarse a
ciegas. Se informan aparte.

Como escribe. Alinea las palabras de los dos lados con `difflib` y aplica cada
tramo distinto buscandolo en el .md con marcado y puntuacion tolerados. Si el
tramo no aparece UNA sola vez, no toca nada: colocarlo en el sitio equivocado es
peor que dejar la divergencia.

Uso:
    python3 sincronizar_idioma.py --lang es            # ensayo
    python3 sincronizar_idioma.py --lang es --aplicar
"""
import difflib
import json
import pathlib
import re
import sys

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

ENTRE = r'(?:[\s\*_,;:.!?()\[\]"\'’‘“”—–«»-]|</?em>|</?i>|\\)+'
INDIO = re.compile(r'[ऀ-ॿঀ-৿]')
SANSCRITO = re.compile(r'[āīūṛṝḷḹṅñṭḍṇśṣḥṁṃ]')


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


def main():
    aplicar = '--aplicar' in sys.argv
    lang = sys.argv[sys.argv.index('--lang') + 1]
    raiz = raiz_de(lang)
    casos = json.loads((HERE / f'paridad_completa_{lang}.json').read_text(encoding='utf-8'))
    hechos = sanscrito = ambiguos = 0
    for x in casos:
        f = raiz / x['file']
        if not f.is_file():
            continue
        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(x['ref'])} AND lang='{lang}'")
        if not filas:
            continue
        fila = filas[0]
        md = f.read_text(encoding='utf-8')
        a = pal(md)
        b = pal(' '.join((fila['v'], fila['d'], fila['s'], fila['t'], fila['p'])))
        nuevo = md
        for op, i1, i2, j1, j2 in difflib.SequenceMatcher(None, b, a).get_opcodes():
            if op != 'replace':
                continue
            viejo_r, nuevo_d = ' '.join(a[j1:j2]), ' '.join(b[i1:i2])
            if not viejo_r or not nuevo_d:
                continue
            # En hindi la PROSA va en devanagari, asi que descartar todo lo
            # que lleve escritura india dejaria el idioma entero sin tocar: en
            # la primera pasada salieron 0 alineados y 47 «sanscritos». Ahi solo
            # se aparta la transliteracion en alfabeto latino, que es la que
            # arbitra el escaneo ingles. En los demas idiomas se apartan las dos.
            indio = INDIO.search(viejo_r + nuevo_d) and lang != 'hi'
            if indio or SANSCRITO.search(viejo_r + nuevo_d):
                sanscrito += 1
                print(f"  {x['ref']:14} SANSCRITO, no toco: {viejo_r[:34]!r} / {nuevo_d[:34]!r}")
                continue
            # Anclado por el contexto IZQUIERDO, en cascada. Buscar el tramo
            # suelto fallaba en la mitad de los casos: o no aparece porque el
            # .md lo escribe con marcado en medio, o aparece varias veces
            # porque son palabras corrientes. Con 5, 4, 3 y 2 palabras delante
            # se coloca sin ambiguedad.
            colocado = False
            for k in (5, 4, 3, 2, 0):
                izq = b[max(0, i1 - k):i1] if k else []
                pat = ENTRE.join(re.escape(w) for w in list(izq) + viejo_r.split())
                m = list(re.finditer(pat, nuevo))
                if len(m) != 1:
                    continue
                tramo = m[0].group(0)
                pat_solo = ENTRE.join(re.escape(w) for w in viejo_r.split())
                dentro = re.sub(pat_solo, lambda _: nuevo_d, tramo, count=1)
                if dentro == tramo:
                    continue
                nuevo = nuevo[:m[0].start()] + dentro + nuevo[m[0].end():]
                colocado = True
                break
            if not colocado:
                ambiguos += 1
                continue
            print(f"  {x['ref']:14} {viejo_r[:36]!r:40} -> {nuevo_d[:36]!r}")
            hechos += 1
        if aplicar and nuevo != md:
            f.write_text(nuevo, encoding='utf-8')
    print(f'\n  alineados con D1: {hechos}   sanscrito (a mirar aparte): {sanscrito}   '
          f'sin sitio unico: {ambiguos}')
    if not aplicar:
        print('  (ensayo: anade --aplicar)')
    return 0


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