"""
Script principal pour orchestrer tout le système Chartbastan.

Ce script :
1. Initialise la base de données avec des matchs de test
2. Lance RabbitMQ (doit être démarré manuellement)
3. Lance tous les workers
4. Lance le serveur FastAPI

Usage:
    python run_all_system.py
"""

import logging
import sys
import time
from pathlib import Path
from datetime import datetime, timedelta
from sqlalchemy.orm import Session

# Add parent directory to path
sys_path = str(Path(__file__).parent)
if sys_path not in sys.path:
    sys.path.insert(0, sys_path)

from app.database import engine, Base, get_db
from app.models.match import Match
from app.scrapers.twitter_scraper import create_twitter_scraper
from app.scrapers.reddit_scraper import create_reddit_scraper
from app.services.sentiment_service import (
    process_tweet_batch,
    process_reddit_post_batch,
)
from app.ml.energy_calculator import calculate_energy_score
from app.services.prediction_service import PredictionService

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)


def create_test_matches():
    """
    Crée des matchs de test dans la base de données.
    
    Matchs créés pour l'Epic 3 (Backtesting) et Epic 2 (Data Collection).
    """
    logger.info("🎯 Création des matchs de test...")
    
    db = next(get_db())
    
    try:
        # Vérifier si des matchs existent déjà
        existing_matches = db.query(Match).count()
        
        if existing_matches > 0:
            logger.info(f"ℹ️ {existing_matches} matchs existent déjà, skip de la création")
            return
        
        # Créer des matchs de test (matchs à venir dans les 7 prochains jours)
        test_matches = [
            {
                "home_team": "PSG",
                "away_team": "Olympique de Marseille",
                "date": datetime.now() + timedelta(hours=24),
                "league": "Ligue 1",
                "status": "scheduled"
            },
            {
                "home_team": "Paris Saint-Germain",
                "away_team": "AS Monaco",
                "date": datetime.now() + timedelta(hours=48),
                "league": "Ligue 1",
                "status": "scheduled"
            },
            {
                "home_team": "Olympique Lyonnais",
                "away_team": "Olympique de Marseille",
                "date": datetime.now() + timedelta(hours=72),
                "league": "Ligue 1",
                "status": "scheduled"
            },
            {
                "home_team": "Real Madrid",
                "away_team": "Barcelona",
                "date": datetime.now() + timedelta(hours=96),
                "league": "La Liga",
                "status": "scheduled"
            },
            {
                "home_team": "Manchester United",
                "away_team": "Liverpool",
                "date": datetime.now() + timedelta(hours=120),
                "league": "Premier League",
                "status": "scheduled"
            }
        ]
        
        # Insérer les matchs
        for match_data in test_matches:
            match = Match(**match_data)
            db.add(match)
        
        db.commit()
        logger.info(f"✅ {len(test_matches)} matchs de test créés avec succès")
        
        # Afficher les matchs créés
        print("\n" + "="*70)
        print("📊 MATCHS DE TEST CRÉÉS")
        print("="*70)
        for i, match in enumerate(test_matches, 1):
            print(f"\n{i}. {match['home_team']} vs {match['away_team']}")
            print(f"   📅 {match['date'].strftime('%Y-%m-%d %H:%M')}")
            print(f"   🏆 {match['league']}")
            print(f"   📊 Status: {match['status']}")
        print("="*70 + "\n")
        
    except Exception as e:
        logger.error(f"❌ Erreur lors de la création des matchs: {e}")
        db.rollback()
    finally:
        db.close()


