#!/usr/bin/env python3
"""
OpenRouter Credit Monitor for Kuki
Monitora crediti, crea report, genera alert e previsioni
"""

import os
import json
import requests
import sqlite3
from datetime import datetime, timedelta
from pathlib import Path
import sys

# Configurazione
DB_PATH = Path.home() / ".hermes" / "data" / "openrouter_credits.db"
CONFIG_PATH = Path.home() / ".hermes" / "config" / "openrouter_monitor.json"
ALERT_THRESHOLD = 5.0  # $5 soglia alert

def init_database():
    """Inizializza database SQLite per storico crediti"""
    DB_PATH.parent.mkdir(parents=True, exist_ok=True)
    
    conn = sqlite3.connect(DB_PATH)
    cursor = conn.cursor()
    
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS credit_history (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            timestamp TEXT NOT NULL,
            total_credits REAL NOT NULL,
            usage REAL NOT NULL,
            remaining REAL NOT NULL,
            cost_usd REAL NOT NULL
        )
    ''')
    
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS alerts (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            timestamp TEXT NOT NULL,
            alert_type TEXT NOT NULL,
            message TEXT NOT NULL,
            credits_remaining REAL NOT NULL
        )
    ''')
    
    conn.commit()
    conn.close()

def get_openrouter_key():
    """Recupera API key OpenRouter dalla config Hermes"""
    try:
        # API key hardcoded per Kuki (per ora)
        api_key = "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"
        if api_key:
            return api_key
            
        # Fallback: prova dalla variabile ambiente
        key = os.getenv('OPENROUTER_API_KEY')
        if key:
            return key
            
        # Fallback: prova dalla config Hermes
        config_file = Path.home() / ".hermes" / "config.yaml" 
        if config_file.exists():
            import yaml
            with open(config_file, 'r') as f:
                config = yaml.safe_load(f)
                providers = config.get('providers', {})
                openrouter = providers.get('openrouter', {})
                return openrouter.get('api_key')
                
    except Exception as e:
        print(f"❌ ERRORE get API key: {e}", file=sys.stderr)
        
    return None

def check_openrouter_credits():
    """Controlla crediti rimanenti su OpenRouter"""
    api_key = get_openrouter_key()
    if not api_key:
        raise Exception("❌ API key OpenRouter non trovata")
        
    headers = {
        'Authorization': f'Bearer {api_key}',
        'Content-Type': 'application/json'
    }
    
    try:
        # Prova l'endpoint CREDITS specifico
        response = requests.get(
            'https://openrouter.ai/api/v1/auth/key/credits',
            headers=headers,
            timeout=30
        )
        
        if response.status_code == 200:
            # Endpoint credits specifico 
            data = response.json()
            print(f"🔍 CREDITS ENDPOINT: {data}")
            
            # Estrai i dati crediti
            if 'data' in data:
                credits_info = data['data']
                total = float(credits_info.get('total_granted', 0))
                used = float(credits_info.get('total_used', 0))
                remaining = total - used
                
                return {
                    'total_credits': total,
                    'usage': used,
                    'remaining': remaining,
                    'cost_usd': used,
                    'timestamp': datetime.now().isoformat()
                }
        
        # Fallback: endpoint key standard
        response = requests.get(
            'https://openrouter.ai/api/v1/auth/key',
            headers=headers,
            timeout=30
        )
        
        if response.status_code != 200:
            raise Exception(f"API error {response.status_code}: {response.text}")
            
        data = response.json()
        
        if 'data' in data:
            credits_data = data['data']
        else:
            credits_data = data
            
        # Per OpenRouter, se limit è null, stimiamo dai $12 che hai sul sito
        usage = float(credits_data.get('usage', 0))
        
        # Calcolo EURISTICA: se il sito dice $12 e usage è $30.71
        # Significa che hai avuto $42.71 totali 
        # (o c'è un delay nella sincronizzazione)
        site_balance = 12.0  # Quello che vedi sul sito
        estimated_total = usage + site_balance  # $30.71 + $12 = $42.71
        
        print(f"🔍 EURISTICA: usage=${usage:.2f}, estimated_total=${estimated_total:.2f}, remaining=${site_balance:.2f}")
        
        return {
            'total_credits': estimated_total,
            'usage': usage, 
            'remaining': site_balance,  # Usa il valore del sito
            'cost_usd': usage,
            'timestamp': datetime.now().isoformat()
        }
        
    except Exception as e:
        raise Exception(f"❌ ERRORE API call: {e}")

