"""Routes: admin roles"""
from datetime import datetime
from flask import abort, flash, redirect, render_template, request, session, url_for

from nexora.core import app
from nexora.database.connection import execute, query
from nexora.security.permissions import (
    PERMISSION_KEYS,
    PERMISSION_LABELS,
    PERMISSION_SECTIONS,
    admin_required,
    forbidden_response,
    has_permission,
    log_role_audit,
    permission_required,
)


@app.route("/admin/roles", methods=["GET", "POST"])
@admin_required
@permission_required("roles_view")
def admin_roles():
    all_users = query("SELECT id, username, full_name, role_id FROM admin_users ORDER BY username")
    if request.method == "POST":
        if not has_permission("roles_create"):
            return forbidden_response()
        name = request.form.get("name", "").strip()
        selected = [key for key in request.form.getlist("permissions") if key in PERMISSION_KEYS]
        assign_user_ids = [int(uid) for uid in request.form.getlist("assign_users") if uid.isdigit()]
        if not name:
            flash("Role name is required.", "danger")
        elif query("SELECT id FROM roles WHERE name = ?", (name,), one=True):
            flash("That role already exists.", "danger")
        else:
            role_id = execute("INSERT INTO roles (name, description, created_at) VALUES (?, ?, ?)", (name, request.form.get("description", "").strip(), datetime.now().isoformat(timespec="seconds")))
            for key in selected:
                execute("INSERT INTO role_permissions (role_id, permission_key) VALUES (?, ?)", (role_id, key))
            for uid in assign_user_ids:
                execute("UPDATE admin_users SET role_id = ? WHERE id = ?", (role_id, uid))
            log_role_audit("role_created", name, f"perms={len(selected)}, users={len(assign_user_ids)}")
            flash(f"Role created and {len(assign_user_ids)} user(s) assigned." if assign_user_ids else "Role created.", "success")
        return redirect(url_for("admin_roles"))
    roles = query("SELECT * FROM roles ORDER BY name")
    role_permissions = {role["id"]: {item["permission_key"] for item in query("SELECT permission_key FROM role_permissions WHERE role_id = ?", (role["id"],))} for role in roles}
    role_users = {}
    for role in roles:
        role_users[role["id"]] = query("SELECT id, username, full_name FROM admin_users WHERE role_id = ? ORDER BY username", (role["id"],))
    audit = query("SELECT * FROM role_audit_log ORDER BY id DESC LIMIT 30")
    return render_template("admin_roles.html", roles=roles, role_permissions=role_permissions, permission_sections=PERMISSION_SECTIONS, permission_labels=PERMISSION_LABELS, audit=audit, all_users=all_users, role_users=role_users)


@app.route("/admin/roles/<int:role_id>/permissions", methods=["POST"])
@admin_required
@permission_required("roles_update")
def update_role_permissions(role_id):
    role = query("SELECT name FROM roles WHERE id = ?", (role_id,), one=True)
    if not role:
        abort(404)
    selected = [key for key in request.form.getlist("permissions") if key in PERMISSION_KEYS]
    execute("DELETE FROM role_permissions WHERE role_id = ?", (role_id,))
    for key in selected:
        execute("INSERT INTO role_permissions (role_id, permission_key) VALUES (?, ?)", (role_id, key))
    log_role_audit("role_permissions_updated", role["name"], ",".join(selected))
    flash("Role permissions updated.", "success")
    return redirect(url_for("admin_roles"))


@app.route("/admin/roles/<int:role_id>/edit", methods=["POST"])
@admin_required
@permission_required("roles_update")
def edit_role(role_id):
    role = query("SELECT name FROM roles WHERE id = ?", (role_id,), one=True)
    if not role:
        abort(404)
    name = request.form.get("name", "").strip()
    description = request.form.get("description", "").strip()
    if not name:
        flash("Role name is required.", "danger")
        return redirect(url_for("admin_roles"))
    if query("SELECT id FROM roles WHERE name = ? AND id != ?", (name, role_id), one=True):
        flash("That role already exists.", "danger")
        return redirect(url_for("admin_roles"))
    execute("UPDATE roles SET name = ?, description = ? WHERE id = ?", (name, description, role_id))
    log_role_audit("role_updated", name, f"previous_name={role['name']}")
    flash("Role updated.", "success")
    return redirect(url_for("admin_roles"))


@app.route("/admin/roles/<int:role_id>/delete", methods=["POST"])
@admin_required
@permission_required("roles_delete")
def delete_role(role_id):
    role = query("SELECT name FROM roles WHERE id = ?", (role_id,), one=True)
    if not role:
        abort(404)
    if session.get("role_id") == role_id:
        flash("You cannot delete the role you are currently assigned to.", "danger")
        return redirect(url_for("admin_roles"))
    execute("UPDATE admin_users SET role_id = NULL WHERE role_id = ?", (role_id,))
    execute("DELETE FROM role_permissions WHERE role_id = ?", (role_id,))
    execute("DELETE FROM roles WHERE id = ?", (role_id,))
    log_role_audit("role_deleted", role["name"])
    flash(f'Role "{role["name"]}" deleted. Assigned staff now have no role.', "success")
    return redirect(url_for("admin_roles"))
