"""
ASGI config for osinaweb project.

It exposes the ASGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/
"""
import os
import jwt
from django.core.asgi import get_asgi_application
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.auth.models import AnonymousUser
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from channels.security.websocket import AllowedHostsOriginValidator
from channels.routing import ProtocolTypeRouter
from osinaweb.routing import websocket_urlpatterns  
from django.core.exceptions import ObjectDoesNotExist
from urllib.parse import parse_qs
from osinacore.api.utils import *
from channels.db import database_sync_to_async

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'osinaweb.settings')

django_asgi_app = get_asgi_application()

class JWTAuthMiddleware:
    """Middleware to extract JWT token from the URL query parameters and set the user in the scope."""
    def __init__(self, inner):
        self.inner = inner

    async def __call__(self, scope, receive, send):
        # Extract the token from the URL query parameters
        query_string = scope['query_string'].decode()  # Decode the query string
        query_params = parse_qs(query_string)  # Parse the query string
        token = query_params.get('token', [None])[0]
        if token:
            try:
                token_data = verify(token)
                user =  await database_sync_to_async(User.objects.get)(id=token_data['userid'])
                scope['user'] = user
            except (jwt.ExpiredSignatureError, jwt.DecodeError, ObjectDoesNotExist):
                scope['user'] = AnonymousUser()  # Set user to AnonymousUser if there's an error
        else:
            # No JWT token provided, fallback to default authentication
            return await AuthMiddlewareStack(self.inner)(scope, receive, send)

        return await self.inner(scope, receive, send)



application = ProtocolTypeRouter({
    "http": django_asgi_app,
    "websocket": AllowedHostsOriginValidator(
        JWTAuthMiddleware(
            AuthMiddlewareStack(URLRouter(websocket_urlpatterns))
        )
    ),
})
