"""
Core Routes - Authentification
GMAO Collège
"""
from flask import Blueprint, render_template, redirect, url_for, request, flash
from flask_login import login_user, logout_user, login_required, current_user
from ...extensions import db
from ..models.user import User
from ..forms import LoginForm, UserForm, PasswordForm
from ...constants import ROLES
from ..models.rbac import Role
from ..services.rbac import replace_user_roles
from ..authorization import has_permission

auth_bp = Blueprint('auth', __name__)


@auth_bp.route('/login', methods=['GET', 'POST'])
def login():
    """Page de connexion."""
    if current_user.is_authenticated:
        return redirect(url_for('dashboard.index'))
    
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user and user.check_password(form.password.data):
            if not user.is_active:
                flash("Votre compte est désactivé.", "danger")
                return render_template("auth/login.html", form=form)
            login_user(user)
            flash(f"Bienvenue, {user.username} !", "success")
            next_page = request.args.get('next', '')
            if not next_page.startswith('/') or next_page.startswith('//'):
                next_page = ''
            return redirect(next_page or url_for('dashboard.index'))
        flash("Nom d'utilisateur ou mot de passe incorrect.", "danger")
    
    return render_template('auth/login.html', form=form)


@auth_bp.route('/logout')
@login_required
def logout():
    """Déconnexion."""
    logout_user()
    flash("Vous avez été déconnecté.", "info")
    return redirect(url_for('auth.login'))


@auth_bp.route('/users')
@login_required
def list_users():
    """Liste des utilisateurs."""
    if not has_permission('user.view', current_user):
        flash("Accès réservé aux administrateurs.", "danger")
        return redirect(url_for('dashboard.index'))
    
    users = User.query.order_by(User.full_name).all()
    return render_template('auth/users.html', users=users)


@auth_bp.route('/users/new', methods=['GET', 'POST'])
@login_required
def create_user():
    """Créer un utilisateur."""
    if not has_permission('user.create', current_user):
        flash("Accès réservé aux administrateurs.", "danger")
        return redirect(url_for('dashboard.index'))
    
    form = UserForm()
    if form.validate_on_submit():
        selected_role_slugs = request.form.getlist('role_ids') or ([form.role.data] if form.role.data else [])
        user = User(
            username=form.username.data,
            email=form.email.data,
            full_name=form.full_name.data,
            role=form.role.data,
            is_active=form.is_active.data,
        )
        if not form.password.data:
            form.password.errors.append("Un mot de passe initial est obligatoire.")
            return render_template('auth/user_form.html', form=form, title="Nouvel utilisateur"), 400
        user.set_password(form.password.data)
        
        db.session.add(user)
        db.session.flush()
        selected_roles = Role.query.filter(Role.slug.in_(selected_role_slugs), Role.is_active.is_(True)).all() if selected_role_slugs else []
        replace_user_roles(user, [role.id for role in selected_roles], assigned_by=current_user)
        db.session.commit()
        flash(f"Utilisateur {user.full_name} créé.", "success")
        return redirect(url_for('auth.list_users'))
    
    return render_template('auth/user_form.html', form=form, title="Nouvel utilisateur", roles_list=Role.query.filter_by(is_active=True).order_by(Role.name).all())


@auth_bp.route('/profile')
@login_required
def profile():
    """Profil utilisateur."""
    return render_template('auth/profile.html', user=current_user)


@auth_bp.route('/users/<int:id>/edit', methods=['GET', 'POST'])
@login_required
def edit_user(id):
    """Modifier un utilisateur."""
    if not has_permission('user.edit', current_user):
        flash("Accès réservé aux administrateurs.", "danger")
        return redirect(url_for('dashboard.index'))
    
    user = User.query.get_or_404(id)
    form = UserForm(obj=user)
    
    if form.validate_on_submit():
        selected_role_slugs = request.form.getlist('role_ids') or ([form.role.data] if form.role.data else [])
        user.username = form.username.data
        user.email = form.email.data
        user.full_name = form.full_name.data
        user.is_active = form.is_active.data
        
        if form.password.data:
            user.set_password(form.password.data)
        selected_roles = Role.query.filter(Role.slug.in_(selected_role_slugs), Role.is_active.is_(True)).all() if selected_role_slugs else []
        replace_user_roles(user, [role.id for role in selected_roles], assigned_by=current_user)
        db.session.commit()
        flash(f"Utilisateur {user.full_name} modifié.", "success")
        return redirect(url_for('auth.list_users'))
    
    return render_template('auth/user_form.html', form=form, title="Modifier l'utilisateur", roles_list=Role.query.filter_by(is_active=True).order_by(Role.name).all())


@auth_bp.route('/change-password', methods=['GET', 'POST'])
@login_required
def change_own_password():
    """Changement de mot de passe."""
    form = PasswordForm()
    
    if form.validate_on_submit():
        if not current_user.check_password(form.current_password.data):
            flash("Mot de passe actuel incorrect.", "danger")
        else:
            current_user.set_password(form.new_password.data)
            db.session.commit()
            flash("Mot de passe modifié avec succès.", "success")
            return redirect(url_for('dashboard.index'))
    
    return render_template('auth/change_own_password.html', form=form)


@auth_bp.route('/users/<int:id>/delete', methods=['POST'])
@login_required
def delete_user(id):
    """Supprimer un utilisateur."""
    if not has_permission('user.delete', current_user):
        flash("Accès réservé aux administrateurs.", "danger")
        return redirect(url_for('dashboard.index'))
    
    user = User.query.get_or_404(id)
    if user.id == current_user.id:
        flash("Vous ne pouvez pas supprimer votre propre compte.", "danger")
    else:
        db.session.delete(user)
        db.session.commit()
        flash(f"Utilisateur {user.username} supprimé.", "success")
    
    return redirect(url_for('auth.list_users'))


@auth_bp.route('/users/<int:id>/password', methods=['GET', 'POST'])
@login_required
def change_user_password(id):
    """Changer le mot de passe d'un utilisateur (admin only)."""
    if not has_permission('user.edit', current_user):
        flash("Accès réservé aux administrateurs.", "danger")
        return redirect(url_for('dashboard.index'))
    
    user = User.query.get_or_404(id)
    
    if request.method == 'POST':
        new_password = request.form.get('new_password')
        confirm_password = request.form.get('confirm_password')
        
        if not new_password:
            flash("Le mot de passe est requis.", "danger")
        elif new_password != confirm_password:
            flash("Les mots de passe ne correspondent pas.", "danger")
        elif len(new_password) < 12:
            flash("Le mot de passe doit contenir au moins 12 caractères.", "danger")
        else:
            user.set_password(new_password)
            db.session.commit()
            flash(f"Mot de passe de {user.username} modifié.", "success")
            return redirect(url_for('auth.list_users'))
    
    return render_template('auth/change_user_password.html', user=user)
