#!/usr/bin/env python
"""
Script tout-en-un pour tester le site GMPL en local, avec l'administration fonctionnelle.
Une seule commande pour tout installer, tout configurer et tout lancer.
"""
import os
import sys
import subprocess
import sqlite3
import shutil
import time
from pathlib import Path
from werkzeug.security import generate_password_hash

# Couleurs pour les messages console
GREEN = '\033[92m'
YELLOW = '\033[93m'
RED = '\033[91m'
BOLD = '\033[1m'
END = '\033[0m'

# Fonction pour afficher un titre
def print_title(title):
    print(f"\n{BOLD}{'=' * 60}{END}")
    print(f"{BOLD}{title.center(60)}{END}")
    print(f"{BOLD}{'=' * 60}{END}\n")

# Fonction pour afficher une étape
def print_step(step):
    print(f"\n{BOLD}[{step}]{END}")

# Créer les dossiers nécessaires
def create_folders():
    print_step("Création des dossiers nécessaires")
    os.makedirs('static/uploads/products', exist_ok=True)
    os.makedirs('static/uploads/services', exist_ok=True)
    os.makedirs('instance', exist_ok=True)
    os.makedirs('temp', exist_ok=True)
    print(f"{GREEN}Dossiers créés avec succès.{END}")

# Installer les dépendances requises
def install_dependencies():
    print_step("Installation des dépendances")
    dependencies = [
        "flask", "flask-login", "flask-sqlalchemy", "flask-wtf", 
        "email-validator", "gunicorn", "python-dotenv", "psycopg2-binary"
    ]
    print(f"Installation de : {', '.join(dependencies)}")
    subprocess.run([sys.executable, "-m", "pip", "install"] + dependencies, stdout=subprocess.PIPE)
    print(f"{GREEN}Dépendances installées avec succès.{END}")

# Créer ou mettre à jour le fichier .env
def update_env_file():
    print_step("Configuration du fichier .env")
    env_content = """
# Configuration locale pour GMPL
FLASK_ENV=development
FLASK_DEBUG=1
SESSION_SECRET=gmpl_local_development_secret_key_very_secure_and_long_enough
DATABASE_URL=sqlite:///instance/gmpl.db
UPLOAD_FOLDER=static/uploads
MAX_CONTENT_LENGTH=8388608
IMAGE_CACHE_BUSTING=true
    """.strip()
    
    with open('.env', 'w') as f:
        f.write(env_content)
    print(f"{GREEN}Fichier .env créé/mis à jour avec succès.{END}")

# Configurer Flask-Login dans app.py
def configure_flask_login():
    print_step("Configuration de Flask-Login pour l'administration")
    
    app_file = Path('app.py')
    if not app_file.exists():
        print(f"{RED}Le fichier app.py n'existe pas!{END}")
        return False
    
    # Lire le contenu du fichier
    with open(app_file, 'r', encoding='utf-8') as f:
        content = f.read()
    
    # Sauvegarde du fichier original
    backup_file = 'temp/app.py.bak'
    os.makedirs(os.path.dirname(backup_file), exist_ok=True)
    shutil.copy2(app_file, backup_file)
    
    # Vérifier et ajouter les imports nécessaires
    if 'from flask_login import LoginManager' not in content:
        content = content.replace(
            'from flask_sqlalchemy import SQLAlchemy',
            'from flask_sqlalchemy import SQLAlchemy\nfrom flask_login import LoginManager'
        )
    
    # Vérifier et ajouter l'initialisation de LoginManager
    if 'login_manager = LoginManager()' not in content:
        content = content.replace(
            'db = SQLAlchemy(',
            'login_manager = LoginManager()\ndb = SQLAlchemy('
        )
    
    # Vérifier et ajouter login_manager.init_app
    if 'login_manager.init_app(' not in content:
        content = content.replace(
            'db.init_app(app)',
            'db.init_app(app)\n    login_manager.init_app(app)\n    login_manager.login_view = "admin.login"'
        )
    
    # Vérifier et ajouter load_user
    if '@login_manager.user_loader' not in content:
        load_user_function = """
@login_manager.user_loader
def load_user(user_id):
    from models import User
    return User.query.get(int(user_id))
"""
        
        if 'with app.app_context():' in content:
            content = content.replace(
                'with app.app_context():',
                f'{load_user_function}\nwith app.app_context():'
            )
        else:
            content += "\n" + load_user_function
    
    # Écrire les modifications
    with open(app_file, 'w', encoding='utf-8') as f:
        f.write(content)
    
    print(f"{GREEN}Flask-Login configuré avec succès dans app.py.{END}")
    return True

