import os
import requests
import re
from dotenv import load_dotenv
import pymysql
import json
from datetime import datetime, date, time, timedelta
from interaccion_planok import patch_lead_gci, crear_seguimiento, obtener_rut_vendedor_por_proyecto

load_dotenv()

# Configuración Base de Datos
DB_HOST = os.getenv('DB_HOST')
DB_USER = os.getenv('DB_USER')
DB_PASSWORD = os.getenv('DB_PASSWORD')
DB_NAME = os.getenv('DB_NAME')
DIASDESCTIVADO   = int(os.getenv("DIASDESCTIVADO", "2"))
# Configuración Chatfuel y PlanOK
CHATFUEL_TOKEN = os.getenv('CHATFUEL_TOKEN')
CHATFUEL_BOT_ID = os.getenv('CHATFUEL_BOT_ID')
CHATFUEL_URL = f"https://api.chatfuel.com/whatsapp/bots/{CHATFUEL_BOT_ID}/contacts?chatfuel_token={CHATFUEL_TOKEN}"

GCI_SEGUIMIENTO_COMENTARIO   = "Cliente en gestión de Conilead"
GCI_ID_TIPO_CONTACTO_DEFAULT = int(os.getenv("CONI_ENPROCESO", "0"))
GCI_ID_EXPECTATIVA_DEFAULT   = int(os.getenv("GCI_ID_EXPECTATIVA_DEFAULT", "3"))

PROYECTOS_ACTIVO_STR = os.getenv("PROYECTOS_ACTIVO", "")
PROYECTOS_ACTIVO = set()
if PROYECTOS_ACTIVO_STR.strip():
    try:
        PROYECTOS_ACTIVO = {int(x.strip()) for x in PROYECTOS_ACTIVO_STR.split(",")}
    except ValueError:
        pass

DB_CONFIG = {
    'host': DB_HOST,
    'user': DB_USER,
    'password': DB_PASSWORD,
    'database': DB_NAME,
    'cursorclass': pymysql.cursors.DictCursor
}

# ─────────────────────────────────────────────────────────────
# Utilidades
# ─────────────────────────────────────────────────────────────
def _solo_digitos(s: str) -> str:
    return re.sub(r'\D', '', s or '')

def clean_phone_number(phone_number):
    d = _solo_digitos(phone_number)
    if d.startswith('0056'): d = d[4:]
    elif d.startswith('056'): d = d[3:]
    if not d.startswith('56'): d = '56' + d
    return d

def format_date(value):
    if isinstance(value, datetime): return value.strftime('%Y-%m-%d %H:%M:%S')
    elif isinstance(value, date): return value.strftime('%Y-%m-%d')
    elif isinstance(value, time): return value.strftime('%H:%M:%S')
    return str(value)

def _parse_fecha_ymd(s: str):
    if not s: return None
    try:
        return datetime.strptime(str(s)[:10], '%Y-%m-%d').date()
    except Exception:
        return None

def _parse_datetime_db(s):
    """Parsea el campo 'Now' que viene de la DB."""
    if isinstance(s, datetime): return s
    if not s: return None
    try:
        # Intenta formato completo
        return datetime.strptime(str(s), '%Y-%m-%d %H:%M:%S')
    except:
        return None

# ─────────────────────────────────────────────────────────────
# DB Helpers
# ─────────────────────────────────────────────────────────────

def ensure_limit_table():
    sql = """
    CREATE TABLE IF NOT EXISTS chatfuel_envios (
      telefono VARCHAR(30) NOT NULL,
      fecha DATE NOT NULL,
      first_id_centralizador VARCHAR(50) NULL,
      count INT NOT NULL DEFAULT 1,
      last_sent_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
      PRIMARY KEY (telefono, fecha)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    """
    conn = pymysql.connect(**DB_CONFIG)
    with conn:
        with conn.cursor() as cur:
            cur.execute(sql)
        conn.commit()

