"""CSRF double-submit token generation and validation."""
import hmac
import secrets
from flask import abort, flash, redirect, request, session, url_for

from nexora.config import logger
from nexora.core import app
from nexora.utils.helpers import wants_json_response


# â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
# CSRF protection (double-submit cookie pattern)
# â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
def generate_csrf_token():
    """Generate and store a CSRF token in the session."""
    if "_csrf_token" not in session:
        session["_csrf_token"] = secrets.token_hex(32)
    return session["_csrf_token"]


def validate_csrf_token():
    """Validate the CSRF token from form data or header against the session."""
    token = request.form.get("csrf_token") or request.headers.get("X-CSRF-Token", "")
    expected = session.get("_csrf_token", "")
    if not token or not expected:
        return False
    return hmac.compare_digest(token, expected)


def csrf_protect():
    """Abort with 403 if CSRF token is missing/invalid on state-changing requests."""
    if app.config.get("TESTING"):
        return
    if request.method in ("POST", "PUT", "DELETE", "PATCH"):
        if not validate_csrf_token():
            logger.warning("CSRF token missing/invalid from %s %s", request.remote_addr, request.path)
            if not request.path.startswith("/admin") and not wants_json_response():
                flash("Your page session expired. Please submit the form again.", "warning")
                return redirect(request.referrer or url_for("register"))
            abort(403)


# Make csrf_token available in all templates
app.jinja_env.globals["csrf_token"] = generate_csrf_token