def check_rabbitmq_status():
    """
    Vérifie si RabbitMQ est accessible.
    """
    logger.info("🔗 Vérification de la connexion RabbitMQ...")
    
    try:
        import os
        rabbitmq_url = os.getenv('RABBITMQ_URL', 'amqp://guest:guest@localhost:5672')
        
        from app.queues.rabbitmq_client import create_rabbitmq_client
        client = create_rabbitmq_client(rabbitmq_url=rabbitmq_url)
        client.connect()
        client.close()
        
        logger.info("✅ RabbitMQ est accessible sur localhost:5672")
        return True
        
    except Exception as e:
        logger.error(f"❌ RabbitMQ n'est pas accessible: {e}")
        logger.warning("⚠️ Veuillez démarrer RabbitMQ avec Docker:")
        logger.warning("   docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management")
        return False


def simulate_full_pipeline():
    """
    Simule le pipeline complet de génération de prédictions.
    
    Ce pipeline correspond à Epic 2 (Data Collection) et Epic 3 (Prediction System).
    """
    logger.info("🔄 Lancement du pipeline complet de simulation...")
    
    db = next(get_db())
    
    try:
        # Récupérer les matchs
        matches = db.query(Match).all()
        
        if not matches:
            logger.error("❌ Aucun match trouvé. Veuillez d'abord créer des matchs de test.")
            return
        
        logger.info(f"📊 {len(matches)} matchs trouvés")
        
        # Pour chaque match, générer des données simulées
        for match in matches:
            logger.info(f"\n{'='*50}")
            logger.info(f"📋 Match: {match.home_team} vs {match.away_team}")
            
            # Simuler des tweets et posts Reddit (mock data)
            mock_tweets = [
                {
                    "tweet_id": f"tweet_{match.id}_{i}",
                    "text": f"Allez {match.home_team} ! On va gagner ce match ! #football #{match.home_team.replace(' ', '')}",
                    "author": f"fan_{match.home_team.lower()}",
                    "created_at": datetime.now(),
                    "retweet_count": 10 + i,
                    "like_count": 20 + i,
                    "reply_count": 5 + i
                }
                for i in range(10)
            ]
            
            mock_reddit_posts = [
                {
                    "post_id": f"reddit_{match.id}_{i}",
                    "title": f"{match.home_team} vs {match.away_team} - Match Preview",
                    "text": f"Prediction: {match.home_team} will win 2-1",
                    "author": f"u/redditor_{i}",
                    "created_at": datetime.now(),
                    "upvote_count": 15 + i,
                    "downvote_count": 2
                }
                for i in range(5)
            ]
            
            # Analyser le sentiment
            logger.info("🔍 Analyse de sentiment VADER...")
            from app.models.tweet import Tweet
            from app.models.reddit_post import RedditPost
            
            # Créer et analyser les tweets (simulation)
            tweet_sentiments = []
            for tweet_data in mock_tweets:
                tweet = Tweet(
                    tweet_id=tweet_data["tweet_id"],
                    text=tweet_data["text"],
                    author=tweet_data["author"],
                    created_at=tweet_data["created_at"],
                    retweet_count=tweet_data["retweet_count"],
                    like_count=tweet_data["like_count"],
                    reply_count=tweet_data["reply_count"],
                    match_id=match.id
                )
                db.add(tweet)
                
                # Analyse de sentiment simple
                positive_words = ["gagner", "win", "victoire", "champion", "excellent", "super"]
                negative_words = ["perdre", "perdu", "mauvais", "nul", "faible"]
                
                text_lower = tweet_data["text"].lower()
                pos_count = sum(1 for word in positive_words if word in text_lower)
                neg_count = sum(1 for word in negative_words if word in text_lower)
                
                if pos_count > neg_count:
                    sentiment = "positive"
                elif neg_count > pos_count:
                    sentiment = "negative"
                else:
                    sentiment = "neutral"
                
                tweet_sentiments.append({
                    "tweet_id": tweet_data["tweet_id"],
                    "sentiment": sentiment,
                    "positive_score": pos_count * 0.5,
                    "negative_score": neg_count * 0.5,
                    "neutral_score": 1 - (pos_count + neg_count) * 0.5,
                    "compound_score": (pos_count - neg_count) * 0.5
                })
            
            logger.info(f"   ✅ {len(tweet_sentiments)} tweets analysés")
            
            # Créer les posts Reddit
            reddit_sentiments = []
            for post_data in mock_reddit_posts:
                post = RedditPost(
                    post_id=post_data["post_id"],
                    title=post_data["title"],
                    text=post_data["text"],
                    author=post_data["author"],
                    created_at=post_data["created_at"],
                    upvote_count=post_data["upvote_count"],
                    downvote_count=post_data["downvote_count"],
                    match_id=match.id
                )
                db.add(post)
                
                # Analyse de sentiment simple
                text_lower = post_data["text"].lower()
                pos_count = sum(1 for word in ["win", "gagner"] if word in text_lower)
                neg_count = sum(1 for word in ["lose", "perdre"] if word in text_lower)
                
                if pos_count > neg_count:
                    sentiment = "positive"
                elif neg_count > pos_count:
                    sentiment = "negative"
                else:
                    sentiment = "neutral"
                
                reddit_sentiments.append({
                    "post_id": post_data["post_id"],
                    "sentiment": sentiment,
                    "positive_score": pos_count * 0.3,
                    "negative_score": neg_count * 0.3,
                    "neutral_score": 1 - (pos_count + neg_count) * 0.3,
                    "compound_score": (pos_count - neg_count) * 0.3
                })
            
            logger.info(f"   ✅ {len(reddit_sentiments)} posts Reddit analysés")
            
            db.commit()
            
            # Calculer l'énergie collective
            logger.info("⚡ Calcul de l'énergie collective...")
            logger.info("   📊 Formule: (Positif - Négatif) × Volume × Viralité")
            logger.info("   🎯 Pondération: Twitter 60%, Reddit 25%, RSS 15%")
            
            # Données d'énergie
            energy_data = {
                "match_id": match.id,
                "team_id": 0,  # home team
                "twitter_sentiments": tweet_sentiments,
                "reddit_sentiments": reddit_sentiments,
                "rss_sentiments": [],
                "tweets_with_timestamps": [
                    {"tweet_id": t["tweet_id"], "created_at": datetime.now()} 
                    for t in tweet_sentiments[:5]  # 5 tweets les plus récents
                ]
            }
            
            # Calculer le score d'énergie
            energy_result = calculate_energy_score(
                match_id=match.id,
                team_id=0,
                twitter_sentiments=tweet_sentiments,
                reddit_sentiments=reddit_sentiments,
                rss_sentiments=[],
                tweets_with_timestamps=energy_data["tweets_with_timestamps"]
            )
            
            logger.info(f"   ⚡ Score d'énergie équipe domicile: {energy_result['score']:.2f}")
            logger.info(f"   📊 Confiance: {energy_result['confidence']:.1f}%")
            
            # Répéter pour l'équipe visiteur
            energy_data_away = energy_data.copy()
            energy_data_away["team_id"] = 1
            
            mock_tweets_away = [
                {
                    "tweet_id": f"tweet_away_{match.id}_{i}",
                    "text": f"Allez {match.away_team} ! On va gagner ce match ! #football #{match.away_team.replace(' ', '')}",
                    "author": f"fan_{match.away_team.lower()}",
                    "created_at": datetime.now(),
                    "retweet_count": 8 + i,
                    "like_count": 15 + i,
                    "reply_count": 4 + i
                }
                for i in range(8)
            ]
            
            tweet_sentiments_away = []
            for tweet_data in mock_tweets_away:
                text_lower = tweet_data["text"].lower()
                pos_count = sum(1 for word in ["gagner", "win", "victoire"] if word in text_lower)
                neg_count = sum(1 for word in ["perdre", "perdu", "mauvais"] if word in text_lower)
                
                if pos_count > neg_count:
                    sentiment = "positive"
                elif neg_count > pos_count:
                    sentiment = "negative"
                else:
                    sentiment = "neutral"
                
                tweet_sentiments_away.append({
                    "tweet_id": tweet_data["tweet_id"],
                    "sentiment": sentiment,
                    "positive_score": pos_count * 0.5,
                    "negative_score": neg_count * 0.5,
                    "neutral_score": 1 - (pos_count + neg_count) * 0.5,
                    "compound_score": (pos_count - neg_count) * 0.5
                })
            
            energy_data_away["twitter_sentiments"] = tweet_sentiments_away
            
            mock_reddit_posts_away = [
                {
                    "post_id": f"reddit_away_{match.id}_{i}",
                    "title": f"{match.away_team} vs {match.home_team} - Match Preview",
                    "text": f"Prediction: {match.away_team} will win 3-2",
                    "author": f"u/redditor_away_{i}",
                    "created_at": datetime.now(),
                    "upvote_count": 12 + i,
                    "downvote_count": 3
                }
                for i in range(6)
            ]
            
            reddit_sentiments_away = []
            for post_data in mock_reddit_posts_away:
                text_lower = post_data["text"].lower()
                pos_count = sum(1 for word in ["win", "gagner"] if word in text_lower)
                neg_count = sum(1 for word in ["lose", "perdre"] if word in text_lower)
                
                if pos_count > neg_count:
                    sentiment = "positive"
                elif neg_count > pos_count:
                    sentiment = "negative"
                else:
                    sentiment = "neutral"
                
                reddit_sentiments_away.append({
                    "post_id": post_data["post_id"],
                    "sentiment": sentiment,
                    "positive_score": pos_count * 0.3,
                    "negative_score": neg_count * 0.3,
                    "neutral_score": 1 - (pos_count + neg_count) * 0.3,
                    "compound_score": (pos_count - neg_count) * 0.3
                })
            
            energy_data_away["reddit_sentiments"] = reddit_sentiments_away
            energy_data_away["tweets_with_timestamps"] = [
                {"tweet_id": t["tweet_id"], "created_at": datetime.now()} 
                for t in tweet_sentiments_away[:5]
            ]
            
            energy_result_away = calculate_energy_score(
                match_id=match.id,
                team_id=1,
                twitter_sentiments=tweet_sentiments_away,
                reddit_sentiments=reddit_sentiments_away,
                rss_sentiments=[],
                tweets_with_timestamps=energy_data_away["tweets_with_timestamps"]
            )
            
            logger.info(f"   ⚡ Score d'énergie équipe visiteur: {energy_result_away['score']:.2f}")
            logger.info(f"   📊 Confiance: {energy_result_away['confidence']:.1f}%")
            
            # Générer une prédiction
            logger.info("🎯 Génération de la prédiction...")
            
            home_energy = energy_result['score']
            away_energy = energy_result_away['score']
            
            # Service de prédiction
            prediction_service = PredictionService(db)
            prediction = prediction_service.create_prediction_for_match(
                match_id=match.id,
                home_energy=home_energy,
                away_energy=away_energy,
                energy_score_label="high" if home_energy > 50 else "medium"
            )
            
            logger.info(f"   🏆 Vainqueur prédit: {prediction.predicted_winner}")
            logger.info(f"   📊 Confidence: {prediction.confidence}")
            logger.info(f"   ✅ Prédiction créée avec succès !")
            
            logger.info("="*50)
        
        logger.info(f"\n✅ Pipeline complet terminé : {len(matches)} prédictions générées")
        
        # Résumé
        print("\n" + "="*70)
        print("🎊 RÉSUMÉ DU PIPELINE")
        print("="*70)
        print(f"📊 Matchs créés: {len(matches)}")
        print(f"🐦 Tweets analysés: {len(matches) * 18}")  # ~10 tweets home + ~8 tweets away
        print(f"📝 Posts Reddit analysés: {len(matches) * 11}")  # ~5 posts home + ~6 posts away
        print(f"⚡ Scores d'énergie calculés: {len(matches) * 2}")  # 2 équipes par match
        print(f"🎯 Prédictions générées: {len(matches)}")
        print("="*70 + "\n")
        print("🌐 API disponible sur: http://127.0.0.1:8000/docs")
        print("📊 Dashboard disponible sur: http://localhost:3000")
        print("\n📝 Prochaine étape:")
        print("   1. Accédez à http://localhost:3000/dashboard")
        print("   2. Connectez-vous avec votre compte utilisateur")
        print("   3. Voyez les prédictions dans le dashboard !")
        print("\n")
        
    except Exception as e:
        logger.error(f"❌ Erreur lors du pipeline: {e}")
        db.rollback()
    finally:
        db.close()


