import os
import sys
import subprocess
import configparser

def install_dependencies():
    """Autoinstala openpyxl y pymysql si no están presentes."""
    for package in ["pymysql", "openpyxl"]:
        try:
            __import__(package)
        except ImportError:
            print(f"Instalando dependencia faltante: {package}...")
            subprocess.check_call([sys.executable, "-m", "pip", "install", package])

# Instalar dependencias necesarias
install_dependencies()

import pymysql
import openpyxl

def decrypt_str(val):
    """Descifra valores del archivo ini usando el cifrado XOR estático de GESTION."""
    if not val or not val.startswith("ENC:"):
        return val
    
    cipher_text = val[4:]
    decrypted = ""
    key = 0xA5C3
    
    # Procesar bloques de 4 caracteres hex
    for i in range(0, len(cipher_text), 4):
        hex_part = cipher_text[i:i+4]
        try:
            val_int = int(hex_part, 16)
            decrypted += chr(val_int ^ key)
        except Exception:
            pass
    return decrypted

def load_db_config():
    """Busca en cascada y lee el archivo db_config.ini descifrando sus credenciales."""
    paths = [
        r"C:\GESTIGEST\db_config.ini",
        r"c:\fuentes\proyectos delphi\RAUL_ASENCIO\GESTION\db_config.ini",
        os.path.join(os.getcwd(), "db_config.ini")
    ]
    
    config = {
        "host": "85.215.144.168",
        "port": 3306,
        "database": "pastelerias",
        "user": "asesoft",
        "password": "Pantera1"
    }
    
    ini_found = None
    for p in paths:
        if os.path.exists(p):
            ini_found = p
            break
            
    if ini_found:
        print(f"Leyendo configuración desde: {ini_found}")
        parser = configparser.ConfigParser(strict=False)
        try:
            parser.read(ini_found, encoding="utf-8")
            if "Database" in parser.sections():
                db_sec = parser["Database"]
                if "Server" in db_sec:
                    config["host"] = decrypt_str(db_sec["Server"])
                if "Port" in db_sec:
                    config["port"] = int(decrypt_str(db_sec["Port"]))
                if "Database" in db_sec:
                    config["database"] = decrypt_str(db_sec["Database"])
                if "User_Name" in db_sec:
                    config["user"] = decrypt_str(db_sec["User_Name"])
                if "Password" in db_sec:
                    config["password"] = decrypt_str(db_sec["Password"])
        except Exception as e:
            print(f"Error parseando archivo ini, usando valores por defecto: {e}")
    else:
        print("No se encontró db_config.ini. Usando parámetros de conexión por defecto.")
        
    return config

def main():
    excel_path = r"c:\fuentes\proyectos delphi\RAUL_ASENCIO\GESTION\CODIGOS DE BARRAS COMPLETO.xlsx"
    print(f"Iniciando importación desde: {excel_path}")
    if not os.path.exists(excel_path):
        print(f"Error: El archivo Excel no existe en {excel_path}")
        return
        
    # Cargar configuración de base de datos
    db_config = load_db_config()
    
    # Leer Excel
    print("Leyendo archivo Excel...")
    wb = openpyxl.load_workbook(excel_path, data_only=True)
    sheet = wb.active
    
    rows = list(sheet.iter_rows(values_only=True))
    if len(rows) < 2:
        print("El archivo Excel está vacío o no contiene filas de datos.")
        return
        
    # Las cabeceras
    headers = rows[0]
    data_rows = rows[1:]
    print(f"Columnas detectadas en Excel: {headers[:18]}")
    print(f"Total de registros a importar: {len(data_rows)}")
    
    # Conexión a Base de Datos
    print(f"Conectando a base de datos '{db_config['database']}' en '{db_config['host']}'...")
    conn = pymysql.connect(
        host=db_config["host"],
        port=db_config["port"],
        user=db_config["user"],
        password=db_config["password"],
        database=db_config["database"],
        charset="utf8mb4"
    )
    
    try:
        with conn.cursor() as cursor:
            # Limpiar tabla antes de la importación
            print("Limpiando tabla 'ge_codigos_barras_completo'...")
            cursor.execute("TRUNCATE TABLE ge_codigos_barras_completo")
            
            sql = """
                INSERT INTO ge_codigos_barras_completo (
                    descripcion_producto, ean_13,
                    ean_14_caja_1, unidades_caja_1,
                    ean_14_caja_2, unidades_caja_2,
                    ean_14_caja_4, unidades_caja_4,
                    ean_14_caja_6, unidades_caja_6,
                    ean_14_caja_8, unidades_caja_8,
                    ean_14_caja_12, unidades_caja_12,
                    ean_14_caja_16, unidades_caja_16,
                    ean_14_caja_28, unidades_caja_28
                ) VALUES (
                    %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s
                )
            """
            
            success_count = 0
            for idx, r in enumerate(data_rows, 1):
                # Rellenar con None si la fila tiene menos columnas de las esperadas
                row_vals = list(r)
                while len(row_vals) < 18:
                    row_vals.append(None)
                
                # Extraer y sanitizar valores (limpiar espacios en blanco de strings)
                def clean_val(v, is_int=False):
                    if v is None:
                        return None
                    v_str = str(v).strip()
                    # Eliminar caracteres especiales invisibles como \xa0 (non-breaking space)
                    v_str = v_str.replace('\xa0', '').replace('\u00a0', '')
                    if not v_str:
                        return None
                    if is_int:
                        try:
                            # Puede venir como decimal en float
                            return int(float(v_str))
                        except Exception:
                            return None
                    return v_str
                
                desc = clean_val(row_vals[0])
                if not desc:
                    # Saltar filas sin descripción
                    continue
                    
                ean13 = clean_val(row_vals[1])
                
                ean14_1  = clean_val(row_vals[2])
                units_1  = clean_val(row_vals[3], is_int=True)
                
                ean14_2  = clean_val(row_vals[4])
                units_2  = clean_val(row_vals[5], is_int=True)
                
                ean14_4  = clean_val(row_vals[6])
                units_4  = clean_val(row_vals[7], is_int=True)
                
                ean14_6  = clean_val(row_vals[8])
                units_6  = clean_val(row_vals[9], is_int=True)
                
                ean14_8  = clean_val(row_vals[10])
                units_8  = clean_val(row_vals[11], is_int=True)
                
                ean14_12 = clean_val(row_vals[12])
                units_12 = clean_val(row_vals[13], is_int=True)
                
                ean14_16 = clean_val(row_vals[14])
                units_16 = clean_val(row_vals[15], is_int=True)
                
                ean14_28 = clean_val(row_vals[16])
                units_28 = clean_val(row_vals[17], is_int=True)
                
                params = (
                    desc, ean13,
                    ean14_1, units_1,
                    ean14_2, units_2,
                    ean14_4, units_4,
                    ean14_6, units_6,
                    ean14_8, units_8,
                    ean14_12, units_12,
                    ean14_16, units_16,
                    ean14_28, units_28
                )
                
                try:
                    cursor.execute(sql, params)
                    success_count += 1
                except Exception as e:
                    print(f"Error insertando fila {idx} ({desc}): {e}")
            
            conn.commit()
            print(f"✅ Importación completada con éxito. {success_count} registros importados en 'ge_codigos_barras_completo'.")
            
    finally:
        conn.close()

if __name__ == "__main__":
    try:
        main()
    except Exception as e:
        print(f"Error general en la ejecución: {e}")
