#!/usr/bin/env python3
"""
Boletín Oficial → CSV para importar en WordPress
Extrae avisos de un archivo .doc o .docx y genera un CSV listo para importar
con el plugin "Really Simple CSV Importer".

Uso:
    python boletin_to_csv.py BO29.doc
    python boletin_to_csv.py BO29.docx
"""

import sys
import os
import csv
import re
import shutil
import tempfile
import subprocess
from pathlib import Path
from collections import Counter


# Categorías que llevan etiqueta del año
CATS_CON_ETIQUETA = {
    "Leyes",
    "Decretos",
    "Resoluciones",
    "Decretos Municipales",
    "Ordenanzas",
    "Resoluciones Municipales",
    "Partidos Políticos",
}

# Mapeo recuadro del .doc → categoría/s de WordPress
# Para recuadros con múltiples categorías, se analiza el contenido del aviso
RECUADROS = {
    "LEYES - DECRETOS - RESOLUCIONES":    "LEYES-DECRETOS-RESOLUCIONES",
    "MUNICIPIOS - COMISIONES MUNICIPALES": "MUNICIPIOS",
    "LICITACIONES - CONCURSO DE PRECIOS": "Licitaciones",
    "CONTRATOS - CONVOCATORIAS - ACTAS":  "Contratos",
    "REMATES":                            "Remates",
    "CONCURSOS Y QUIEBRAS":               "Concursos y Quiebras",
    "PARTIDOS POLITICOS":                 "Partidos Políticos",
    "PARTIDOS POLÍTICOS":                 "Partidos Políticos",
    "EDICTOS DE MINAS":                   "Minas",
    "EDICTOS DE USUCAPION":               "Usucapión",
    "EDICTOS DE USUCAPIÓN":               "Usucapión",
    "EDICTOS DE NOTIFICACION":            "Notificaciones",
    "EDICTOS DE NOTIFICACIÓN":            "Notificaciones",
    "EDICTOS DE CITACION":                "Citación",
    "EDICTOS DE CITACIÓN":                "Citación",
    "EDICTOS SUCESORIOS":                 "Sucesorios",
}


def clasificar_por_contenido_general(first):
    """Para LEYES-DECRETOS-RESOLUCIONES: distingue por primera línea."""
    if first.startswith("LEY"):
        return "Leyes"
    if first.startswith("DECRETO"):
        return "Decretos"
    if first.startswith("RESOLUCION") or first.startswith("RESOLUCIÓN"):
        return "Resoluciones"
    return "Resoluciones"  # default


def clasificar_municipios(first):
    """Para MUNICIPIOS-COMISIONES MUNICIPALES: distingue por primera línea."""
    if first.startswith("DECRETO"):
        return "Decretos Municipales"
    if first.startswith("ORDENANZA"):
        return "Ordenanzas"
    if first.startswith("RESOLUCION") or first.startswith("RESOLUCIÓN"):
        return "Resoluciones Municipales"
    return "Decretos Municipales"  # default


def encontrar_libreoffice():
    rutas_windows = [
        r"C:\Program Files\LibreOffice\program\soffice.exe",
        r"C:\Program Files (x86)\LibreOffice\program\soffice.exe",
    ]
    for ruta in rutas_windows:
        if os.path.exists(ruta):
            return ruta
    return shutil.which("soffice")


def convertir_doc_a_docx(doc_path):
    soffice = encontrar_libreoffice()
    if not soffice:
        print("ERROR: LibreOffice no encontrado.")
        print("Instalalo desde https://www.libreoffice.org y reiniciá la computadora.")
        print("O convertí el archivo a .docx desde Word manualmente.")
        sys.exit(1)
    tmpdir = tempfile.mkdtemp()
    try:
        result = subprocess.run(
            [soffice, "--headless", "--convert-to", "docx", "--outdir", tmpdir, doc_path],
            capture_output=True, text=True
        )
        if result.returncode != 0:
            print(f"ERROR al convertir: {result.stderr}")
            sys.exit(1)
        out_name = Path(doc_path).stem + ".docx"
        final = os.path.join(tempfile.gettempdir(), out_name)
        shutil.copy(os.path.join(tmpdir, out_name), final)
        return final
    finally:
        shutil.rmtree(tmpdir, ignore_errors=True)