# --- LA FUNCIÓN CLAVE ---
def verificar_respuesta_post_lead(telefono, fecha_corte_lead):
    """
    Revisa si el usuario habló DESPUÉS de que llegó el lead.
    - telefono: Número normalizado (569...)
    - fecha_corte_lead: El campo 'Now' de Lead_entrantes (datetime)
    """
    if not fecha_corte_lead:
        # Si no hay fecha de referencia, por seguridad asumimos que NO ha respondido para intentar contactar
        return False
        
    conn = pymysql.connect(**DB_CONFIG)
    try:
        with conn.cursor() as cur:
            # Buscamos interacción donde la fecha sea MAYOR a la fecha de llegada del lead
            sql = """
                SELECT 1 FROM UserInteraction 
                WHERE whatsapp_phone = %s 
                  AND last_seen > %s 
                LIMIT 1
            """
            cur.execute(sql, (telefono, fecha_corte_lead))
            return cur.fetchone() is not None
    except Exception as e:
        print(f"⚠️ Error verificando respuesta post-lead: {e}")
        return False
    finally:
        conn.close()

def existe_envio_misma_fecha(telefono, fecha_ref):
    if not telefono or not fecha_ref: return False
    conn = pymysql.connect(**DB_CONFIG)
    try:
        with conn.cursor() as cur:
            # Usamos el teléfono limpio como llave (solo dígitos)
            t_key = _solo_digitos(telefono)
            # Quitamos el 56 inicial para normalizar la llave si es necesario, 
            # pero tu función clean_phone_number agrega 56. 
            # Para la tabla de limite diario, usaremos el numero limpio sin 56 para evitar duplicados 09/9/569
            if t_key.startswith("56"): t_key = t_key[2:]
            
            cur.execute("SELECT 1 FROM chatfuel_envios WHERE telefono=%s AND fecha=%s LIMIT 1", (t_key, fecha_ref))
            return cur.fetchone() is not None
    finally:
        conn.close()

def registrar_envio_misma_fecha(telefono, id_centralizador, fecha_ref):
    if not telefono or not fecha_ref: return
    t_key = _solo_digitos(telefono)
    if t_key.startswith("56"): t_key = t_key[2:]

    conn = pymysql.connect(**DB_CONFIG)
    try:
        with conn.cursor() as cur:
            cur.execute("""
                INSERT INTO chatfuel_envios (telefono, fecha, first_id_centralizador, count, last_sent_at)
                VALUES (%s, %s, %s, 1, NOW())
                ON DUPLICATE KEY UPDATE count = count + 1, last_sent_at = NOW()
            """, (t_key, fecha_ref, id_centralizador))
        conn.commit()
    finally:
        conn.close()

def update_sent_status(id_centralizador, respuesta_cf, enviado_cf):
    conn = pymysql.connect(**DB_CONFIG)
    try:
        with conn.cursor() as cur:
            # CORRECCIÓN: Si enviado_cf es 1 (éxito), avanzamos enviado_cf_2 a 'dos' automáticamente
            sql = """
                UPDATE Lead_entrantes 
                SET enviado_cf = %s, 
                    respuesta_cf = COALESCE(respuesta_cf, %s),
                    enviado_cf_2 = CASE WHEN %s = 1 THEN 'dos' ELSE enviado_cf_2 END
                WHERE ID_centralizador = %s
            """
            cur.execute(sql, (enviado_cf, respuesta_cf, enviado_cf, id_centralizador))
        conn.commit()
    finally:
        conn.close()

def update_planok_response_db(id_centralizador, respuesta):
    conn = pymysql.connect(**DB_CONFIG)
    try:
        with conn.cursor() as cur:
            sql = "UPDATE Lead_entrantes SET planok_respuesta = %s WHERE ID_centralizador = %s"
            cur.execute(sql, (str(respuesta), id_centralizador))
        conn.commit()
    except:
        pass
    finally:
        conn.close()