# Configurer UserMixin dans models.py
def configure_user_mixin():
    print_step("Configuration de UserMixin pour le modèle User")
    
    models_file = Path('models.py')
    if not models_file.exists():
        print(f"{RED}Le fichier models.py n'existe pas!{END}")
        return False
    
    # Lire le contenu du fichier
    with open(models_file, 'r', encoding='utf-8') as f:
        content = f.read()
    
    # Sauvegarde du fichier original
    backup_file = 'temp/models.py.bak'
    os.makedirs(os.path.dirname(backup_file), exist_ok=True)
    shutil.copy2(models_file, backup_file)
    
    # Vérifier et ajouter l'import de UserMixin
    if 'from flask_login import UserMixin' not in content:
        import_lines = content.split('\n', 10)  # Prendre les 10 premières lignes
        for i, line in enumerate(import_lines):
            if line.startswith('import ') or line.startswith('from '):
                import_lines.insert(i+1, 'from flask_login import UserMixin')
                break
        else:
            import_lines.insert(0, 'from flask_login import UserMixin')
        
        # Reconstruire le contenu
        content = '\n'.join(import_lines)
    
    # Vérifier et ajouter UserMixin à la classe User
    if 'class User(' in content and 'UserMixin' not in content.split('class User(')[1].split(')')[0]:
        content = content.replace(
            'class User(db.Model)',
            'class User(UserMixin, db.Model)'
        )
    
    # Écrire les modifications
    with open(models_file, 'w', encoding='utf-8') as f:
        f.write(content)
    
    print(f"{GREEN}UserMixin configuré avec succès dans models.py.{END}")
    return True

# Créer directement un compte administrateur
def create_admin_directly():
    print_step("Préparation de l'utilisateur administrateur")
    
    # Créer un fichier temporaire contenant le code pour créer l'admin
    admin_code = """
import os
import sys
from werkzeug.security import generate_password_hash

# Ajouter le répertoire courant au PYTHONPATH
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

# Importer notre application et notre modèle User
try:
    from app import app, db
    from models import User
    
    with app.app_context():
        # Vérifier si l'admin existe déjà
        admin = User.query.filter_by(username='admin').first()
        
        if admin:
            print(f"L'utilisateur admin existe déjà (ID: {admin.id}). Mise à jour du mot de passe...")
            admin.password_hash = generate_password_hash('admin123456')
            admin.role = 'admin'
        else:
            print("Création d'un nouvel utilisateur admin...")
            admin = User(username='admin', email='admin@example.com', role='admin')
            admin.password_hash = generate_password_hash('admin123456')
            db.session.add(admin)
        
        db.session.commit()
        print("\nCompte administrateur configuré:\n- Nom d'utilisateur: admin\n- Mot de passe: admin123456\n")
        sys.exit(0)

except Exception as e:
    print(f"Erreur lors de la création de l'administrateur: {e}")
    sys.exit(1)
"""
    
    create_admin_path = 'temp/create_admin_direct.py'
    with open(create_admin_path, 'w') as f:
        f.write(admin_code)
    
    print(f"{YELLOW}Le compte administrateur sera créé automatiquement au démarrage du serveur.{END}")
    return create_admin_path

# Démarrer le serveur
def start_server(admin_script_path):
    print_title("DÉMARRAGE DU SERVEUR")
    print(f"{GREEN}Le site GMPL sera accessible à l'adresse: {BOLD}http://localhost:5000{END}")
    print(f"{GREEN}L'administration sera accessible à: {BOLD}http://localhost:5000/admin{END}")
    print(f"{GREEN}Identifiants admin: {BOLD}admin / admin123456{END}")
    print(f"\n{YELLOW}Pour arrêter le serveur, appuyez sur {BOLD}Ctrl+C{END}")
    print(f"\n{BOLD}Démarrage du serveur...{END}\n")
    
    # Définir les variables d'environnement
    os.environ["FLASK_ENV"] = "development"
    os.environ["FLASK_DEBUG"] = "1"
    
    # Démarrer le serveur - Utiliser le module importable pour garantir la création de la base
    from app import app
    
    # Créer rapidement le compte admin une fois que le serveur est lancé
    import threading
    import time
    
    def delayed_admin_creation():
        time.sleep(2)  # Attendre que le serveur soit bien démarré
        try:
            subprocess.run([sys.executable, admin_script_path], stdout=subprocess.PIPE)
            print(f"\n{GREEN}==== Compte administrateur créé/mis à jour avec succès ===={END}")
            print(f"{GREEN}Vous pouvez vous connecter à l'administration avec:{END}")
            print(f"{GREEN}- Nom d'utilisateur: {BOLD}admin{END}")
            print(f"{GREEN}- Mot de passe: {BOLD}admin123456{END}")
        except Exception as e:
            print(f"{RED}Erreur lors de la création de l'administrateur: {e}{END}")
    
    admin_thread = threading.Thread(target=delayed_admin_creation)
    admin_thread.daemon = True
    admin_thread.start()
    
    # Démarrer l'application
    app.run(host='0.0.0.0', port=5000, debug=True)

def main():
    # Afficher le titre
    print_title("DÉMARRAGE SIMPLE DU SITE GMPL")
    
    # 1. Créer les dossiers nécessaires
    create_folders()
    
    # 2. Installer les dépendances
    install_dependencies()
    
    # 3. Configurer le fichier .env
    update_env_file()
    
    # 4. Configurer Flask-Login pour l'administration
    configure_flask_login()
    
    # 5. Configurer UserMixin dans le modèle User
    configure_user_mixin()
    
    # 6. Préparer la création du compte administrateur
    admin_script_path = create_admin_directly()
    
    # 7. Démarrer le serveur
    start_server(admin_script_path)

if __name__ == "__main__":
    main()
