import os
import pymysql
import logging
from datetime import datetime, timedelta, date
from dotenv import load_dotenv

# === IMPORTS ===
from interaccion_planok import crear_seguimiento, obtener_rut_vendedor_por_proyecto
from crear_contacto import create_contact 

# === CONFIGURACIÓN ===
logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s] %(message)s')
load_dotenv()

DB_CONFIG = {
    'host': os.getenv('DB_HOST'),
    'user': os.getenv('DB_USER'),
    'password': os.getenv('DB_PASSWORD'),
    'database': os.getenv('DB_NAME'),
    'cursorclass': pymysql.cursors.DictCursor
}

TIPO_CONTACTOPOK = int(os.getenv("CONI_GESTIONADO", "0")) 
PROYECTOS_ACTIVO_STR = os.getenv("PROYECTOS_ACTIVO", "")
PROYECTOS_ACTIVO = set()
if PROYECTOS_ACTIVO_STR.strip():
    try:
        PROYECTOS_ACTIVO = {int(x) for x in PROYECTOS_ACTIVO_STR.split(",")}
    except ValueError:
        pass

# ───────────────────────────────────────────────
# Helpers
# ───────────────────────────────────────────────

def _to_dt(fecha):
    """Convierte string de DB a datetime."""
    if isinstance(fecha, datetime): return fecha
    if isinstance(fecha, date): return datetime.combine(fecha, datetime.min.time())
    if not fecha: return None
    
    # Intentamos parsear formatos comunes
    s = str(fecha).strip()
    for fmt in ("%Y-%m-%d %H:%M:%S", "%Y-%m-%d", "%Y-%m-%dT%H:%M:%S"):
        try:
            return datetime.strptime(s, fmt)
        except ValueError:
            pass
    return None

def fetch_pending_leads():
    # Traemos 'uno' (primer intento) y 'dos' (segundo intento pendiente)
    sql = """
        SELECT *
        FROM Lead_entrantes
        WHERE enviado_cf_2 IN ('uno','dos')
          AND (Enviado_25h IS NULL OR Enviado_25h = 0)
    """
    conn = pymysql.connect(**DB_CONFIG)
    try:
        with conn.cursor() as cur:
            cur.execute(sql)
            return cur.fetchall()
    finally:
        conn.close()

def update_enviado_cf2(id_centralizador, nuevo_valor, respuesta=None):
    conn = pymysql.connect(**DB_CONFIG)
    try:
        with conn.cursor() as cur:
            sql = "UPDATE Lead_entrantes SET enviado_cf_2 = %s, respuesta_cf = %s WHERE ID_centralizador = %s"
            cur.execute(sql, (nuevo_valor, respuesta, id_centralizador))
        conn.commit()
    finally:
        conn.close()

def update_enviado_planok_flag(id_cliente):
    """Marca el flag Enviado_25h para no volver a procesar el cierre."""
    conn = pymysql.connect(**DB_CONFIG)
    try:
        with conn.cursor() as cur:
            # Usamos ID_cliente con cuidado, o idealmente ID_centralizador si pudieras cambiar la estructura
            # Asumimos que ID_cliente es seguro para este flujo
            sql = "UPDATE Lead_entrantes SET Enviado_25h = 1 WHERE ID_cliente = %s"
            cur.execute(sql, (id_cliente,))
        conn.commit()
    finally:
        conn.close()

