"""
Agente de Seguimiento Comercial — Track Mar (División Repuestos)
Orquestador principal. Uso:

    python main.py --modo diario
    python main.py --modo semanal
    python main.py --modo diario --dry-run     # fuerza modo de prueba aunque config.DRY_RUN sea False

Pensado para correr como una tarea programada (cron / Task Scheduler) una vez
por día. Ver el documento "Agente_Seguimiento_Comercial_TrackMar.docx" para el
diseño completo y la sección 9 para lo que falta configurar antes de un uso real.
"""
import argparse
from datetime import datetime
from collections import defaultdict
import calendar

import config
import db
import reglas
import registro
import reportes
import whatsapp


def _cargar_sucursales(engine):
    """sucursal_id -> {"nombre": ..., "email_alerta": ...}, una sola consulta
    por corrida (antes se pasaba un cache {} nuevo en cada llamado, así que
    nunca cacheaba nada y no había forma de resolver el encargado real)."""
    return {s["sucursal_id"]: s for s in db.obtener_sucursales(engine)}


def _nombre_sucursal(sucursal_id, sucursales):
    info = sucursales.get(sucursal_id)
    return info["sucursal_nombre"] if info else str(sucursal_id)


def correr_diario(engine, dry_run_forzado=False):
    print(f"[{datetime.now()}] Corriendo control diario...")
    sucursales = _cargar_sucursales(engine)

    cotizaciones_caidas = db.obtener_cotizaciones_sin_seguimiento(engine)
    ventas_sin_motivo = db.obtener_ventas_perdidas_sin_motivo(engine)
    contactos_caidos = db.obtener_contactos_en_frio_sin_cotizacion(engine)
    visitas_sin_resultado = db.obtener_visitas_sin_resultado(engine)

    # --- Eje 1 y Eje 3: contacto directo al cliente (solo en sucursales piloto) ---
    for item in cotizaciones_caidas:
        sucursal = _nombre_sucursal(item["sucursal_id"], sucursales)
        if not reglas.puede_contactar_cliente_por_sucursal(sucursal):
            registro.registrar(tipo="cotizacion_sin_seguimiento", sucursal=sucursal,
                                cliente_id=item["cliente_id"], referencia=item["cotizacion_id"],
                                canal="whatsapp_cliente", resultado="omitido_fuera_de_piloto")
            continue
        if not reglas.telefono_whatsapp_valido(item.get("cliente_whatsapp")):
            registro.registrar(tipo="cotizacion_sin_seguimiento", sucursal=sucursal,
                                cliente_id=item["cliente_id"], referencia=item["cotizacion_id"],
                                canal="whatsapp_cliente", resultado="omitido_sin_telefono_valido")
            continue
        if registro.ya_se_contacto_recientemente(item["cliente_id"], item["cotizacion_id"]):
            continue
        whatsapp.enviar_plantilla(
            telefono=item["cliente_whatsapp"],
            nombre_plantilla=config.PLANTILLA_SEGUIMIENTO_COTIZACION,
            parametros=[item.get("cliente_nombre", ""), item["cotizacion_id"], sucursal],
            cliente_id=item["cliente_id"], cliente_nombre=item.get("cliente_nombre", ""),
            referencia=item["cotizacion_id"], tipo="cotizacion_sin_seguimiento",
        )

    for item in contactos_caidos:
        sucursal = _nombre_sucursal(item["sucursal_id"], sucursales)
        if not reglas.puede_contactar_cliente_por_sucursal(sucursal):
            registro.registrar(tipo="contacto_frio_sin_cotizacion", sucursal=sucursal,
                                cliente_id=item["cliente_id"], referencia=item["contacto_id"],
                                canal="whatsapp_cliente", resultado="omitido_fuera_de_piloto")
            continue
        if not reglas.telefono_whatsapp_valido(item.get("cliente_whatsapp")):
            registro.registrar(tipo="contacto_frio_sin_cotizacion", sucursal=sucursal,
                                cliente_id=item["cliente_id"], referencia=item["contacto_id"],
                                canal="whatsapp_cliente", resultado="omitido_sin_telefono_valido")
            continue
        if registro.ya_se_contacto_recientemente(item["cliente_id"], item["contacto_id"]):
            continue
        whatsapp.enviar_plantilla(
            telefono=item["cliente_whatsapp"],
            nombre_plantilla=config.PLANTILLA_CONTACTO_FRIO,
            parametros=[item.get("cliente_nombre", ""), sucursal],
            cliente_id=item["cliente_id"], cliente_nombre=item.get("cliente_nombre", ""),
            referencia=item["contacto_id"], tipo="contacto_frio_sin_cotizacion",
        )

    # --- Ventas perdidas sin motivo y visitas sin resultado: solo aviso interno ---
    for item in ventas_sin_motivo:
        registro.registrar(tipo="venta_perdida_sin_motivo", sucursal=str(item["sucursal_id"]),
                            referencia=item["cotizacion_id"], canal="interno", resultado="detectado")
    for item in visitas_sin_resultado:
        registro.registrar(tipo="visita_sin_resultado", sucursal=str(item["sucursal_id"]),
                            referencia=item["visita_id"], canal="interno", resultado="detectado")

    # --- Armar y enviar alerta diaria por sucursal ---
    por_sucursal = defaultdict(lambda: {"cotizaciones": [], "contactos": [], "visitas": []})
    for i in cotizaciones_caidas:
        por_sucursal[i["sucursal_id"]]["cotizaciones"].append(i)
    for i in contactos_caidos:
        por_sucursal[i["sucursal_id"]]["contactos"].append(i)
    for i in visitas_sin_resultado:
        por_sucursal[i["sucursal_id"]]["visitas"].append(i)

    for sucursal_id, datos in por_sucursal.items():
        info_sucursal = sucursales.get(sucursal_id)
        sucursal_nombre = info_sucursal["sucursal_nombre"] if info_sucursal else str(sucursal_id)
        texto = reportes.armar_alerta_diaria(sucursal_nombre, datos["cotizaciones"], datos["contactos"], datos["visitas"])
        email_encargado = (info_sucursal or {}).get("email_alerta")
        if email_encargado and "@" in email_encargado:
            reportes.enviar_email(email_encargado, f"Track Mar — Alerta diaria ({sucursal_nombre})", texto)
        else:
            print(f"[sin email_alerta valido para sucursal {sucursal_nombre}]\n{texto}")

    for destinatario in config.DESTINATARIOS_GERENCIALES:
        if destinatario.get("email"):
            resumen_completo = "\n\n".join(
                reportes.armar_alerta_diaria(_nombre_sucursal(sid, sucursales), d["cotizaciones"], d["contactos"], d["visitas"])
                for sid, d in por_sucursal.items()
            ) or "Sin novedades en ninguna sucursal hoy."
            reportes.enviar_email(destinatario["email"], "Track Mar — Alerta diaria del agente de seguimiento", resumen_completo)

    print(f"[{datetime.now()}] Control diario terminado. "
          f"{len(cotizaciones_caidas)} cotizaciones, {len(contactos_caidos)} contactos, "
          f"{len(visitas_sin_resultado)} visitas, {len(ventas_sin_motivo)} ventas sin motivo.")


