"""
Worker de follow-up. Roda em loop, a cada N segundos consulta o banco,
determina quais notificações venceram e envia via DinastiAPI.
"""
import logging
import time
from datetime import datetime, timezone
from typing import Optional

import requests

import config
import db

log = logging.getLogger("px3_followup.worker")


# ---------------------------------------------------------------------------
# Envio via DinastiAPI
# ---------------------------------------------------------------------------
def send_whatsapp(phone: str, body: str) -> bool:
    url = f"{config.DINASTIA_URL.rstrip('/')}{config.DINASTIA_SEND_ENDPOINT}"
    headers = {
        "Content-Type": "application/json",
        "token": config.DINASTIA_TOKEN,
    }
    payload = {"Phone": phone, "Body": body}
    try:
        resp = requests.post(url, json=payload, headers=headers, timeout=20)
        if resp.status_code >= 400:
            log.error(
                "DinastiAPI erro %s ao enviar para %s: %s",
                resp.status_code, phone, resp.text[:300],
            )
            return False
        log.info("Notificação enviada para %s", phone)
        return True
    except Exception as e:
        log.exception("Falha ao enviar WhatsApp para %s: %s", phone, e)
        return False


# ---------------------------------------------------------------------------
# Construção da mensagem
# ---------------------------------------------------------------------------
def build_message(event: dict, tag_label: str, delay_hours: int) -> str:
    return (
        "🔔 PX3 - Follow-up necessário\n\n"
        f"Lead: {event.get('contact_name') or '(sem nome)'}\n"
        f"Telefone: {event.get('contact_phone') or '(sem telefone)'}\n"
        f"Evento: {tag_label}\n"
        f"Tempo: há {config.delay_label(delay_hours)}\n\n"
        "Retorne agora."
    )


# ---------------------------------------------------------------------------
# Parse de datas do banco
# ---------------------------------------------------------------------------
def _parse_ts(value: str) -> datetime:
    """
    Aceita ISO com/sem timezone. Se vier naive, assume UTC.
    """
    if value.endswith("Z"):
        value = value.replace("Z", "+00:00")
    dt = datetime.fromisoformat(value)
    if dt.tzinfo is None:
        dt = dt.replace(tzinfo=timezone.utc)
    return dt


# ---------------------------------------------------------------------------
# Processamento
# ---------------------------------------------------------------------------
def process_pending() -> None:
    """
    Percorre todos os eventos e envia as notificações que já venceram
    e ainda não foram enviadas.
    """
    now = datetime.now(timezone.utc)
    events = db.list_all_events()
    log.info("Worker rodando - %d evento(s) monitorado(s)", len(events))

    for event in events:
        tag = event["tag"]
        cfg = config.TAGS_CONFIG.get(tag)
        if not cfg:
            continue

        tag_added_at = _parse_ts(event["tag_added_at"])
        elapsed_hours = (now - tag_added_at).total_seconds() / 3600.0

        for delay in cfg["delays_hours"]:
            if elapsed_hours < delay:
                # ainda não venceu esse marco (e como a lista é crescente, os próximos também não)
                break

            if db.notification_already_sent(event["id"], delay):
                continue

            assigned = event.get("assigned_user_id") or ""
            phone = config.USER_PHONE_MAP.get(assigned)
            if not phone:
                log.warning(
                    "Sem WhatsApp para assignedTo=%s (event %s, tag=%s, delay=%sh) - skip",
                    assigned, event["id"], tag, delay,
                )
                # marca como enviada mesmo assim, senão vai logar toda hora
                db.mark_notification_sent(event["id"], delay)
                continue

            body = build_message(event, cfg["label"], delay)
            ok = send_whatsapp(phone, body)
            if ok:
                db.mark_notification_sent(event["id"], delay)


# ---------------------------------------------------------------------------
# Loop
# ---------------------------------------------------------------------------
def run_forever() -> None:
    log.info(
        "Worker iniciado - intervalo=%ss - tags=%s",
        config.WORKER_INTERVAL_SECONDS,
        list(config.TAGS_CONFIG.keys()),
    )
    while True:
        try:
            process_pending()
        except Exception:
            log.exception("Erro no ciclo do worker")
        time.sleep(config.WORKER_INTERVAL_SECONDS)


if __name__ == "__main__":
    logging.basicConfig(
        level=logging.INFO,
        format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
        handlers=[
            logging.FileHandler(config.LOG_PATH),
            logging.StreamHandler(),
        ],
    )
    db.init_db()
    run_forever()
