from flask import Blueprint, request, redirect, session, url_for, current_app, flash
from flask_login import login_user, current_user, logout_user
import requests
import xmltodict
from urllib.parse import urlencode
from functools import wraps
from extensions import db
from models import User
import os
import urllib.request

cas_bp = Blueprint("cas", __name__)

# Configuration CAS de l'Université de Poitiers
CAS_SERVER = "https://auth.univ-poitiers.fr"
CAS_LOGIN_ROUTE = "/cas/login"
CAS_LOGOUT_ROUTE = "/cas/logout"
CAS_VALIDATE_ROUTE = "/cas/serviceValidate"
APP_BASE_URL = 'https://10.15.61.100'

# Configuration du proxy pour les requêtes HTTP/HTTPS
os.environ['HTTP_PROXY'] = 'http://proxy.iutn.univ-poitiers.fr:3128'
os.environ['HTTPS_PROXY'] = 'http://proxy.iutn.univ-poitiers.fr:3128'
os.environ['NO_PROXY'] = 'localhost,127.0.0.1,10.15.61.100,knowledge.local,auth.univ-poitiers.fr'

# Définition des proxies pour les requêtes
PROXIES = {
    'http': 'http://proxy.iutn.univ-poitiers.fr:3128',
    'https': 'http://proxy.iutn.univ-poitiers.fr:3128'
}

def admin_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if not current_user.is_authenticated or current_user.role != "admin":
            flash("Accès réservé aux administrateurs.", "error")
            return redirect(url_for('main.document_search'))
        return f(*args, **kwargs)
    return decorated_function

def get_service_url():
    """Génère l'URL de callback pour le CAS."""
    return url_for("cas.login", _external=True, _scheme="https").replace(":443", "")

@cas_bp.route("/login")
def login():
    ticket = request.args.get("ticket")
    service_url = get_service_url()

    # Étape 1 : Redirection vers le CAS si aucun ticket
    if not ticket:
        login_url = f"{CAS_SERVER}{CAS_LOGIN_ROUTE}?service={service_url}"
        current_app.logger.info(f"Redirection vers le CAS : {login_url}")
        return redirect(login_url)

    # Étape 2 : Validation du ticket CAS
    validate_url = f"{CAS_SERVER}{CAS_VALIDATE_ROUTE}?{urlencode({'ticket': ticket, 'service': service_url})}"
    try:
        current_app.logger.info(f"Validation CAS : {validate_url}")
        response = requests.get(validate_url, verify=True, proxies=PROXIES)
        response.raise_for_status()
        current_app.logger.info(f"Réponse CAS : {response.text}")

        # Parsing de la réponse XML
        data = xmltodict.parse(response.text)
        if "cas:serviceResponse" not in data or "cas:authenticationSuccess" not in data.get("cas:serviceResponse", {}):
            current_app.logger.warning("Échec de l'authentification CAS.")
            flash("Échec de l'authentification CAS.", "error")
            return redirect(url_for("main.index"))

        # Extraction des informations utilisateur
        user_cas = data["cas:serviceResponse"]["cas:authenticationSuccess"]["cas:user"]
        attributes = data["cas:serviceResponse"]["cas:authenticationSuccess"].get("cas:attributes", {})
        email = attributes.get("mail", f"{user_cas}@univ-poitiers.fr")

        # Initialisation de la session
        session.clear()
        session["username"] = user_cas
        session["email"] = email
        session["is_authenticated"] = True
        current_app.logger.info(f"Authentification CAS réussie : {user_cas}")

        # Détermination du rôle
        session["role"] = "user"
        session["is_admin"] = False
        admin_emails = ["neil.andre@univ-poitiers.fr"]
        if email in admin_emails:
            session["role"] = "admin"
            session["is_admin"] = True

        # Charge ou crée l'utilisateur en base de données
        with current_app.app_context():
            user = User.query.filter_by(username=user_cas).first()
            if not user:
                user = User(username=user_cas, email=email, role=session["role"])
                db.session.add(user)
                db.session.commit()
                current_app.logger.info(f"Nouvel utilisateur créé en base : {user_cas}")
            else:
                current_app.logger.info(f"Utilisateur existant : {user_cas}")

        # Connexion de l'utilisateur avec Flask-Login
        login_user(user)
        current_app.logger.info(f"Utilisateur connecté avec Flask-Login : {user_cas}")

        flash(f"Connecté en tant que {user_cas}", "success")
        return redirect(url_for("main.document_search"))

    except requests.exceptions.RequestException as e:
        current_app.logger.error(f"Erreur lors de la validation CAS : {e}")
        flash("Erreur d'authentification.", "error")
        return redirect(url_for("main.index"))

@cas_bp.route("/logout")
def logout():
    """Déconnexion du CAS."""
    current_app.logger.info(f"Déconnexion de l'utilisateur : {session.get('username')}")
    with current_app.app_context():
        session.clear()
        if current_user.is_authenticated:
            logout_user()
    logout_url = f"{CAS_SERVER}{CAS_LOGOUT_ROUTE}?service={url_for('main.index', _external=True, _scheme='https')}"
    current_app.logger.info(f"Déconnexion et redirection vers : {logout_url}")
    return redirect(logout_url)
