"""Authentication blueprint - login, logout, profile."""
from functools import wraps

from flask import Blueprint, abort, flash, jsonify, redirect, render_template, request, session, url_for
from flask_babel import gettext as _

from services.api_client import api_client

auth_bp = Blueprint("auth", __name__, url_prefix="/auth")


def login_required(f):
    """Decorator to require login for protected routes."""
    @wraps(f)
    def decorated(*args, **kwargs):
        if not session.get("api_key"):
            flash(_("Effettua il login per continuare"), "warning")
            return redirect(url_for("auth.login"))
        return f(*args, **kwargs)
    return decorated


def role_required(*roles):
    """Decorator to require one of the specified roles.

    Usage:
        @role_required("MeasurementTec", "Metrologist")
        def my_view(): ...
    """
    def decorator(f):
        @wraps(f)
        def decorated(*args, **kwargs):
            user = session.get("user", {})
            user_roles = user.get("roles", [])
            if not any(r in user_roles for r in roles):
                abort(403)
            return f(*args, **kwargs)
        return decorated
    return decorator


def _post_login_landing():
    """Pick the landing endpoint based on the logged-in user's roles.

    A Maker-only user must not be bounced to /measure (MeasurementTec-only),
    which would raise a 403 right after login. Order of preference follows the
    primary operator flow first, then editing, analysis, admin.
    """
    user = session.get("user", {})
    roles = user.get("roles", [])
    if "MeasurementTec" in roles:
        return url_for("measure.select_recipe")
    if "Maker" in roles:
        return url_for("maker.recipe_list")
    if "Metrologist" in roles:
        return url_for("statistics.dashboard")
    if user.get("is_admin"):
        return url_for("admin.user_list")
    return url_for("auth.profile")


@auth_bp.route("/login", methods=["GET", "POST"])
def login():
    """Login page and form handler."""
    # Se già loggato, redirect alla home in base al ruolo
    if session.get("api_key"):
        return redirect(_post_login_landing())

    if request.method == "POST":
        username = request.form.get("username", "").strip()
        password = request.form.get("password", "")

        if not username or not password:
            flash(_("Inserisci username e password"), "error")
            return render_template("auth/login.html")

        try:
            response = api_client.post("/api/auth/login", data={"username": username, "password": password})

            if response.get("error"):
                flash(response.get("detail", _("Credenziali non valide")), "error")
                return render_template("auth/login.html")

            # Salva in sessione
            session["api_key"] = response["api_key"]
            session["user"] = response["user"]
            session["user_id"] = response["user"]["id"]

            # Applica preferenze utente
            user = response["user"]
            if user.get("language_pref"):
                session["language"] = user["language_pref"]
            if user.get("theme_pref"):
                session["theme"] = user["theme_pref"]

            # Carica impostazioni di sistema
            settings_resp = api_client.get("/api/settings")
            if not settings_resp.get("error"):
                logo_path = settings_resp.get("company_logo_path")
                if logo_path:
                    session["company_logo"] = logo_path
                auto_logout = settings_resp.get("auto_logout_minutes")
                if auto_logout:
                    try:
                        session["auto_logout_minutes"] = int(auto_logout)
                    except (ValueError, TypeError):
                        pass

            flash(_("Benvenuto, %(name)s!", name=user.get("display_name", username)), "success")

            # Redirect dopo login (in base al ruolo)
            return redirect(_post_login_landing())

        except Exception as e:
            flash(_("Errore di connessione al server: %(error)s", error=str(e)), "error")
            return render_template("auth/login.html")

    return render_template("auth/login.html")


@auth_bp.route("/logout", methods=["GET", "POST"])
def logout():
    """Clear session and redirect to login."""
    # Invalida il token sul server
    if session.get("api_key"):
        try:
            api_client.post("/api/auth/logout")
        except Exception:
            pass  # Ignora errori durante logout

    session.clear()
    flash(_("Logout effettuato"), "info")
    return redirect(url_for("auth.login"))


@auth_bp.route("/set-theme", methods=["POST"])
@login_required
def set_theme():
    """Persist the user's theme toggle (light/dark) to session and profile.

    Called via AJAX from the navbar theme switch so the choice survives
    navigation and matches on the next login. Best-effort on the API side:
    the session is updated regardless so the current browsing stays correct.
    """
    theme = (request.get_json(silent=True) or {}).get("theme", "")
    if theme not in ("light", "dark"):
        return jsonify({"error": True, "detail": "invalid theme"}), 400

    session["theme"] = theme
    try:
        api_client.put("/api/auth/me", data={"theme_pref": theme})
    except Exception:
        pass  # Non-fatal: session theme is already updated for this session.
    return jsonify({"ok": True, "theme": theme})


@auth_bp.route("/profile", methods=["GET", "POST"])
@login_required
def profile():
    """User profile page - change display name, language, theme."""
    if request.method == "POST":
        display_name = request.form.get("display_name", "").strip()
        language_pref = request.form.get("language_pref", "").strip()
        theme_pref = request.form.get("theme_pref", "").strip()

        try:
            data = {}
            if display_name:
                data["display_name"] = display_name
            if language_pref:
                data["language_pref"] = language_pref
            if theme_pref:
                data["theme_pref"] = theme_pref

            response = api_client.put("/api/auth/me", data=data)

            if response.get("error"):
                flash(response.get("detail", _("Errore durante l'aggiornamento del profilo")), "error")
            else:
                # Aggiorna sessione
                session["user"] = response
                if language_pref:
                    session["language"] = language_pref
                if theme_pref:
                    session["theme"] = theme_pref

                flash(_("Profilo aggiornato con successo"), "success")
                return redirect(url_for("auth.profile"))

        except Exception as e:
            flash(_("Errore di connessione al server: %(error)s", error=str(e)), "error")

    # GET - carica dati profilo
    user_data = api_client.get("/api/auth/me")
    if user_data.get("error"):
        flash(_("Errore nel caricamento del profilo: %(error)s", error=user_data.get("detail", "")), "error")
        user_data = session.get("user", {})
    else:
        session["user"] = user_data

    return render_template("auth/profile.html", user=user_data)
