#!/usr/bin/env python3
"""Busca en el repo y en D1 palabras rotas por reemplazos en bloque.

De donde viene. Al cruzar el repo con D1 salieron de rebote «foodstuffstuff»,
«hisother», «appearsfrom», «Śrīpādṅkarācārya», «homogenousoneness»,
«virāṭaa-rūpa» en el repo y «Vedānta-sūtrass», «elderlyly»,
«Nāmārtha-sudhābhidhabhidha» en D1. Ninguno los buscaba nadie: aparecieron
porque los dos almacenes discrepaban. Si hubo pasadas de sustitucion sin ancla
de contexto, habra mas donde los dos coinciden — y ahi no los ve nadie.

Como se detecta sin diccionario. El escaneo es el vocabulario: una palabra que
esta en el texto y NO esta en el impreso es sospechosa. Sola, esa prueba da
demasiados falsos (el OCR se come palabras buenas), asi que ademas tiene que
parecer daño:

  - repeticion interna:  food(stuff)(stuff),  abhidha·abhidha,  sūtras·s
  - dos palabras pegadas: appears+from, homogenous+oneness — las dos mitades
    SI estan en el impreso
  - letra duplicada al final de la raiz: virāṭ·a·a

Uso:
    python3 barrer_destrozos.py            # el repo
    python3 barrer_destrozos.py --d1       # D1
"""
import json
import os
import pathlib
import re
import subprocess
import sys

HERE = pathlib.Path(__file__).resolve().parent
REPO = pathlib.Path('/Users/jaganat/git_projects/vedabase-original')
ASTRO = HERE.parent.parent
SURYA = HERE / 'surya'

LIBRO = {'bhagavad-gita-as-it-is': 'bg', 'srimad-bhagavatam': 'sb',
         'sri-caitanya-caritamrta': 'cc', 'krsna-the-supreme-personality-of-godhead': 'kb',
         'teachings-of-lord-caitanya': 'tlc', 'beyond-birth-and-death': 'bbd',
         'elevation-to-krsna-consciousness': 'ekc', 'teachings-of-queen-kunti': 'tqk',
         'path-of-perfection': 'pop', 'perfection-of-yoga': 'poy',
         'science-of-self-realization': 'ssr', 'nectar-of-devotion': 'nod',
         'nectar-of-instruction': 'noi', 'isopanisad': 'iso',
         'light-of-the-bhagavata': 'lob', 'on-the-way-to-krsna': 'owk',
         'perfect-questions-perfect-answers': 'pqpa', 'raja-vidya': 'rv',
         'easy-journey-to-other-planets': 'ej', 'topmost-yoga-system': 'ttp',
         'reservoir-of-pleasure': 'krp'}

PAL = re.compile(r"[A-Za-zÀ-ÿāīūṛṝḷḹṣśṇṭḍñṅṁḥ'’-]{4,}")
REPE = re.compile(r'(\w{3,})\1', re.I)
DOBLE_FINAL = re.compile(r'(\w)\1(?=[^aeiouāīū]|$)', re.I)


def texto_impreso(carpeta):
    d = SURYA / carpeta
    if not d.is_dir():
        return ''
    t = ' '.join(f.read_text(encoding='utf-8', errors='ignore')
                 for f in sorted(d.rglob('*.surya.txt')))
    return re.sub(r'\s+', ' ', t).lower()


def vocabulario(carpeta):
    d = SURYA / carpeta
    if not d.is_dir():
        return set()
    t = ' '.join(f.read_text(encoding='utf-8', errors='ignore')
                 for f in sorted(d.rglob('*.surya.txt')))
    return {w.lower() for w in PAL.findall(t)}


