"""
core/monitoring.py — Enregistrement des requêtes et métriques d'utilisation.

Stockage en mémoire (FIFO, 1 000 requêtes max). Thread-safe.

Tarifs GPT-4o appliqués (avril 2025) :
    Input  : $2.50 / 1M tokens
    Output : $10.00 / 1M tokens

Fonctions publiques :
    enregistrer(question, duree_ms, tokens_prompt, tokens_completion, erreur)
    get_metrics() → dict
"""

from __future__ import annotations

import threading
from collections import deque
from dataclasses import dataclass
from datetime import datetime, timezone

# ---------------------------------------------------------------------------
# Tarifs GPT-4o (USD par token)
# ---------------------------------------------------------------------------

_COUT_INPUT_PAR_TOKEN  = 2.50  / 1_000_000
_COUT_OUTPUT_PAR_TOKEN = 10.00 / 1_000_000

MAX_REQUETES = 1_000

# ---------------------------------------------------------------------------
# ROI — hypothèses de calcul
# Référence : coût d'une analyse manuelle par un analyste (30 min à 40 €/h)
# ---------------------------------------------------------------------------

_COUT_ANALYSE_MANUELLE_EUR = 20.0   # € par analyse (30 min × 40 €/h)
_TAUX_EUR_USD              = 1.09   # taux de conversion EUR→USD (avril 2025)

# ---------------------------------------------------------------------------
# Stockage
# ---------------------------------------------------------------------------

@dataclass
class Requete:
    timestamp:          str
    question:           str
    duree_ms:           float
    tokens_prompt:      int
    tokens_completion:  int
    cout_estime_usd:    float
    erreur:             str | None


_historique: deque[Requete] = deque(maxlen=MAX_REQUETES)
_lock = threading.Lock()


# ---------------------------------------------------------------------------
# API publique
# ---------------------------------------------------------------------------

def enregistrer(
    question:          str,
    duree_ms:          float,
    tokens_prompt:     int = 0,
    tokens_completion: int = 0,
    erreur:            str | None = None,
) -> None:
    """Enregistre une requête dans l'historique en mémoire."""
    cout = (
        tokens_prompt     * _COUT_INPUT_PAR_TOKEN
        + tokens_completion * _COUT_OUTPUT_PAR_TOKEN
    )
    entree = Requete(
        timestamp=datetime.now(timezone.utc).isoformat(),
        question=question[:200],
        duree_ms=round(duree_ms, 1),
        tokens_prompt=tokens_prompt,
        tokens_completion=tokens_completion,
        cout_estime_usd=round(cout, 6),
        erreur=erreur,
    )
    with _lock:
        _historique.append(entree)


def get_metrics() -> dict:
    """Retourne les agrégats sur toutes les requêtes enregistrées."""
    with _lock:
        requetes = list(_historique)

    nb_total   = len(requetes)
    nb_erreurs = sum(1 for r in requetes if r.erreur)

    if nb_total == 0:
        return {
            "total_requetes":           0,
            "requetes_en_erreur":       0,
            "taux_erreur_pct":          0.0,
            "duree_moyenne_ms":         0.0,
            "duree_max_ms":             0.0,
            "tokens_prompt_total":      0,
            "tokens_completion_total":  0,
            "cout_total_usd":           0.0,
            "cout_par_requete_usd":     0.0,
            "roi_economies_usd":        0.0,
            "roi_pct":                  0.0,
            "derniere_requete":         None,
        }

    ok     = [r for r in requetes if not r.erreur]
    durees = [r.duree_ms for r in ok] if ok else [0.0]

    cout_total_usd    = round(sum(r.cout_estime_usd for r in requetes), 6)
    valeur_manuelle   = nb_total * _COUT_ANALYSE_MANUELLE_EUR / _TAUX_EUR_USD
    economies_usd     = round(valeur_manuelle - cout_total_usd, 4)
    roi_pct           = round((valeur_manuelle - cout_total_usd) / max(cout_total_usd, 1e-9) * 100, 1)
    cout_par_requete  = round(cout_total_usd / nb_total, 6)

    return {
        "total_requetes":           nb_total,
        "requetes_en_erreur":       nb_erreurs,
        "taux_erreur_pct":          round(nb_erreurs / nb_total * 100, 1),
        "duree_moyenne_ms":         round(sum(durees) / len(durees), 1),
        "duree_max_ms":             round(max(durees), 1),
        "tokens_prompt_total":      sum(r.tokens_prompt for r in requetes),
        "tokens_completion_total":  sum(r.tokens_completion for r in requetes),
        "cout_total_usd":           cout_total_usd,
        "cout_par_requete_usd":     cout_par_requete,
        "roi_economies_usd":        economies_usd,
        "roi_pct":                  roi_pct,
        "derniere_requete": {
            "timestamp": requetes[-1].timestamp,
            "question":  requetes[-1].question,
            "duree_ms":  requetes[-1].duree_ms,
            "erreur":    requetes[-1].erreur,
        },
    }
