"""RBAC decorators for Flask route protection."""
from __future__ import annotations

import functools
from typing import Callable

from flask import jsonify, redirect, request, session, url_for


def login_required(f: Callable) -> Callable:
    """Redirect to login if user is not authenticated."""
    @functools.wraps(f)
    def wrapper(*args, **kwargs):
        if "user" not in session or session.get("user_type") not in ("authenticated", "guest"):
            if request.is_json or request.path.startswith("/api") or request.path.startswith("/admin/api"):
                return jsonify({"error": "Authentication required"}), 401
            return redirect(url_for("auth.login"))
        return f(*args, **kwargs)
    return wrapper


def require_permission(permission_name: str) -> Callable:
    """Decorator that checks a specific permission.

    Admin: always allowed.
    Manager: allowed for all non-admin_panel permissions.
    Employee: only if explicitly assigned.
    """
    def decorator(f: Callable) -> Callable:
        @functools.wraps(f)
        def wrapper(*args, **kwargs):
            user_email = session.get("user")
            if not user_email or session.get("user_type") not in ("authenticated",):
                if request.is_json or "/api" in request.path:
                    return jsonify({"error": "Authentication required"}), 401
                return redirect(url_for("auth.login"))

            from services.rbac_service import has_permission
            if not has_permission(user_email, permission_name):
                if request.is_json or "/api" in request.path:
                    return jsonify({"error": f"Permission denied: {permission_name}"}), 403
                from flask import render_template
                return render_template("403.html", permission=permission_name), 403

            return f(*args, **kwargs)
        return wrapper
    return decorator


def require_role(*roles: str) -> Callable:
    """Decorator that checks user role (e.g. 'admin', 'manager')."""
    def decorator(f: Callable) -> Callable:
        @functools.wraps(f)
        def wrapper(*args, **kwargs):
            user_role = session.get("sales_role", "")
            if user_role not in roles:
                if request.is_json or "/api" in request.path:
                    return jsonify({"error": f"Requires role: {', '.join(roles)}"}), 403
                from flask import render_template
                return render_template("403.html", permission=f"role:{','.join(roles)}"), 403
            return f(*args, **kwargs)
        return wrapper
    return decorator


def admin_required(f: Callable) -> Callable:
    """Shorthand for @require_role('admin')."""
    @functools.wraps(f)
    def wrapper(*args, **kwargs):
        if session.get("sales_role") != "admin":
            if request.is_json or "/api" in request.path:
                return jsonify({"error": "Admin access required"}), 403
            from flask import render_template
            return render_template("403.html", permission="admin"), 403
        return f(*args, **kwargs)
    return wrapper