def should_send_to_chatfuel(id_centralizador):
    conn = pymysql.connect(**DB_CONFIG)
    try:
        with conn.cursor() as cur:
            cur.execute("SELECT enviado_cf, respuesta_cf FROM Lead_entrantes WHERE ID_centralizador = %s", (id_centralizador,))
            res = cur.fetchone()
            if res and res['enviado_cf'] == 0:
                if res['respuesta_cf'] and "Invalid phone number" in str(res['respuesta_cf']):
                    return False
                return True
            return False
    finally:
        conn.close()

def fetch_data_from_database():
    conn = pymysql.connect(**DB_CONFIG)
    try:
        with conn.cursor() as cur:
            # Traemos solo los pendientes de primer envío
            sql = "SELECT * FROM Lead_entrantes WHERE enviado_cf = 0 AND respuesta_cf IS NULL"
            cur.execute(sql)
            return cur.fetchall()
    finally:
        conn.close()

# ─────────────────────────────────────────────────────────────
# LÓGICA PRINCIPAL
# ─────────────────────────────────────────────────────────────

def create_contact(data):
    id_centralizador = data.get("ID_centralizador")
    crm_proyecto_id = data.get("ID_proyecto")

    # 1. MODOS DE ENVÍO
    activar_manual = str(data.get("Activar_Contacto") or "").lower().strip()
    estado_cf_2    = str(data.get("enviado_cf_2") or "").lower().strip()
    IS_SECOND_SEND = (activar_manual == "dos") or (estado_cf_2 == "dos")

    # === [LÓGICA DE TIEMPOS Y RESPUESTAS] ===
    # Obtenemos el campo 'Now' (2025-11-27 00:55:09)
    fecha_lead_now = _parse_datetime_db(data.get("Now"))
    raw_phone = data.get("phone_norm_gen") or data.get("Numero_telefono_movil_cliente")
    phone_number = clean_phone_number(raw_phone)
    fecha_ref_diaria = _parse_fecha_ymd(format_date(data.get("Fecha_ingreso"))) or datetime.now().date()

    if IS_SECOND_SEND:
        print(f"🔄 [MODO] SEGUNDO ENVIO para ID {id_centralizador}")
        
        # Validar si el cliente YA respondió DESPUÉS de que llegó este lead
        if fecha_lead_now:
            if verificar_respuesta_post_lead(phone_number, fecha_lead_now):
                print(f"✋ Cliente respondió después de {fecha_lead_now}. Cancelando Envío 2.")
                return {'status': 'stopped', 'message': 'Cliente ya respondió'}
        else:
            print("⚠️ Advertencia: Campo 'Now' vacío en DB, no se puede verificar respuesta post-lead.")

    else:
        print(f"✨ [MODO] PRIMER ENVIO para ID {id_centralizador}")

    # 2. VALIDAR PROYECTO
    try:
        if int(crm_proyecto_id) not in PROYECTOS_ACTIVO:
            if not IS_SECOND_SEND:
                update_sent_status(id_centralizador, "proyecto no activo", 0)
            return {'status': 'skipped', 'message': 'Proyecto no activo'}
    except:
        return {'status': 'skipped', 'message': 'ID Proyecto inválido'}


    # 3. VALIDACIONES PRIMER ENVÍO
    if not IS_SECOND_SEND:
        # A. Ya enviado este ID
        if not should_send_to_chatfuel(id_centralizador):
            return {'status': 'skipped', 'message': f"ID {id_centralizador} ya enviado."}
        # B. Límite diario (mismo día calendario)
        if existe_envio_misma_fecha(phone_number, fecha_ref_diaria):
            return {'status': 'skipped', 'message': "Límite diario alcanzado hoy."}

    # 4. PAYLOAD
    payload = {
        "phone": phone_number,
        "attributes": {
            "whatsapp_phone": phone_number,
            "crm Fecha_ingreso": format_date(data.get("Fecha_ingreso")),
            "crm Hora_ingreso": format_date(data.get("Hora_ingreso")),
            "crm ID_centralizador": id_centralizador,
            "crm Estado": data.get("Estado"),
            "crm ID_cliente": data.get("ID_cliente"),
            "crm_ID_cliente": data.get("ID_cliente"),
            "crm medio id": data.get("ID_medio_llegada"),
            "crm Medio_llegada": data.get("Medio_llegada"),
            "crm Rut_cliente": data.get("Rut_cliente"),
            "crm Nombre_cliente": data.get("Nombre_cliente"),
            "crm Apellido_cliente": data.get("Apellido_cliente"),
            "crm Proyecto": data.get("Proyecto"),
            "crm ID_proyecto": crm_proyecto_id,
            "crm Nombre_vendedor": data.get("Nombre_vendedor"),
            "crm Email_vendedor": data.get("Email_vendedor"),
            "crm Rut_vendedor": data.get("Rut_vendedor"),
            "crm Email_cliente": data.get("Email_cliente"), 
            "Activar_Contacto": "Dos" if IS_SECOND_SEND else True 
        },
        "invokeTriggers": True,
        "tagNames": ["Nuevo_lead"]
    }
    
    headers = {'Content-Type': 'application/json'}

    # 5. ENVIAR
    try:
        if CHATFUEL_TOKEN != 'NO' and CHATFUEL_BOT_ID != 'NO':
            response = requests.post(CHATFUEL_URL, data=json.dumps(payload), headers=headers)
            
            if response.status_code == 200:
                update_sent_status(id_centralizador, response.text, 1)
                
                if not IS_SECOND_SEND:
                    # Registrar envío diario solo en el primero
                    registrar_envio_misma_fecha(phone_number, id_centralizador, fecha_ref_diaria)

                # 6. PLANOK (Solo Primer Envío)
                if not IS_SECOND_SEND:
                    if int(crm_proyecto_id) in PROYECTOS_ACTIVO and os.getenv("RUN_PATCH_GCI","0").lower() in ("1","true","yes"):
                        print(f"📡 [PlanOK] Enviando GCI para ID {id_centralizador}")
                        try:
                            patch_lead_gci(id_centralizador)
                            id_cli = int(data.get("ID_cliente") or 0)
                            id_med = int(data.get("ID_medio_llegada") or 0)
                            rut_v = data.get("Rut_vendedor") or obtener_rut_vendedor_por_proyecto(int(crm_proyecto_id))
                            f_rec = (datetime.utcnow() + timedelta(days=DIASDESCTIVADO)).strftime('%Y-%m-%dT%H:%M:%SZ')

                            seg_id = crear_seguimiento(
                                id_cliente=id_cli, id_proyecto=int(crm_proyecto_id), id_medio=id_med,
                                id_tipo_contacto=GCI_ID_TIPO_CONTACTO_DEFAULT, id_expectativa=GCI_ID_EXPECTATIVA_DEFAULT,
                                comentario=GCI_SEGUIMIENTO_COMENTARIO, fecha_recontacto_str=f_rec,
                                mantener_ejecutivo=False, rutvendedor=rut_v
                            )
                            print(f"✅ [PlanOK] Seguimiento ID: {seg_id}")
                            if seg_id: update_planok_response_db(id_centralizador, seg_id)
                        except Exception as e:
                            print(f"❌ [PlanOK] Error: {e}")
                            update_planok_response_db(id_centralizador, f"Error: {e}")
                
                return response.json()
            else:
                return {'status': 'error', 'text': response.text, 'code': response.status_code}
        else:
            return {'status': 'skipped', 'message': 'Chatfuel config missing'}
    except Exception as e:
        return {'error': str(e)}

def process_data():
    ensure_limit_table()
    data_list = fetch_data_from_database()
    if data_list:
        for data in data_list:
            create_contact(data)

if __name__ == '__main__':
    process_data()