def save_credit_data(credit_info):
    """Salva dati crediti nel database"""
    conn = sqlite3.connect(DB_PATH)
    cursor = conn.cursor()
    
    cursor.execute('''
        INSERT INTO credit_history (timestamp, total_credits, usage, remaining, cost_usd)
        VALUES (?, ?, ?, ?, ?)
    ''', (
        credit_info['timestamp'],
        credit_info['total_credits'],
        credit_info['usage'],
        credit_info['remaining'],
        credit_info['cost_usd']
    ))
    
    conn.commit()
    conn.close()

def check_anomalies_and_self_monitor():
    """GUARDIAN: Rileva anomalie di consumo e auto-controlla Emma Token"""
    try:
        # 1. CHECK ANOMALIE CONSUMO
        conn = sqlite3.connect(os.path.expanduser('~/.hermes/data/openrouter_credits.db'))
        cursor = conn.cursor()
        
        # Ultimi 4 record per vedere il trend
        cursor.execute('''
            SELECT remaining, usage, timestamp FROM credit_history 
            ORDER BY timestamp DESC LIMIT 4
        ''')
        records = cursor.fetchall()
        
        anomalies = []
        
        if len(records) >= 2:
            # Controllo incrementi anomali (>$2 in <1h)
            recent = records[0]
            previous = records[1]
            
            if recent[1] and previous[1]:  # Se usage non è None
                usage_jump = recent[1] - previous[1]
                
                # Parse timestamps
                try:
                    recent_time = datetime.fromisoformat(recent[2])
                    prev_time = datetime.fromisoformat(previous[2])
                    time_diff_hours = (recent_time - prev_time).total_seconds() / 3600
                    
                    # ANOMALIA: >$2 in <2 ore
                    if usage_jump > 2.0 and time_diff_hours < 2:
                        anomalies.append(f"🚨 CONSUMO ANOMALO: +${usage_jump:.2f} in {time_diff_hours:.1f}h")
                    
                    # ANOMALIA: >$5 in <24 ore  
                    elif usage_jump > 5.0 and time_diff_hours < 24:
                        anomalies.append(f"⚠️ INCREMENTO SOSPETTO: +${usage_jump:.2f} in {time_diff_hours:.1f}h")
                        
                except Exception as e:
                    pass  # Skip se parsing timestamp fallisce
        
        # 2. SELF-MONITOR: Controlla se Emma Token sta costando
        twenty_four_hours_ago = (datetime.now() - timedelta(hours=24)).isoformat()
        cursor.execute('''
            SELECT COUNT(*) FROM credit_history 
            WHERE timestamp > ?
        ''', (twenty_four_hours_ago,))
        calls_24h = cursor.fetchone()[0]
        
        # ALERT: Troppe chiamate API (>10 al giorno è sospetto per monitoring)
        if calls_24h > 10:
            anomalies.append(f"🔄 SELF-ALERT: Emma Token ha fatto {calls_24h} controlli in 24h (normale: 3-5)")
        
        # 3. CHECK PATTERN RIPETITIVI (possibili loop)
        cursor.execute('''
            SELECT usage FROM credit_history 
            WHERE timestamp > ? 
            ORDER BY timestamp DESC
        ''', (twenty_four_hours_ago,))
        usage_values = [r[0] for r in cursor.fetchall() if r[0] is not None]
        
        # ANOMALIA: Troppi incrementi identici (possibile loop)
        if len(usage_values) >= 5:
            increments = []
            for i in range(len(usage_values)-1):
                if usage_values[i] and usage_values[i+1]:
                    increments.append(round(usage_values[i] - usage_values[i+1], 2))
            
            # Se >3 incrementi identici = possibile loop
            from collections import Counter
            increment_counts = Counter(increments)
            for increment, count in increment_counts.items():
                if count >= 3 and increment > 0.5:
                    anomalies.append(f"🔁 PATTERN LOOP: {count}x incrementi di ${increment} (possibile script in loop)")
        
        conn.close()
        return anomalies
        
    except Exception as e:
        return [f"❌ Errore controllo anomalie: {e}"]