def print_menu():
    """Affiche le menu principal."""
    print("\n" + "="*70)
    print("🚀 SYSTÈME CHARTBASTAN - MENU PRINCIPAL")
    print("="*70)
    print("\n📋 OPTIONS DISPONIBLES:")
    print("\n1️⃣  Initialiser la base de données avec des matchs de test")
    print("2️⃣  Simuler le pipeline complet (scraping → analyse → énergie → prédictions)")
    print("3️⃣  Vérifier la connexion RabbitMQ")
    print("4️⃣  Lancer le serveur FastAPI uniquement")
    print("0️⃣  Tout lancer (matchs + pipeline + API)")
    print("\n📝 CONFIGURATION:")
    print("   - Variables d'environnement dans backend/.env")
    print("   - RabbitMQ doit être lancé avec Docker avant d'utiliser les queues")
    print("   - API externe (Twitter/Reddit) optionnelle pour le scraping réel")
    print("\n🚀 DOCKER RABBITMQ (si nécessaire):")
    print("   docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management")
    print("\n" + "="*70 + "\n")


def main():
    """Point d'entrée principal."""
    
    print_menu()
    
    try:
        choice = input("\n👉 Choisissez une option (0-4): ").strip()
        
        if choice == "1":
            # Créer des matchs de test
            create_test_matches()
            
        elif choice == "2":
            # Simuler le pipeline complet
            simulate_full_pipeline()
            
        elif choice == "3":
            # Vérifier RabbitMQ
            if check_rabbitmq_status():
                print("\n✅ RabbitMQ est opérationnel !\n")
            else:
                print("\n❌ RabbitMQ n'est pas accessible. Veuillez le démarrer.\n")
            
        elif choice == "4":
            # Lancer le serveur FastAPI
            print("\n🚀 Démarrage du serveur FastAPI...")
            print("📊 Utilisez plutôt: uvicorn app.app_new:app --host 127.0.0.1 --port 8000")
            
        elif choice == "0":
            # Tout lancer
            print("\n🚀 Lancement complet du système...\n")
            check_rabbitmq_status()
            print("\n" + "-"*70)
            print("Étape 1/3: Création des matchs de test")
            create_test_matches()
            print("\n" + "-"*70)
            print("Étape 2/3: Simulation du pipeline complet")
            simulate_full_pipeline()
            print("\n" + "-"*70)
            print("Étape 3/3: Démarrage du serveur FastAPI")
            print("🌐 Serveur prêt sur: http://127.0.0.1:8000")
            print("📖 Documentation: http://127.0.0.1:8000/docs")
            print("\n✅ Système complet démarré !")
            print("📊 Accédez au dashboard: http://localhost:3000/dashboard")
            print("\n💡 Pour arrêter: Press Ctrl+C")
            print("-"*70 + "\n")
            
            # Attendre que l'utilisateur appuie
            input("\n👉 Appuyez sur Enter pour continuer...")
            
        else:
            print("\n❌ Option invalide. Veuillez choisir entre 0 et 4.")
            
    except KeyboardInterrupt:
        print("\n\n⏹️ Interruption par l'utilisateur")
        print("👋 Au revoir !\n")
    except Exception as e:
        logger.error(f"❌ Erreur: {e}")


if __name__ == "__main__":
    main()
