# -*- coding: utf-8 -*-
"""
Script para mapear dinámicamente columnas de Excel
Se ejecuta así: python mapeo_dinamico.py <ruta_archivo> <formato> [<json_mapeos_customizados>]
"""
import sys
import json
import pandas as pd
from config import COLUMNAS_CRITICAS, NORMALIZED_MAPPING, COLUMNAS_SIIGO, COLUMNAS_DIAN
from utils import (
    obtener_columnas_excel, retornar_error, retornar_respuesta,
    normalizar_string, encontrar_columna_similar, cargar_mapeos_cliente
)

def mapear_columnas_dinamico(ruta_archivo, formato, mapeos_custom=None, cliente_id=None):
    """
    Mapea dinámicamente columnas del Excel a nombres estándar.

    Retorna DataFrame estandarizado con mapeo aplicado.
    Estructura respuesta: {
        "exito": True,
        "mapeo_aplicado": {...},
        "columnas_mapeadas": [...],
        "columnas_no_mapeadas": [...],
    }
    """
    try:
        # Cargar Excel
        df = pd.read_excel(ruta_archivo)
        columnas_originales = list(df.columns)

        if not columnas_originales:
            retornar_error("El archivo no tiene columnas")
            return

        # Cargar mapeos guardados del cliente si existen
        if cliente_id:
            mapeos_guardados = cargar_mapeos_cliente(cliente_id)
            if mapeos_guardados:
                mapeos_custom = mapeos_guardados.get("mapeos", mapeos_custom)

        # Crear mapeo normalizado
        mapeo_final = {}
        columnas_mapeadas = []
        columnas_no_mapeadas = []

        # Estructura de columnas esperadas según formato
        columnas_esperadas = COLUMNAS_SIIGO if formato == "SIIGO" else COLUMNAS_DIAN

        for col_original in columnas_originales:
            col_original_norm = normalizar_string(col_original)

            # 1. Buscar en mapeos customizados del usuario
            mapeo_encontrado = None
            if mapeos_custom and col_original in mapeos_custom:
                mapeo_encontrado = mapeos_custom[col_original]

            # 2. Buscar en mapeo normalizado directo
            if not mapeo_encontrado:
                if col_original_norm in NORMALIZED_MAPPING:
                    mapeo_encontrado = NORMALIZED_MAPPING[col_original_norm]

            # 3. Buscar coincidencia en columnas esperadas del formato
            if not mapeo_encontrado:
                for col_esperada in columnas_esperadas.keys():
                    col_esperada_norm = normalizar_string(col_esperada)
                    if col_original_norm == col_esperada_norm:
                        mapeo_encontrado = col_esperada
                        break

            # 4. Buscar similitud fuzzy
            if not mapeo_encontrado:
                mapeo_encontrado = encontrar_columna_similar(
                    col_original,
                    list(columnas_esperadas.keys()),
                    umbral_similitud=0.75
                )

            if mapeo_encontrado:
                mapeo_final[col_original] = mapeo_encontrado
                columnas_mapeadas.append({
                    "original": col_original,
                    "mapeada_a": mapeo_encontrado
                })
            else:
                columnas_no_mapeadas.append(col_original)

        # Aplicar mapeo al DataFrame
        df_mapeado = df.rename(columns=mapeo_final)

        # Asegurarse que todas las columnas críticas estén presentes
        criticas_presentes = all(
            col in df_mapeado.columns or normalizar_string(col) in [normalizar_string(c) for c in df_mapeado.columns]
            for col in COLUMNAS_CRITICAS
        )

        # Guardar Excel estandarizado en buffer
        from io import BytesIO
        output = BytesIO()
        with pd.ExcelWriter(output, engine='openpyxl') as writer:
            df_mapeado.to_excel(writer, sheet_name='Datos', index=False)
        output.seek(0)

        # Retornar respuesta
        retornar_respuesta(True, {
            "mapeo_aplicado": mapeo_final,
            "columnas_mapeadas": columnas_mapeadas,
            "columnas_no_mapeadas": columnas_no_mapeadas,
            "criticas_presentes": criticas_presentes,
            "archivo_estandarizado": output.getvalue().hex() if False else None,  # Si necesitas retornar el archivo
        })

    except Exception as e:
        retornar_error(str(e))

if __name__ == "__main__":
    if len(sys.argv) < 3:
        retornar_error("Uso: python mapeo_dinamico.py <ruta_archivo> <formato> [<json_mapeos>] [<cliente_id>]")

    ruta = sys.argv[1]
    formato = sys.argv[2]  # "DIAN" o "SIIGO"
    mapeos_custom = None
    cliente_id = None

    if len(sys.argv) > 3:
        try:
            mapeos_custom = json.loads(sys.argv[3])
        except:
            pass

    if len(sys.argv) > 4:
        cliente_id = sys.argv[4]

    mapear_columnas_dinamico(ruta, formato, mapeos_custom, cliente_id)
