import pandas as pd
import openpyxl
import unicodedata
from thefuzz import process, fuzz

def eliminar_tildes(texto):
    if not texto or str(texto).upper() == "NONE":
        return ""
    texto = unicodedata.normalize('NFD', str(texto))
    texto = texto.encode('ascii', 'ignore').decode("utf-8")
    return texto.upper().strip()

def actualizar_nombres_estandar(ruta_archivo, hoja_datos, hoja_maestra):
    try:
        print(f"Abriendo archivo: {ruta_archivo}...")
        wb = openpyxl.load_workbook(ruta_archivo)
        
        ws_maestra = wb[hoja_maestra]
        data_maestra = list(ws_maestra.values)
        cols_maestra = [str(c).strip() for c in data_maestra[0]]
        df_maestro = pd.DataFrame(data_maestra[1:], columns=cols_maestra)
        
        # Diccionario estricto por Departamento
        maestra_por_depa = {}
        # Lista para búsqueda de rescate (Distritos Especiales)
        maestra_global = []

        for _, row in df_maestro.iterrows():
            d_org, m_org = str(row['depa_db']), str(row['muni_db'])
            d_limpio, m_limpio = eliminar_tildes(d_org), eliminar_tildes(m_org)
            
            if d_limpio not in maestra_por_depa:
                maestra_por_depa[d_limpio] = []
            maestra_por_depa[d_limpio].append({'m_limpio': m_limpio, 'm_org': m_org, 'd_org': d_org})
            maestra_global.append({'m_limpio': m_limpio, 'm_org': m_org, 'd_org': d_org})

        ws_datos = wb[hoja_datos]
        header = [str(cell.value).strip() if cell.value else "" for cell in ws_datos[1]]
        col_muni = header.index('muni_nombre') + 1 
        col_depa = header.index('depa_nombre') + 1

        cont_actualizados = 0
        incidencias = []

        for r_idx in range(2, ws_datos.max_row + 1):
            val_muni_raw = str(ws_datos.cell(row=r_idx, column=col_muni).value or "")
            val_depa_raw = str(ws_datos.cell(row=r_idx, column=col_depa).value or "")
            
            if not val_muni_raw or val_muni_raw.upper() == "NONE": continue

            m_limpio = eliminar_tildes(val_muni_raw)
            d_limpio = eliminar_tildes(val_depa_raw)
            match_encontrado = False

            # --- ESTRATEGIA 1: BUSCAR DEPARTAMENTO PRIMERO (EL MURO DE SEGURIDAD) ---
            depas_maestros = list(maestra_por_depa.keys())
            # Usamos un scorer más estricto para el departamento
            mejor_depa, d_score = process.extractOne(d_limpio, depas_maestros, scorer=fuzz.ratio)

            # Si el departamento es confiable (>75) O si es una variante conocida
            if d_score > 75:
                opciones_muni = maestra_por_depa[mejor_depa]
                nombres_muni = [x['m_limpio'] for x in opciones_muni]
                
                # Buscamos el municipio SOLO dentro de ese departamento
                mejor_muni, m_score = process.extractOne(m_limpio, nombres_muni, scorer=fuzz.token_set_ratio)
                
                if m_score > 80:
                    idx = nombres_muni.index(mejor_muni)
                    ws_datos.cell(row=r_idx, column=col_muni).value = opciones_muni[idx]['m_org']
                    ws_datos.cell(row=r_idx, column=col_depa).value = opciones_muni[idx]['d_org']
                    match_encontrado = True
                else:
                    incidencias.append(f"Fila {r_idx}: El municipio '{val_muni_raw}' no existe en '{mejor_depa}'. No se aplica cambio para evitar error de homónimo.")

            # --- ESTRATEGIA 2: RESCATE GLOBAL (SOLO SI EL DEPARTAMENTO ES IGUAL AL MUNICIPIO) ---
            # Ejemplo: Barranquilla - Barranquilla
            if not match_encontrado and (m_limpio == d_limpio or d_score < 50):
                nombres_muni_global = [x['m_limpio'] for x in maestra_global]
                m_global, mg_score = process.extractOne(m_limpio, nombres_muni_global, scorer=fuzz.token_set_ratio)
                
                if mg_score > 95:
                    idx = nombres_muni_global.index(m_global)
                    ws_datos.cell(row=r_idx, column=col_muni).value = maestra_global[idx]['m_org']
                    ws_datos.cell(row=r_idx, column=col_depa).value = maestra_global[idx]['d_org']
                    match_encontrado = True
                    incidencias.append(f"Fila {r_idx}: Rescate global exitoso para '{val_muni_raw}' -> {maestra_global[idx]['d_org']}")

            if match_encontrado:
                cont_actualizados += 1
            elif not any(inc.startswith(f"Fila {r_idx}:") for inc in incidencias):
                incidencias.append(f"Fila {r_idx}: Sin coincidencia para '{val_muni_raw}' en '{val_depa_raw}'")

        # Guardar y Reporte
        ruta_salida = ruta_archivo.replace(".xlsx", "_CORREGIDO.xlsx")
        wb.save(ruta_salida)
        
        with open("reporte_verificacion.txt", "w", encoding="utf-8") as f:
            f.write("REPORTE DE VERIFICACIÓN DE MUNICIPIOS\n" + "="*40 + "\n")
            f.write("\n".join(incidencias))

        print(f"Proceso terminado. Actualizados: {cont_actualizados}. Revisar reporte_verificacion.txt para errores.")

    except Exception as e:
        print(f"Error crítico: {e}")

# --- EJECUCIÓN ---
ruta = r'C:\\Users\\james\\OneDrive\\Desktop\\cargue reps 11-03-2026\\Capacidad.xlsx'
actualizar_nombres_estandar(ruta, hoja_datos='Capacidad', hoja_maestra='DepaMuni')