def correr_semanal(engine):
    print(f"[{datetime.now()}] Armando resumen semanal...")
    ritmo = db.obtener_ritmo_contactos_mes(engine)
    hoy = datetime.now()
    dias_en_el_mes = calendar.monthrange(hoy.year, hoy.month)[1]

    resumen = []
    for fila in ritmo:
        en_riesgo = reglas.proyeccion_contactos_en_riesgo(
            fila["contactos_mes_actual"], hoy.day, dias_en_el_mes)
        resumen.append({
            "sucursal": fila["sucursal_nombre"],
            "semaforo_eje1": "—",  # completar cruzando con cotizaciones si se desea en el resumen semanal
            "semaforo_eje2": "—",
            "semaforo_eje3": "Rojo" if en_riesgo else "Verde",
            "contactos_mes": fila["contactos_mes_actual"],
            "objetivo_mes": config.OBJETIVO_CONTACTOS_FRIO_POR_MES,
        })

    texto = reportes.armar_resumen_semanal(resumen)
    for destinatario in config.DESTINATARIOS_GERENCIALES:
        if destinatario.get("email"):
            reportes.enviar_email(destinatario["email"], "Track Mar — Resumen semanal del agente de seguimiento", texto)
    print(texto)


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Agente de Seguimiento Comercial - Track Mar")
    parser.add_argument("--modo", choices=["diario", "semanal"], required=True)
    parser.add_argument("--dry-run", action="store_true", help="Fuerza modo de prueba (no envía nada real)")
    args = parser.parse_args()

    if args.dry_run:
        config.DRY_RUN = True

    engine = db.get_engine()
    if args.modo == "diario":
        correr_diario(engine)
    else:
        correr_semanal(engine)
