"""
app/routes/relacion.py – Gestión de relación usuarios ↔ sistemas.
Permite asignar/desasignar usuarios a un sistema (N:M).
"""
import logging
from flask import Blueprint, render_template, redirect, url_for, flash, request
from flask_login import login_required

from app import db
from app.models import Sistema, Usuario, UsuarioSistema
from app.forms  import RelacionForm
from app.utils.decorators import role_required

relacion_bp = Blueprint('relacion', __name__, url_prefix='/relacion')
logger       = logging.getLogger(__name__)


@relacion_bp.route('/')
@login_required
@role_required('Administrador')
def lista():
    """Muestra todos los sistemas con sus usuarios asignados."""
    sistemas = Sistema.query.order_by(Sistema.nombre).all()
    return render_template('relacion/list.html', sistemas=sistemas)


@relacion_bp.route('/asignar', methods=['GET', 'POST'])
@relacion_bp.route('/asignar/<int:sistema_id>', methods=['GET', 'POST'])
@login_required
@role_required('Administrador')
def asignar(sistema_id=None):
    """
    Formulario para asignar/desasignar usuarios a un sistema.
    """
    form = RelacionForm()
    sistemas_activos = Sistema.query.filter_by(activo=True).order_by(Sistema.nombre).all()
    form.sistema_id.choices  = [(s.id, s.nombre) for s in sistemas_activos]
    form.usuario_ids.choices = [
        (u.id, u.nombre_completo)
        for u in Usuario.query.filter_by(activo=True).order_by(Usuario.nombre_completo).all()
    ]

    sistema_sel = None
    asignados   = []

    if sistema_id:
        sistema_sel = Sistema.query.get_or_404(sistema_id)
        asignados   = [us.usuario_id for us in
                       UsuarioSistema.query.filter_by(sistema_id=sistema_id).all()]
        if request.method == 'GET':
            form.sistema_id.data  = sistema_id
            form.usuario_ids.data = asignados

    if form.validate_on_submit():
        sid         = form.sistema_id.data
        nuevos_ids  = set(form.usuario_ids.data)
        actuales    = {us.usuario_id: us
                       for us in UsuarioSistema.query.filter_by(sistema_id=sid).all()}

        # Agregar nuevos
        for uid in nuevos_ids - set(actuales.keys()):
            db.session.add(UsuarioSistema(usuario_id=uid, sistema_id=sid))

        # Eliminar los que ya no están
        for uid in set(actuales.keys()) - nuevos_ids:
            db.session.delete(actuales[uid])

        db.session.commit()
        logger.info('Relación actualizada para sistema_id=%s', sid)
        flash('Asignación guardada correctamente.', 'success')
        return redirect(url_for('relacion.lista'))

    return render_template(
        'relacion/form.html',
        form=form,
        sistema_sel=sistema_sel,
        asignados=asignados,
    )


@relacion_bp.route('/eliminar/<int:id>', methods=['POST'])
@login_required
@role_required('Administrador')
def eliminar(id):
    rel = UsuarioSistema.query.get_or_404(id)
    db.session.delete(rel)
    db.session.commit()
    flash('Relación eliminada.', 'success')
    return redirect(url_for('relacion.lista'))
