# -*- coding: utf-8 -*-
"""
Funciones auxiliares para manejo de Excel y data
"""
import pandas as pd
import json
import sys
import unicodedata
from io import BytesIO
from config import MAPEOS_FILE, CONFIG_DIR

def normalizar_string(s):
    """Normaliza un string: minúsculas, sin acentos, espacios normales."""
    if not isinstance(s, str):
        return ""
    s = s.strip().lower()
    # Eliminar acentos
    s = ''.join(
        c for c in unicodedata.normalize('NFD', s)
        if unicodedata.category(c) != 'Mn'
    )
    return s

def encontrar_columna_similar(nombre_buscado, columnas_disponibles, umbral_similitud=0.8):
    """
    Busca una columna similar en la lista disponible.
    Retorna el nombre más similar o None.
    """
    from difflib import SequenceMatcher

    buscado_norm = normalizar_string(nombre_buscado)
    coincidencias = []

    for col in columnas_disponibles:
        col_norm = normalizar_string(col)
        ratio = SequenceMatcher(None, buscado_norm, col_norm).ratio()
        if ratio > umbral_similitud:
            coincidencias.append((col, ratio))

    if coincidencias:
        coincidencias.sort(key=lambda x: x[1], reverse=True)
        return coincidencias[0][0]
    return None

def leer_excel_primeras_filas(ruta_archivo, num_filas=5):
    """Lee las primeras filas de un Excel y retorna DataFrame."""
    try:
        df = pd.read_excel(ruta_archivo, nrows=num_filas)
        return df
    except Exception as e:
        raise Exception(f"Error leyendo Excel: {str(e)}")

def obtener_columnas_excel(ruta_archivo):
    """Obtiene lista de columnas de un Excel."""
    try:
        df = pd.read_excel(ruta_archivo, nrows=0)
        return list(df.columns)
    except Exception as e:
        raise Exception(f"Error obteniendo columnas: {str(e)}")

def cargar_mapeos_cliente(cliente_id):
    """Carga mapeos guardados para un cliente específico."""
    try:
        if not os.path.isfile(MAPEOS_FILE):
            return None
        with open(MAPEOS_FILE, 'r', encoding='utf-8') as f:
            mapeos = json.load(f)
            return mapeos.get(str(cliente_id), None)
    except Exception as e:
        return None

def guardar_mapeos_cliente(cliente_id, formato, mapeos):
    """Guarda mapeos de un cliente para reutilizar."""
    try:
        # Crear directorio si no existe
        os.makedirs(CONFIG_DIR, exist_ok=True)

        # Cargar mapeos existentes
        if os.path.isfile(MAPEOS_FILE):
            with open(MAPEOS_FILE, 'r', encoding='utf-8') as f:
                datos = json.load(f)
        else:
            datos = {}

        # Agregar/actualizar cliente
        datos[str(cliente_id)] = {
            "formato": formato,
            "mapeos": mapeos,
            "timestamp": pd.Timestamp.now().isoformat()
        }

        # Guardar
        with open(MAPEOS_FILE, 'w', encoding='utf-8') as f:
            json.dump(datos, f, ensure_ascii=False, indent=2)

        return True
    except Exception as e:
        print(f"Error guardando mapeos: {e}", file=sys.stderr)
        return False

def dataframe_a_json(df):
    """Convierte DataFrame a JSON (para retornar al PHP)."""
    return json.loads(df.to_json(orient='records', force_ascii=False))

def dict_a_json(d):
    """Convierte diccionario a JSON string."""
    return json.dumps(d, ensure_ascii=False, indent=2)

def excel_a_bytes(df, nombre_hoja="DFFC"):
    """Convierte DataFrame a bytes Excel (para descargar)."""
    try:
        output = BytesIO()
        with pd.ExcelWriter(output, engine='openpyxl') as writer:
            df.to_excel(writer, sheet_name=nombre_hoja, index=False)
        output.seek(0)
        return output.getvalue()
    except Exception as e:
        raise Exception(f"Error convertiendo a Excel: {str(e)}")

def retornar_error(mensaje):
    """Retorna error en formato JSON estándar."""
    print(json.dumps({
        "exito": False,
        "error": mensaje,
    }, ensure_ascii=False), file=sys.stdout)
    sys.exit(1)

def retornar_respuesta(exito, datos=None, error=None):
    """Retorna respuesta en formato JSON estándar."""
    respuesta = {
        "exito": exito,
    }
    if datos:
        respuesta.update(datos)
    if error:
        respuesta["error"] = error

    print(json.dumps(respuesta, ensure_ascii=False, default=str), file=sys.stdout)

import os
