from functools import wraps

from django.conf import settings
from django.contrib.auth import get_user_model
from django.http import JsonResponse
from django.shortcuts import redirect
from django.urls import reverse

from .services.jwt_auth_service import JwtAuthError, decode_access_token


def get_token_from_request(request):
    authorization = request.headers.get("Authorization", "")

    if authorization.lower().startswith("bearer "):
        return authorization.split(" ", 1)[1].strip()

    return request.COOKIES.get(settings.JWT_COOKIE_NAME)


def get_user_from_token(token):
    if not token:
        raise JwtAuthError("Authentification requise.")

    payload = decode_access_token(token)
    user_id = payload.get("sub")

    if not user_id:
        raise JwtAuthError("Identifiant utilisateur absent du token.")

    user = get_user_model().objects.filter(pk=user_id, is_active=True).first()

    if user is None:
        raise JwtAuthError("Utilisateur introuvable ou inactif.")

    return user, payload


def authenticate_jwt_request(request):
    token = get_token_from_request(request)
    user, payload = get_user_from_token(token)
    request.user = user
    request.jwt_payload = payload
    return user


def is_api_request(request):
    if request.path.startswith("/api/") or request.path.endswith(".csv"):
        return True

    accepted = request.headers.get("Accept", "")
    return "application/json" in accepted



def jwt_login_required(view_func):
    @wraps(view_func)
    def wrapped(request, *args, **kwargs):
        try:
            authenticate_jwt_request(request)
        except JwtAuthError as error:
            if is_api_request(request):
                return JsonResponse(
                    {"success": False, "error": str(error) or "Authentification requise."},
                    status=401,
                )

            login_url = f"{reverse('login')}?next={request.get_full_path()}"
            return redirect(login_url)

        return view_func(request, *args, **kwargs)

    return wrapped








def set_jwt_cookie(response, token):
    response.set_cookie(
        settings.JWT_COOKIE_NAME,
        token,
        max_age=settings.JWT_ACCESS_TOKEN_SECONDS,
        httponly=True,
        secure=not settings.DEBUG,
        samesite="Lax",
    )
    return response


def delete_jwt_cookie(response):
    response.delete_cookie(settings.JWT_COOKIE_NAME, samesite="Lax")
    return response
