import pyodbc
import pandas as pd
import mysql.connector
from datetime import datetime
import logging
import time

# Configuración para el logging
log_path = r'C:\Users\sysadm\Desktop\connection_log.txt'
logging.basicConfig(filename=log_path, level=logging.ERROR)

# Configuración de conexión para la base de datos origen (SQL Server)
configuracion_origen = {
    'server': 'gigotqa.database.windows.net',
    'database': 'gigotqa',
    'username': 'gigotqa',
    'password': 'ViRrEy1485!',
    'driver': '{ODBC Driver 17 for SQL Server}'
}

# Configuración de conexión para la base de datos destino (MySQL en XAMPP)
configuracion_destino = {
    'host': 'localhost',
    'user': 'root',
    'password': '',
    'database': 'giapy',
    'port': '3306'
}

def obtener_datos_origen():
    """Conectar a SQL Server y obtener los datos de la tabla origen."""
    try:
        print("Conectando a la base de datos de origen (SQL Server)...")
        conexion_origen = pyodbc.connect(
            f'DRIVER={configuracion_origen["driver"]};SERVER={configuracion_origen["server"]};PORT=1433;'
            f'DATABASE={configuracion_origen["database"]};UID={configuracion_origen["username"]};'
            f'PWD={configuracion_origen["password"]};Encrypt=yes;TrustServerCertificate=yes'
        )
        print("Conexión establecida a la base de datos de origen.")
        
        cursor = conexion_origen.cursor()
        
        # Ejecutar la consulta SQL para obtener los campos especificados
        query = """
        SELECT 
            LastName, FirstName, Email, EmailConfirmation, PhoneNumber, HomePhone, 
            Nationality, Address_Region, Address_Locality, Address_Province, 
            Address_PostalCode, Address_Neighborhood, Address_Street, Address_Number, 
            Address_Floor, Address_Apartment, Address_Complement, Address_Latitude, 
            Address_Longitude, UtmSource, UtmCampaign, UtmContent, UtmMedium, 
            UtmKeyword, Status, CreationDate, ValidationCode, AuthorizePhonesDisclosure, 
            WantToReceiveNewsletter, DocumentType, DocumentNumber, GeoLocatedZoneId, 
            Observations
        FROM IntencionCompra
        """
        print("Ejecutando consulta en la base de datos de origen...")
        cursor.execute(query)
        
        # Obtener los resultados
        filas = cursor.fetchall()
        columnas = [column[0] for column in cursor.description]
        
        # Convertir los datos en un DataFrame de pandas
        df = pd.DataFrame.from_records(filas, columns=columnas)
        print(f"Se obtuvieron {len(df)} filas de la base de datos de origen.")
        
        cursor.close()
        conexion_origen.close()
        
        return df
    
    except pyodbc.Error as e:
        print(f"Error al conectar o ejecutar consulta en la base de datos de origen: {e}")
        logging.error(f"{datetime.now()}: Error en la base de datos de origen: {e}")
        return None

def truncar_tabla_destino(tabla_destino):
    """Truncar la tabla de destino en MySQL antes de insertar nuevos datos."""
    try:
        print(f"Conectando a la base de datos de destino (MySQL) para truncar la tabla {tabla_destino}...")
        conexion_destino = mysql.connector.connect(
            host=configuracion_destino['host'],
            user=configuracion_destino['user'],
            password=configuracion_destino['password'],
            database=configuracion_destino['database'],
            port=configuracion_destino['port'],
            charset='utf8mb4',
            collation='utf8mb4_general_ci'
        )
        
        cursor = conexion_destino.cursor()
        cursor.execute(f"TRUNCATE TABLE {tabla_destino}")
        conexion_destino.commit()
        print(f"Tabla {tabla_destino} truncada exitosamente.")
        
        cursor.close()
        conexion_destino.close()

        # Pausa después de truncar la tabla
        #time.sleep(5)
    
    except mysql.connector.Error as e:
        print(f"Error al truncar la tabla de destino: {e}")
        logging.error(f"{datetime.now()}: Error al truncar la tabla de destino: {e}")

def insertar_datos_destino(df, tabla_destino, batch_size=1000, max_retries=3):
    """Insertar los datos obtenidos en la tabla de destino en MySQL por lotes."""
    for intento in range(max_retries):
        try:
            print(f"Conectando a la base de datos de destino (MySQL) para insertar en la tabla {tabla_destino}...")
            conexion_destino = mysql.connector.connect(
                host=configuracion_destino['host'],
                user=configuracion_destino['user'],
                password=configuracion_destino['password'],
                database=configuracion_destino['database'],
                port=configuracion_destino['port'],
                charset='utf8mb4',
                collation='utf8mb4_general_ci'
            )
            
            cursor = conexion_destino.cursor()

            # Ajustar el INSERT para los campos especificados
            insert_query = f"""
            INSERT INTO {tabla_destino} 
            (LastName, FirstName, Email, EmailConfirmation, PhoneNumber, HomePhone, 
            Nationality, Address_Region, Address_Locality, Address_Province, 
            Address_PostalCode, Address_Neighborhood, Address_Street, Address_Number, 
            Address_Floor, Address_Apartment, Address_Complement, Address_Latitude, 
            Address_Longitude, UtmSource, UtmCampaign, UtmContent, UtmMedium, 
            UtmKeyword, Status, CreationDate, ValidationCode, AuthorizePhonesDisclosure, 
            WantToReceiveNewsletter, DocumentType, DocumentNumber, GeoLocatedZoneId, 
            Observations)
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 
                    %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
            """
            
            # Reemplazar valores NaN/None con None para que MySQL los interprete como NULL
            df = df.where(pd.notnull(df), None)

            valores = df.values.tolist()  # Convertir DataFrame a lista de listas
            total_filas = len(valores)
            print(f"Insertando {total_filas} registros en lotes de {batch_size}...")

            for i in range(0, total_filas, batch_size):
                lote = valores[i:i + batch_size]
                try:
                    cursor.executemany(insert_query, lote)
                    conexion_destino.commit()
                    print(f"Lote {i // batch_size + 1}: Insertados {len(lote)} registros.")
                except mysql.connector.Error as e:
                    print(f"Error en lote {i // batch_size + 1}: {e}")
                    logging.error(f"{datetime.now()}: Error en lote {i // batch_size + 1}: {e}")
            
            cursor.close()
            conexion_destino.close()
            break  # Salir del bucle si todo fue bien

        except mysql.connector.Error as e:
            print(f"Error de conexión al insertar datos en el intento {intento + 1}: {e}")
            logging.error(f"{datetime.now()}: Error de conexión en intento {intento + 1}: {e}")
            time.sleep(5)  # Esperar antes de reintentar

        if intento == max_retries - 1:
            print("Error persistente, no se pudo completar la operación.")
            logging.error(f"{datetime.now()}: Error persistente tras {max_retries} intentos.")

def ejecutar_pasaje():
    """Función principal que obtiene los datos de origen y los inserta en destino."""
    # Obtener los datos desde la base de datos origen (SQL Server)
    datos_origen = obtener_datos_origen()
    
    if datos_origen is not None and not datos_origen.empty:
        # Insertar los datos en la base de datos destino (MySQL)
        tabla_destino = 'app_intencioncompra'  # Nombre de la tabla de destino en MySQL
        insertar_datos_destino(datos_origen, tabla_destino)
    else:
        print("No se encontraron datos para transferir.")

# Ejecutar el proceso de pasaje de datos
ejecutar_pasaje()