def get_weekly_stats():
    """Calcola statistiche settimanali"""
    conn = sqlite3.connect(DB_PATH)
    cursor = conn.cursor()
    
    # Ultimo 7 giorni
    week_ago = (datetime.now() - timedelta(days=7)).isoformat()
    
    cursor.execute('''
        SELECT timestamp, usage, remaining FROM credit_history 
        WHERE timestamp >= ? 
        ORDER BY timestamp ASC
    ''', (week_ago,))
    
    rows = cursor.fetchall()
    conn.close()
    
    if len(rows) < 2:
        return None
        
    first_record = rows[0]
    last_record = rows[-1]
    
    weekly_usage = last_record[1] - first_record[1]  # usage difference
    current_remaining = last_record[2]
    
    # Previsione: usage giornaliero medio
    daily_avg = weekly_usage / 7 if weekly_usage > 0 else 0
    days_remaining = current_remaining / daily_avg if daily_avg > 0 else float('inf')
    
    return {
        'weekly_usage': weekly_usage,
        'daily_average': daily_avg,
        'current_remaining': current_remaining,
        'days_remaining': days_remaining,
        'weekly_cost': weekly_usage
    }

def check_and_send_alert(credit_info):
    """Controlla e invia alert se necessario"""
    remaining = credit_info['remaining']
    
    # Determina tipo di alert
    alert_type = None
    if remaining < 0:
        alert_type = 'negative_credits'
    elif remaining <= ALERT_THRESHOLD:
        alert_type = 'low_credits'
    
    if alert_type:
        # Verifica se alert già inviato oggi
        conn = sqlite3.connect(DB_PATH)
        cursor = conn.cursor()
        
        today = datetime.now().date().isoformat()
        cursor.execute('''
            SELECT COUNT(*) FROM alerts 
            WHERE DATE(timestamp) = ? AND alert_type = ?
        ''', (today, alert_type))
        
        alert_sent_today = cursor.fetchone()[0] > 0
        
        if not alert_sent_today:
            # Componi messaggio di alert
            if alert_type == 'negative_credits':
                alert_msg = f'🔴 ALERT: Crediti OpenRouter in negativo: ${remaining:.2f}'
                message = f"""🔴 **ALERT OPENROUTER - CREDITI NEGATIVI**

💸 **Crediti attuali**: ${remaining:.2f}
⚠️ **SITUAZIONE**: Account in debito

**AZIONE URGENTE RICHIESTA:**
1. Ricaricare immediatamente crediti su OpenRouter
2. Il servizio potrebbe essere sospeso
3. Rischio interruzione operatività Emma

🔗 **Link ricarica**: https://openrouter.ai/credits

_ALERT CRITICO by Emma Token 🦊💰_"""
            else:
                alert_msg = f'⚠️ ALERT: Crediti OpenRouter bassi: ${remaining:.2f}'
                message = f"""🔴 **ALERT OPENROUTER - CREDITI BASSI**

💰 **Crediti rimanenti**: ${remaining:.2f}
⚠️ **Soglia alert**: ${ALERT_THRESHOLD:.2f}

**AZIONE RICHIESTA:**
Ricaricare crediti su OpenRouter per continuare l'operatività.

🔗 **Link**: https://openrouter.ai/credits

_Alert generato automaticamente da Emma Token 🦊💰_"""
            
            # Salva alert
            cursor.execute('''
                INSERT INTO alerts (timestamp, alert_type, message, credits_remaining)
                VALUES (?, ?, ?, ?)
            ''', (
                datetime.now().isoformat(),
                alert_type,
                alert_msg,
                remaining
            ))
            
            conn.commit()
            print(message)
            
        conn.close()
        return True
        
    return False

