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 
        Number, StartDatePick, StartDateCC, EndDate, EndDateCC, EndDatePick,
        FirstOrderCredit, FourthOrderCredit, MinOrder, MinOrderShipping, SecondOrderCredit,
        ShippingAmount, StartDate, ThirdOrderCredit, Status, FifthOrderCredit, Sequence,
        EstimatedOrders, CommercialOrders, NoticeOrderValue
        FROM Campaign
        """
        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} 
            (number, start_date_pick, start_date_cc, end_date, end_date_cc, end_date_pick,
            first_order_credit, fourth_order_credit, min_order, min_order_shipping, second_order_credit,
            shipping_amount, start_date, third_order_credit, status, fifth_order_credit, sequence,
            estimated_orders, commercial_orders, notice_order_value)
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
            """
            
            # Convertir NaN a None para que MySQL los interprete como NULL
            df = df.replace({pd.NA: None, 'NaN': None, float('nan'): None})

            # Convertir DataFrame a lista de listas
            valores = df.values.tolist()
            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(300000)  # 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, trunca la tabla de destino 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:
        # Nombre de la tabla de destino en MySQL
        tabla_destino = 'app_campaign'

        # Truncar la tabla de destino antes de la inserción
        truncar_tabla_destino(tabla_destino)

        # Insertar los datos en la base de datos destino (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()

