import os
import json
import logging
import mysql.connector
import requests
import pandas as pd
import hashlib
from datetime import datetime

# --- CONFIGURAZIONE E LOGGING ---
def load_config(config_path):
    with open(config_path, encoding="utf-8") as f:
        return json.load(f)

def setup_logging(log_dir, log_file, debug=False):
    os.makedirs(log_dir, exist_ok=True)
    log_path = os.path.join(log_dir, log_file)
    logging.basicConfig(
        level=logging.DEBUG if debug else logging.INFO,
        format="%(asctime)s [%(levelname)s] %(message)s",
        handlers=[
            logging.FileHandler(log_path),
            logging.StreamHandler()
        ]
    )

# --- UTILS DATABASE ---
def get_mysql_connection(cfg):
    return mysql.connector.connect(
        host=cfg["MySQLHost"],
        port=cfg["MySQLPort"],
        user=cfg["MySQLUser"],
        password=cfg["MySQLPassword"],
        database=cfg["MySQLDatabase"]
    )

def calculate_hash(data_dict):
    filtered_dict = {k: v for k, v in data_dict.items() if v is not None}
    ordered_data = json.dumps(filtered_dict, sort_keys=True, default=str).encode('utf-8')
    return hashlib.md5(ordered_data).hexdigest()

# --- ESTRAZIONE E INVIO DATI ---
def extract_and_send_data(cfg):
    logging.info("--- Inizio estrazione e invio dati ---")
    input_dir = cfg["InputDirectory"]
    
    if not os.path.isdir(input_dir):
        logging.error(f"Directory di input non trovata: {input_dir}")
        return

    conn = get_mysql_connection(cfg)
    cursor = conn.cursor(dictionary=True)

    for mapping in cfg.get("SyncMappings", []):
        table = mapping['table']
        endpoint = cfg['ApiBaseUrl'] + mapping['endpoint']
        logging.info(f"Estrazione dati dalla tabella: {table}")

        # Estrai i dati dalla tabella
        cursor.execute(f"SELECT * FROM `{table}`")
        rows = cursor.fetchall()

        for row in rows:
            payload = {mapping['payload_fields'][k]: row[k] for k in mapping['payload_fields']}
            payload['hash_sync'] = calculate_hash(payload)

            # Invia i dati all'API
            response = send_to_api(endpoint, cfg['AdminToken'], payload)
            if response.status_code == 200:
                logging.info(f"Dati inviati con successo per {table}: {payload}")
            else:
                logging.error(f"Errore nell'invio dei dati per {table}: {response.text}")

    cursor.close()
    conn.close()
    logging.info("--- Fine estrazione e invio dati ---")

def send_to_api(endpoint, token, payload):
    headers = {
        'Authorization': f'Bearer {token}',
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    }
    try:
        response = requests.post(endpoint, headers=headers, json=payload)
        return response
    except requests.exceptions.RequestException as e:
        logging.error(f"Errore nella richiesta API: {e}")
        return None

# --- LOGICA PRINCIPALE ---
if __name__ == "__main__":
    base_dir = os.path.dirname(os.path.abspath(__file__))
    config_path = os.path.join(base_dir, "agent_config.json")

    try:
        cfg = load_config(config_path)
    except FileNotFoundError:
        logging.error(f"File di configurazione non trovato: {config_path}")
        exit(1)

    setup_logging(cfg["LogDirectory"], cfg.get("LogFile", "agent.log"), cfg.get("Debug", False))
    
    extract_and_send_data(cfg)