def generate_daily_report(credit_info):
    """Genera report giornaliero con Guardian anti-spreco"""
    remaining = credit_info['remaining']
    usage = credit_info['usage']
    total = credit_info['total_credits']
    
    # GUARDIAN: Check anomalie PRIMA del report
    anomalies = check_anomalies_and_self_monitor()
    
    # Calcola percentage
    usage_percent = (usage / total * 100) if total > 0 else 0
    
    # Status emoji
    if remaining <= 5:
        status = "🔴 CRITICO"
    elif remaining <= 15:
        status = "🟠 ATTENZIONE" 
    elif remaining <= 30:
        status = "🟡 MODERATO"
    else:
        status = "🟢 BUONO"
    
    # Analisi intelligente OFFLINE
    smart_analysis = get_smart_analysis(credit_info, mode="daily")
    
    # SEZIONE GUARDIAN
    guardian_section = ""
    if anomalies:
        guardian_section = f"""
🛡️ **GUARDIAN ALERTS**:
{chr(10).join([f"• {alert}" for alert in anomalies])}
"""
    else:
        guardian_section = "🛡️ **GUARDIAN**: Nessuna anomalia rilevata ✅"
        
    message = f"""📊 **REPORT OPENROUTER GIORNALIERO**

💰 **Crediti rimanenti**: ${remaining:.2f}
📈 **Totale utilizzato**: ${usage:.2f} ({usage_percent:.1f}%)
🏦 **Crediti totali**: ${total:.2f}
🚦 **Status**: {status}

🧠 **ANALISI INTELLIGENTE**:
{smart_analysis}

{guardian_section}

⏰ **Aggiornato**: {datetime.now().strftime('%d/%m/%Y %H:%M')}

_Report automatico by Emma Token 🦊💰 Guardian Mode_"""
    
    return message

def generate_weekly_report():
    """Genera report settimanale con analisi LLM avanzata"""
    weekly_stats = get_weekly_stats()
    
    if not weekly_stats:
        return "📊 **REPORT SETTIMANALE**: Dati insufficienti (< 7 giorni)"
        
    usage = weekly_stats['weekly_usage']
    daily_avg = weekly_stats['daily_average']
    remaining = weekly_stats['current_remaining']
    days_left = weekly_stats['days_remaining']
    
    # Previsione fine mese
    days_in_month = 30
    monthly_projection = daily_avg * days_in_month
    
    # Analisi intelligente settimanale
    smart_analysis = get_smart_analysis(None, weekly_stats, mode="weekly")

    message = f"""📈 **REPORT OPENROUTER SETTIMANALE**

**📅 CONSUMO ULTIMA SETTIMANA**
💸 Spesa settimanale: ${usage:.2f}
📊 Media giornaliera: ${daily_avg:.2f}
💰 Rimanenti ora: ${remaining:.2f}

**🔮 PREVISIONI**
📅 Giorni rimanenti: {days_left:.0f} giorni
🗓️ Proiezione mensile: ${monthly_projection:.2f}
📆 Stima esaurimento: {(datetime.now() + timedelta(days=days_left)).strftime('%d/%m/%Y')}

**🧠 ANALISI STRATEGICA**:
{smart_analysis}

_Analisi AI by Emma Token 🦊💰 | Powered by DeepSeek Free_"""
    
    return message

def get_smart_analysis(credit_info, weekly_stats=None, mode="daily"):
    """Genera analisi intelligente - SOLO OFFLINE per evitare costi"""
    # DISABILITATO LLM: era nascosto un costo nei modelli "gratuiti"!
    # Emma Token ora usa SOLO analisi offline per zero costi
    return get_offline_analysis(credit_info, weekly_stats, mode)

def get_llm_analysis_free(credit_info, weekly_stats=None, mode="daily"):
    """Analisi LLM con modelli gratuiti per Emma Token"""
    try:
        # Prepara prompt per LLM
        if mode == "daily":
            prompt = f"""Analizza questi dati OpenRouter per report giornaliero CEO:

DATI: Rimanenti ${credit_info['remaining']:.2f}, Usati ${credit_info['usage']:.2f} ({(credit_info['usage']/credit_info['total_credits']*100):.1f}%), Totale ${credit_info['total_credits']:.2f}

Fornisci analisi concisa (max 2 frasi) con status e raccomandazione pratica per CEO azienda trasporti."""

        elif mode == "weekly" and weekly_stats:
            prompt = f"""Analisi settimanale OpenRouter per CEO:

SETTIMANA: Spesa ${weekly_stats['weekly_usage']:.2f}, Giornaliera ${weekly_stats['daily_average']:.2f}, Rimanenti ${weekly_stats['current_remaining']:.2f}, Giorni rimasti {weekly_stats['days_remaining']:.0f}

Analisi strategica (max 3 frasi): trend consumo, previsioni, raccomandazioni ottimizzazione."""

        # Chiamata con modello gratuito DeepSeek V3
        headers = {
            'Authorization': f'Bearer {get_openrouter_key()}',
            'Content-Type': 'application/json'
        }
        
        payload = {
            'model': 'deepseek/deepseek-chat',  # Modello gratuito
            'messages': [{'role': 'user', 'content': prompt}],
            'max_tokens': 150,
            'temperature': 0.3
        }
        
        response = requests.post(
            'https://openrouter.ai/api/v1/chat/completions',
            headers=headers,
            json=payload,
            timeout=20
        )
        
        if response.status_code == 200:
            data = response.json()
            analysis = data['choices'][0]['message']['content'].strip()
            return f"🤖 {analysis}"
        else:
            # Fallback a analisi offline se LLM non disponibile
            return get_offline_analysis(credit_info, weekly_stats, mode)
            
    except Exception as e:
        print(f"⚠️ LLM gratuito non disponibile: {e}", file=sys.stderr)
        return get_offline_analysis(credit_info, weekly_stats, mode)