# ───────────────────────────────────────────────
# FLUJO PRINCIPAL (Orquestador)
# ───────────────────────────────────────────────
def process_leads():
    leads = fetch_pending_leads()
    if not leads:
        logging.info("Sin leads pendientes (uno/dos).")
        return

    # Usamos datetime.now() asumiendo que el servidor y la DB están en la misma zona horaria
    # Si la DB está en UTC y el server en Chile, habría que ajustar.
    now = datetime.now() 

    for lead in leads:
        id_centralizador = lead.get("ID_centralizador")
        status = (lead.get("enviado_cf_2") or "").lower()
        
        # 1. Validación de Proyecto
        try:
            proyecto_id = int(lead.get("ID_proyecto") or 0)
        except:
            proyecto_id = 0
            
        if proyecto_id not in PROYECTOS_ACTIVO:
            update_enviado_cf2(id_centralizador, 'ignorado_proyecto', 'Proyecto inactivo')
            continue

        # 2. Obtener Fechas
        fecha_ingreso_dt = _to_dt(lead.get("Fecha_ingreso")) # Para fase 1
        base_dt_now      = _to_dt(lead.get("Now"))           # Para fase 2 (Precisión)

        try:
            # ==========================================
            # FASE 1: PRIMER CONTACTO (0 - 24 horas)
            # ==========================================
            if status == "uno":
                
                if lead.get('enviado_cf') == 1:
                    logging.info(f"Lead {id_centralizador}: Ya fue enviado antes (enviado_cf=1). Corrigiendo estado a 'dos'.")
                    update_enviado_cf2(id_centralizador, "dos", "Corregido autom. por script")
                    continue                
                
                if not fecha_ingreso_dt:
                    logging.warning(f"Lead {id_centralizador}: Sin Fecha_ingreso.")
                    continue

                # Calculamos antigüedad
                horas_pasadas = (now - fecha_ingreso_dt).total_seconds() / 3600

                if horas_pasadas <= 24:
                    logging.info(f"Lead {id_centralizador}: Intentando Primer Envío...")
                    
                    # Llamamos a create_contact. Él se encarga de validar si ya habló (UserInteraction)
                    resp = create_contact(lead)
                    
                    if resp.get('status') == 'skipped':
                        # CASO CLAVE: Si se saltó porque "Ya tiene conversación" o "Ya enviado",
                        # NO lo pasamos a 'dos'. Lo cerramos aquí.
                        msg = resp.get('message', '')
                        if "conversación activa" in msg or "Ya enviado" in msg:
                            logging.info(f"Lead {id_centralizador}: Ya gestionado/conversando. Fin del flujo.")
                            update_enviado_cf2(id_centralizador, "final_conversando", str(resp))
                        else:
                            # Otros skips (ej. límite diario) se mantienen en 'uno' para intentar mañana
                            logging.info(f"Lead {id_centralizador}: Skipped ({msg}). Se mantiene en 'uno'.")
                    
                    elif resp.get('error'):
                        logging.error(f"Lead {id_centralizador}: Error Chatfuel: {resp}")
                    
                    else:
                        # ÉXITO: Pasamos a etapa 'dos' para esperar las 24h
                        update_enviado_cf2(id_centralizador, "dos", str(resp))
                        logging.info(f"Lead {id_centralizador}: Éxito Fase 1 -> Pasa a 'dos'")
                
                else:
                    # Se pasó el tiempo del primer envío (> 24h)
                    logging.info(f"Lead {id_centralizador}: Expiró tiempo Fase 1 (>24h).")
                    update_enviado_cf2(id_centralizador, "expirado_fase1", "Fuera de ventana inicial")


            # ==========================================
            # FASE 2: SEGUNDO CONTACTO (24 - 26 horas post-lead)
            # ==========================================
            elif status == "dos":
                if not base_dt_now:
                    logging.warning(f"Lead {id_centralizador}: Sin campo 'Now' para cálculo preciso.")
                    update_enviado_cf2(id_centralizador, "error_data", "Falta campo Now")
                    continue

                # Ventana estricta basada en el campo 'Now' de la DB
                ventana_inicio = base_dt_now + timedelta(hours=24)
                ventana_fin    = base_dt_now + timedelta(hours=26) # Ventana de 2 horas para actuar

                if now < ventana_inicio:
                    # Aún es muy temprano (ej. han pasado 20h). Esperamos.
                    continue
                
                elif ventana_inicio <= now <= ventana_fin:
                    logging.info(f"Lead {id_centralizador}: DENTRO DE VENTANA 24H (Fase 2). Ejecutando...")
                    
                    # 1. Reintento Chatfuel (Modo "Dos")
                    lead_cf = dict(lead)
                    lead_cf["Activar_Contacto"] = "Dos" # Forzamos la lógica de segundo envío
                    
                    resp_cf = create_contact(lead_cf)
                    
                    # Si create_contact responde "stopped" es porque el cliente respondió en el intertanto
                    if resp_cf.get('status') == 'stopped':
                        logging.info(f"Lead {id_centralizador}: Cliente respondió antes del 2do envío. Cancelado.")
                        update_enviado_cf2(id_centralizador, "final_respondio", str(resp_cf))
                        continue

                    # 2. Cierre en PlanOK
                    # Se envía la notificación de "Gestión realizada / No contestó"
                    rut_vend = obtener_rut_vendedor_por_proyecto(proyecto_id)
                    seg_id = crear_seguimiento(
                        id_cliente=lead.get("ID_cliente"),
                        id_proyecto=proyecto_id,
                        id_medio=int(lead.get('ID_medio_llegada') or 0),
                        id_tipo_contacto=TIPO_CONTACTOPOK,
                        id_expectativa=1, # Baja expectativa porque no contestó
                        comentario="Gestión ConiLead: Se enviaron recordatorios, cliente no contestó (Ciclo Terminado).",
                        fecha_recontacto_str=now.strftime('%Y-%m-%dT%H:%M:%SZ'),
                        mantener_ejecutivo=False,
                        rutvendedor=rut_vend
                    )
                    
                    # 3. Finalizar
                    update_enviado_cf2(id_centralizador, "final", str(resp_cf))
                    if seg_id:
                        update_enviado_planok_flag(lead.get("ID_cliente"))
                        logging.info(f"Lead {id_centralizador}: Ciclo cerrado exitosamente.")

                else:
                    # now > ventana_fin
                    # Se nos pasó la hora (el script no corrió o falló en la ventana)
                    logging.info(f"Lead {id_centralizador}: Ventana Fase 2 expirada (>26h).")
                    update_enviado_cf2(id_centralizador, "expirado_fase2", "Fuera de ventana recontacto")

        except Exception as e:
            logging.error(f"Error procesando lead {id_centralizador}: {e}", exc_info=True)

if __name__ == "__main__":
    process_leads()