def sospechoso(w, voc):
    """(motivo, sugerencia) o None."""
    b = w.lower().strip("'’-")
    if b in voc or len(b) < 6:
        return None
    if REPE.search(b):
        # food(stuff)(stuff) -> quitar la repeticion
        return 'repeticion interna', REPE.sub(r'\1', b)
    for i in range(3, len(b) - 2):
        if b[:i] in voc and b[i:] in voc:
            return 'dos palabras pegadas', f'{b[:i]} {b[i:]}'
    m = re.search(r'(\w)\1', b)
    if m and b[:m.start() + 1] + b[m.end():] in voc:
        return 'letra duplicada', b[:m.start() + 1] + b[m.end():]
    return None


def texto_d1(pref):
    p = subprocess.run(['npx', 'wrangler', 'd1', 'execute', 'vedabase-search-db', '--remote',
                        '--json', '--command',
                        "SELECT COALESCE(translation,'')||' '||COALESCE(purport,'') t FROM verses "
                        f"WHERE lang='en' AND ref LIKE '{pref}/%'"],
                       capture_output=True, text=True, cwd=str(ASTRO),
                       env={**os.environ, 'CF_API_TOKEN': '', 'CLOUDFLARE_API_TOKEN': ''})
    try:
        return ' '.join(r['t'] for r in json.loads(p.stdout)[0]['results'])
    except Exception:
        return ''


def main():
    en_d1 = '--d1' in sys.argv
    hallazgos = []
    for carpeta, pref in sorted(LIBRO.items()):
        voc = vocabulario(carpeta)
        if not voc:
            continue
        if en_d1:
            texto = texto_d1(pref)
        else:
            d = REPO / carpeta
            texto = ' '.join(f.read_text(encoding='utf-8') for f in sorted(d.rglob('*.md'))) \
                if d.is_dir() else ''
        if not texto:
            continue
        # La prueba que de verdad discrimina. Que la forma corregida aparezca
        # en ALGUN sitio del impreso no vale: el OCR parte palabras al final de
        # linea, asi que «girl friends» sale aunque el impreso escriba
        # «girlfriends». Tiene que aparecer EN EL MISMO CONTEXTO — dos palabras
        # a cada lado— que la palabra sospechosa en el texto. Con eso los 716
        # falsos se quedan en los que son daño de verdad.
        impreso = texto_impreso(carpeta)
        pals = texto.split()
        vistos = set()
        for i, w in enumerate(pals):
            limpio = w.strip('*_`"\u201c\u201d()[]{}.,;:!?')
            if limpio in vistos or not PAL.fullmatch(limpio):
                continue
            r = sospechoso(limpio, voc)
            if not r:
                continue
            vistos.add(limpio)
            izq = ' '.join(x.strip('*_`"\u201c\u201d()[]{}.,;:!?').lower()
                           for x in pals[max(0, i - 2):i])
            der = ' '.join(x.strip('*_`"\u201c\u201d()[]{}.,;:!?').lower()
                           for x in pals[i + 1:i + 3])
            frase = ' '.join(y for y in (izq, r[1], der) if y)
            # el espacio justo detras de un guion es el corte de linea del
            # impreso, no una palabra partida: «avidyā-racita- viṣama…»
            if '- ' in r[1]:
                continue
            if frase in impreso:
                hallazgos.append({'libro': pref, 'palabra': limpio, 'motivo': r[0],
                                  'sugerencia': r[1], 'contexto': frase[:90]})
        print(f'  {pref:5} {len(voc):7} palabras en el impreso', end='\r', flush=True)
    salida = HERE / ('destrozos_d1.json' if en_d1 else 'destrozos_repo.json')
    salida.write_text(json.dumps(hallazgos, ensure_ascii=False, indent=1), encoding='utf-8')
    print(f'\n  sospechosos en {"D1" if en_d1 else "el repo"}: {len(hallazgos)}')
    for h in hallazgos[:40]:
        print(f"    {h['libro']:5} {h['palabra'][:34]:36} {h['motivo']:22} -> {h['sugerencia'][:34]!r}")
    return 0


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