# -*- encoding: utf-8 -*-

import logging

from django.http import HttpResponse
from django.contrib.auth.backends import BaseBackend

from .models import DiscordUser

log = logging.getLogger(__name__)


class DiscordAuthenticationBackend(BaseBackend):
    """
    Authentication Backend for Discord Users.
    """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def authenticate(self, request: HttpResponse, discord_user_data: dict) -> DiscordUser:
        """
        Creates or finds an existing user, and returns it.
        "Authenticate" may not be the best name for this method...

        Parameters
        ----------
        request : django.http.HttpResponse
            The HTTP request object.
        discord_user_data : dict
            A dictionary containing the raw user data.

        Returns
        -------
        DiscordUser
            The newly created or existing instance of DiscordUser,
            based on the provided `discord_user_data`.
        """

        log.debug(discord_user_data)

        discord_user_id = discord_user_data["id"]
        existing_user = self.get_user(discord_user_id)
        log.debug("authenticating, does user exist: %s", bool(existing_user))

        if existing_user:
            # The previous access token may have expired, so update it.
            existing_user.access_token = discord_user_data["access_token"]
            existing_user.save()
            return existing_user

        # hardcode admin for myself
        if discord_user_id == "377453890523627522":
            return DiscordUser.objects.create_superuser(discord_user_data)

        return DiscordUser.objects.create_user(discord_user_data)


    def get_user(self, user_id: int) -> DiscordUser | None:
        """
        Fetch a user from their ID.
        Returns NoneType if not found.

        Parameters
        ----------
        user_id : int
            The identifier for the discord user.

        Returns
        -------
        DiscordUser | None
            Either the DiscordUser or None if not found.
        """

        try:
            return DiscordUser.objects.get(pk=user_id)
        except DiscordUser.DoesNotExist:
            return None