def extraer_avisos(docx_path, titulo_boletin, anio):
    from docx import Document
    doc = Document(docx_path)

    # --- NOTA: cuando trabajemos con el .doc original, aquí leeremos
    # los recuadros directamente del XML para clasificar con precisión.
    # Por ahora clasificamos por el contenido de la primera línea. ---

    sep_indices = []
    for i, para in enumerate(doc.paragraphs):
        if "pBdr" in para._element.xml and para.text.strip():
            sep_indices.append(i)

    blocks = []
    prev = 0
    for sep_i in sep_indices:
        block = [doc.paragraphs[j].text.strip()
                 for j in range(prev, sep_i + 1)
                 if doc.paragraphs[j].text.strip()]
        if block:
            blocks.append(block)
        prev = sep_i + 1

    last = [doc.paragraphs[j].text.strip()
            for j in range(prev, len(doc.paragraphs))
            if doc.paragraphs[j].text.strip()]
    if last:
        blocks.append(last)

    avisos = []
    for lines in blocks:
        first = lines[0].upper()

        # Clasificar categoría por contenido
        if first.startswith("LEY"):
            category = "Leyes"
        elif first.startswith("DECRETO") and "MUNICIPAL" not in first:
            category = "Decretos"
        elif first.startswith("DECRETO") and "MUNICIPAL" in first:
            category = "Decretos Municipales"
        elif first.startswith("ORDENANZA"):
            category = "Ordenanzas"
        elif (first.startswith("RESOLUCION") or first.startswith("RESOLUCIÓN")) and "MUNICIPAL" in first:
            category = "Resoluciones Municipales"
        elif first.startswith("RESOLUCION") or first.startswith("RESOLUCIÓN") or "INSTITUTO DE VIVIENDA" in first:
            category = "Resoluciones"
        elif "MUNICIPALIDAD" in first or "MUNICIPIO" in first or "COMISION MUNICIPAL" in first or "COMISIÓN MUNICIPAL" in first:
            category = "Decretos Municipales"
        elif "PARTIDO" in first and "POLITIC" in first:
            category = "Partidos Políticos"
        elif "LICITACION" in first or "CONCURSO DE PRECIO" in first:
            category = "Licitaciones"
        elif "REMATE" in first:
            category = "Remates"
        elif "QUIEBRA" in first or ("CONCURSO" in first and "PRECIO" not in first):
            category = "Concursos y Quiebras"
        elif "MINAS" in first:
            category = "Minas"
        elif "USUCAP" in first:
            category = "Usucapión"
        elif "NOTIFICACI" in first:
            category = "Notificaciones"
        elif "CITACI" in first:
            category = "Citación"
        elif "SUCESORIO" in first or "TRIBUNAL DE FAMILIA" in " ".join(lines).upper() or "JUZGADO" in first:
            category = "Sucesorios"
        elif first.startswith("ACTA") or first.startswith("CONTRATO") or first.startswith("CESION") or \
             first.startswith("ESCRITURA") or "INSTRUMENTO CONSTITUTIVO" in first or \
             "DECLARACION JURADA" in first or "DECLARACIÓN JURADA" in first or "ANEXO" in first:
            category = "Contratos"
        else:
            category = "Sin clasificar"

        etiqueta = anio if category in CATS_CON_ETIQUETA else ""
        html_content = "\n".join(f"<p>{line}</p>" for line in lines if line.strip())

        avisos.append({
            "post_title":   titulo_boletin,
            "post_content": html_content,
            "post_status":  "publish",
            "post_type":    "post",
            "tax_category": category,
            "tax_post_tag": etiqueta,
        })

    return avisos


def main():
    try:
        from docx import Document
    except ImportError:
        print("Instalando python-docx...")
        subprocess.run([sys.executable, "-m", "pip", "install", "python-docx", "-q"])

    if len(sys.argv) < 2:
        print("Uso: python boletin_to_csv.py archivo.doc")
        print("     python boletin_to_csv.py archivo.docx")
        sys.exit(1)

    archivo = sys.argv[1]

    if archivo.lower().endswith(".doc"):
        print(f"Convirtiendo {archivo} a .docx con LibreOffice...")
        archivo = convertir_doc_a_docx(archivo)
        print(f"  → Listo\n")
    elif not archivo.lower().endswith(".docx"):
        print("ERROR: El archivo debe ser .doc o .docx")
        sys.exit(1)

    print("─" * 55)
    titulo = input("Título del boletín (ej: BOLETIN OFICIAL Nº 29 – 09/03/2026): ").strip()
    if not titulo:
        print("ERROR: El título no puede estar vacío.")
        sys.exit(1)

    match = re.search(r'\b(20\d{2})\b', titulo)
    anio = match.group(1) if match else ""
    if anio:
        print(f"  → Etiqueta de año detectada: {anio}")
    print("─" * 55)
    print()

    salida = Path(sys.argv[1]).stem + "_avisos.csv"

    print("Extrayendo avisos...")
    avisos = extraer_avisos(archivo, titulo, anio)
    print(f"  → {len(avisos)} avisos encontrados")

    resumen = Counter(a["tax_category"] for a in avisos)
    print("\nResumen por categoría:")
    for cat, n in sorted(resumen.items()):
        print(f"  {n:3d}  {cat}")

    campos = ["post_title", "post_content", "post_status", "post_type", "tax_category", "tax_post_tag"]
    with open(salida, "w", newline="", encoding="utf-8-sig") as f:
        writer = csv.DictWriter(f, fieldnames=campos)
        writer.writeheader()
        writer.writerows(avisos)

    print(f"\n✓ CSV generado: {salida}")
    print(f"  {len(avisos)} entradas listas para importar en WordPress")
    print()
    print("Próximo paso: Herramientas → Import CSV en WordPress")


if __name__ == "__main__":
    main()