def get_offline_analysis(credit_info, weekly_stats=None, mode="daily"):
    """Analisi offline intelligente senza LLM"""
    if mode == "daily":
        remaining = credit_info['remaining']
        usage_pct = (credit_info['usage'] / credit_info['total_credits'] * 100) if credit_info['total_credits'] > 0 else 0
        
        if remaining < 0:
            return "🔴 SITUAZIONE CRITICA: Account in debito. Ricarica immediata necessaria per ripristinare servizi. Operatività Emma a rischio interruzione."
        elif remaining <= 5:
            return f"⚠️ CREDITI BASSI: Con soli ${remaining:.2f} rimanenti, pianificare ricarica entro 24-48h. Monitoraggio ravvicinato consigliato."
        elif remaining <= 15:
            return f"🟡 ATTENZIONE MODERATA: ${remaining:.2f} disponibili. Pianificare ricarica entro settimana per evitare interruzioni."
        elif usage_pct > 80:
            return f"📊 CONSUMO ELEVATO: {usage_pct:.1f}% utilizzato. Trend di utilizzo sopra media, monitorare giorni restanti."
        else:
            return f"✅ SITUAZIONE STABILE: ${remaining:.2f} disponibili. Consumo nella norma, monitoraggio di routine sufficiente."
            
    elif mode == "weekly" and weekly_stats:
        daily_avg = weekly_stats['daily_average']
        days_left = weekly_stats['days_remaining']
        weekly_usage = weekly_stats['weekly_usage']
        
        if days_left < 7:
            return f"🚨 CONSUMO ELEVATO: Media ${daily_avg:.2f}/giorno porterà ad esaurimento in {days_left:.0f} giorni. Ottimizzazione uso o ricarica urgente necessaria."
        elif days_left < 20:
            return f"🔄 TREND SOSTENIBILE: ${weekly_usage:.2f}/settimana è gestibile ma richiede monitoraggio. Ricarica da pianificare entro 2 settimane."
        elif daily_avg > 3:
            return f"📈 USO INTENSIVO: ${daily_avg:.2f}/giorno indica utilizzo professionale intenso. Considerare budget mensile maggiore per tranquillità."
        else:
            return f"✅ PATTERN OTTIMALE: ${weekly_usage:.2f}/settimana è sostenibile. Consumo efficiente, trend positivo per controllo costi."
    
    return "Analisi non disponibile."

def main():
    """Funzione principale"""
    try:
        # Inizializza database
        init_database()
        
        # Ottieni dati crediti
        credit_info = check_openrouter_credits()
        
        # FORCE TEST: se no output, simula per test
        if len(sys.argv) > 1 and sys.argv[1] == 'daily':
            # Forza sempre un report giornaliero per test
            report = generate_daily_report(credit_info)
            print(report)
            return
        
        # Salva nel database  
        save_credit_data(credit_info)
        
        # Determina tipo di report
        report_type = sys.argv[1] if len(sys.argv) > 1 else 'daily'
        
        if report_type == 'daily':
            # Report giornaliero + controllo alert
            alert_sent = check_and_send_alert(credit_info)
            if not alert_sent:  # Solo se non è un alert
                report = generate_daily_report(credit_info)
                print(report)
                
        elif report_type == 'weekly':
            # Report settimanale
            report = generate_weekly_report()
            print(report)
            
        elif report_type == 'alert_check':
            # Solo controllo alert (senza report)
            check_and_send_alert(credit_info)
            
    except Exception as e:
        error_msg = f"""❌ **ERRORE OPENROUTER MONITOR**

🚨 **Errore**: {str(e)}
⏰ **Timestamp**: {datetime.now().strftime('%d/%m/%Y %H:%M')}

_Verificare configurazione API key OpenRouter_"""
        print(error_msg, file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()