"""
dashboard_saude.py — Dashboard de saúde do consumo de leads/API do Google Places
para o painel /admin da ferramenta de prospecção.

Regras:
 - Free tier realista Google Places API ~= 10.500 leads/mês (US$200 grátis)
 - Overflow: cada lead extra custa ~US$ 0,019 (chamadas de Details/Search). Câmbio 5,5.
 - Configurável via env PROSPECCAO_FREE_TIER_LIMIT (default 10500).
"""

from __future__ import annotations

import os
import sqlite3
from datetime import datetime, timedelta
from pathlib import Path
from calendar import monthrange

DB_PATH = Path("/opt/mia/workspace/prospeccao_ativa/users.db")

# Custo médio por lead adicional (overflow) — Google Places API
USD_POR_LEAD_OVERFLOW = 0.019
CAMBIO_USD_BRL = 5.5


def _get_free_tier_limit() -> int:
    try:
        return int(os.environ.get("PROSPECCAO_FREE_TIER_LIMIT", "10500"))
    except (TypeError, ValueError):
        return 10500


def _get_conn():
    conn = sqlite3.connect(str(DB_PATH))
    conn.row_factory = sqlite3.Row
    return conn


def _somar_leads_do_mes_atual(conn) -> int:
    """
    Soma leads_usados de todas as contas.

    Regra: leads_usados representa o consumo desde o último reset da conta
    (quota_reset_em). Quando o cron mensal roda, zera-se leads_usados e
    atualiza-se quota_reset_em. Portanto, a SOMA atual de leads_usados
    reflete o consumo do mês corrente (do último reset até hoje).
    """
    row = conn.execute("SELECT COALESCE(SUM(leads_usados), 0) FROM ghl_config").fetchone()
    return int(row[0] or 0)


def _dias_restantes_no_mes() -> int:
    hoje = datetime.now()
    _, ultimo_dia = monthrange(hoje.year, hoje.month)
    return max(1, ultimo_dia - hoje.day)


def _dias_ja_passados_no_mes() -> int:
    return max(1, datetime.now().day)


def _semaforo(pct: float) -> tuple[str, str]:
    """Retorna (cor, texto) baseado no % consumido."""
    if pct < 75:
        return (
            "verde",
            "Saudável. Dentro do free tier do Google, custo API = R$ 0,00.",
        )
    if pct < 95:
        return (
            "amarelo",
            "Atenção. Aproximando do limite mensal do free tier.",
        )
    return (
        "vermelho",
        "Crítico. Free tier praticamente esgotado. Cada lead extra custa R$ 0,10-0,15.",
    )


def _top5_contas(conn) -> list[dict]:
    """Retorna top 5 contas por leads_usados."""
    rows = conn.execute("""
        SELECT c.id, c.nome, g.leads_usados, g.leads_limite
          FROM contas c
          JOIN ghl_config g ON g.conta_id = c.id
         ORDER BY g.leads_usados DESC
         LIMIT 5
    """).fetchall()

    top = []
    for i, r in enumerate(rows, start=1):
        limite = int(r["leads_limite"] or 0)
        usados = int(r["leads_usados"] or 0)
        pct = round((usados / limite) * 100, 1) if limite > 0 else 0.0
        top.append({
            "rank": i,
            "conta_id": r["id"],
            "nome": r["nome"],
            "usados": usados,
            "limite": limite,
            "pct": pct,
        })
    return top


def get_dashboard_saude(free_tier_limit: int | None = None) -> dict:
    """
    Retorna o dict com o estado atual do dashboard de saúde.

    Campos:
      total_usado, limite, pct, restantes
      cor_semaforo, texto_semaforo
      media_diaria, dias_restantes, projecao_mes
      overflow_projetado, custo_overflow_brl
      top5 (lista de dicts)
      free_tier_limit
    """
    if free_tier_limit is None:
        free_tier_limit = _get_free_tier_limit()

    conn = _get_conn()
    try:
        total_usado = _somar_leads_do_mes_atual(conn)
        top5 = _top5_contas(conn)
    finally:
        conn.close()

    limite = max(1, int(free_tier_limit))
    pct = round((total_usado / limite) * 100, 1)
    restantes = max(0, limite - total_usado)

    cor, texto = _semaforo(pct)

    # Projeção de fim de mês baseada em média diária corrente
    dias_passados = _dias_ja_passados_no_mes()
    dias_restantes = _dias_restantes_no_mes()
    media_diaria = round(total_usado / dias_passados, 1)
    projecao_mes = int(total_usado + (media_diaria * dias_restantes))
    overflow_projetado = max(0, projecao_mes - limite)
    custo_overflow_brl = round(overflow_projetado * USD_POR_LEAD_OVERFLOW * CAMBIO_USD_BRL, 2)

    # Ajuste do texto do semáforo quando há overflow projetado
    if cor == "amarelo" and overflow_projetado > 0:
        texto = (
            f"Atenção. Aproximando do limite. Se o ritmo continuar, "
            f"overflow custará R$ {custo_overflow_brl:.2f} este mês."
        )
    elif cor == "vermelho":
        texto = (
            f"Crítico. Free tier praticamente esgotado. Overflow projetado: "
            f"{overflow_projetado} leads (~R$ {custo_overflow_brl:.2f})."
        )

    return {
        "total_usado": total_usado,
        "limite": limite,
        "free_tier_limit": limite,
        "pct": pct,
        "pct_capped": min(100.0, pct),
        "restantes": restantes,
        "cor_semaforo": cor,
        "texto_semaforo": texto,
        "media_diaria": media_diaria,
        "dias_passados": dias_passados,
        "dias_restantes": dias_restantes,
        "projecao_mes": projecao_mes,
        "overflow_projetado": overflow_projetado,
        "custo_overflow_brl": custo_overflow_brl,
        "top5": top5,
    }


if __name__ == "__main__":
    import json as _json
    print(_json.dumps(get_dashboard_saude(), indent=2, ensure_ascii=False))
