import sys
import os
import logging
import pathlib
import socket
from datetime import datetime
BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
sys.path.append(BASE_DIR)
from helpers.cuit_homonimia import buscar_cuit_sugerido, seleccionar_mejor_cuit
from helpers.db import conectar, ejecutar_sp, ejecutar_sp_raw
from helpers.logging_setup import setup_logging, setup_logging_db

ID_PROCESO = int(os.getenv("ID_PROCESO_HOMONIMIA", 0))

_run_id = setup_logging("homonimia")

def obtener_edictos(tabla, fecha_desde, fecha_hasta, conn):
    try:
        logging.debug(f"getData tabla={tabla} desde={fecha_desde} hasta={fecha_hasta}")
        return ejecutar_sp_raw('recorrerEdictos', ('getData', tabla, None, None, fecha_desde, fecha_hasta), conn)
    except Exception as e:
        logging.error(f"Error al obtener edictos tabla={tabla}: {e}")
        return None

def asignar_cuit(tabla, id, cuit, rol, conn):
    try:
        logging.debug(f"updateData tabla={tabla} id={id} cuit={cuit} rol={rol}")
        ejecutar_sp_raw('recorrerEdictos', ('updateData', tabla, id, cuit, None, None, rol), conn)
        return True
    except Exception as e:
        logging.error(f"Error al asignar CUIT id={id} tabla={tabla} cuit={cuit}: {e}")
        return False

def flag_negativa(tabla, id, conn):
    try:
        ejecutar_sp_raw('recorrerEdictos', ('cuit_asignacion_negativo', tabla, id, None), conn)
    except Exception as e:
        logging.error(f"Error al ejecutar flag_negativa id={id} tabla={tabla}: {e}")

def flag_multiple(tabla, id, conn):
    try:
        ejecutar_sp_raw('recorrerEdictos', ('cuit_asignacion_multiple', tabla, id, None), conn)
    except Exception as e:
        logging.error(f"Error al ejecutar flag_multiple id={id} tabla={tabla}: {e}")

def validar_fecha(fecha_str):
    try:
        return datetime.strptime(fecha_str, "%Y-%m-%d").date()
    except (ValueError, TypeError):
        return None

def proceso_desde_tabla(tabla, fecha_desde, fecha_hasta):
    logging.info(f"Inicio | tabla={tabla} | desde={fecha_desde} | hasta={fecha_hasta}")
    conn = conectar()
    contador_asigna = 0
    contador_no_asigna = 0
    contador_multiple_resultados = 0

    edictos = obtener_edictos(tabla, fecha_desde, fecha_hasta, conn)
    if not edictos:
        logging.info("No se encontraron edictos.")
        conn.close()
        return 0, 0, 0

    # cursor temporal solo para que buscar_cuit_sugerido pueda acceder a conn via cursor.connection
    search_cursor = conn.cursor()

    try:
        for i, edicto in enumerate(edictos, start=1):
            id_edicto = edicto[0]
            cuit = edicto[1]
            razon_social = edicto[2]
            provincia = edicto[3] if len(edicto) > 3 else None
            rol = edicto[4] if len(edicto) > 4 else None
            logging.info(f"[{i}] id={id_edicto} cuit={cuit} razon_social='{razon_social}'")

            sugeridos = buscar_cuit_sugerido(cuit, razon_social, provincia, search_cursor)

            if sugeridos:
                if isinstance(sugeridos, list):
                    mejor = seleccionar_mejor_cuit(razon_social, sugeridos)
                    if mejor:
                        logging.info(f"ID {id_edicto} - '{razon_social}': Ganador claro: {mejor}")
                        if asignar_cuit(tabla, id_edicto, mejor, rol, conn):
                            contador_asigna += 1
                        else:
                            contador_no_asigna += 1
                    else:
                        logging.info(f"ID {id_edicto} - '{razon_social}': Multiples sin resolver, sugeridos: {sugeridos}")
                        flag_multiple(tabla, id_edicto, conn)
                        contador_multiple_resultados += 1
                else:
                    logging.info(f"ID {id_edicto} - '{razon_social}': Sugerido: {sugeridos}")
                    if asignar_cuit(tabla, id_edicto, sugeridos, rol, conn):
                        contador_asigna += 1
                    else:
                        contador_no_asigna += 1
            else:
                contador_no_asigna += 1
                logging.info(f"ID {id_edicto} - '{razon_social}': No se pudo sugerir CUIT")
                flag_negativa(tabla, id_edicto, conn)

        total = contador_asigna + contador_no_asigna + contador_multiple_resultados
        logging.info(f"Fin | Asignados: {contador_asigna} | Multiples: {contador_multiple_resultados} | No asignados: {contador_no_asigna} | Total: {total}")
        conn.commit()
        return total, contador_asigna + contador_multiple_resultados, contador_no_asigna
    finally:
        search_cursor.close()
        conn.close()


_TABLAS_PERMITIDAS = {
    'edictos_ia',
    'sociedades_constituciones_relaciones_vinculadas',
    'sociedades_constituciones_relaciones_personas',
}

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print("Uso: python limpieza_homonimia.py <NOMBRE_TABLA> [FECHA_DESDE] [FECHA_HASTA]")
        print(f"TABLAS DISPONIBLES: {' '.join(repr(t) for t in sorted(_TABLAS_PERMITIDAS))}")
        print("Ejemplo: python procesamiento/homonimia/limpieza_homonimia.py edictos_ia 2025-01-01 2025-08-01")
        sys.exit(1)

    tabla = sys.argv[1]
    if tabla not in _TABLAS_PERMITIDAS:
        print(f"Error: tabla '{tabla}' no permitida. Tablas válidas: {', '.join(sorted(_TABLAS_PERMITIDAS))}")
        sys.exit(1)
    fecha_desde = validar_fecha(sys.argv[2]) if len(sys.argv) > 2 else None
    fecha_hasta = validar_fecha(sys.argv[3]) if len(sys.argv) > 3 else None

    id_log = None
    try:
        result = ejecutar_sp('PRS_iniciar', [
            ID_PROCESO,
            socket.gethostbyname(socket.gethostname()),
            os.getpid(),
            socket.gethostname(),
            12,
            _run_id,
        ])
        if result:
            id_log = result[0].get('id_log')
            setup_logging_db(id_log)
    except Exception as e:
        logging.warning(f"PRS_iniciar falló: {e}")

    total = ok_count = error_count = 0
    try:
        total, ok_count, error_count = proceso_desde_tabla(tabla, fecha_desde, fecha_hasta)
    except Exception as e:
        error_count = 1
        logging.error(f"Error en proceso_desde_tabla: {e}")
    finally:
        if id_log is not None:
            try:
                ejecutar_sp('PRS_finalizar', [id_log, None, total, ok_count, error_count])
            except Exception as e:
                logging.warning(f"PRS_finalizar falló: {e}")
