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

import json
import logging
import requests

from django.conf import settings
from django.http import JsonResponse
from django.views.generic import View, TemplateView
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login

from .models import UserServerLink
from apps.home.models import SavedGuilds

log = logging.getLogger(__name__)


class DiscordLoginAction(View):

    def get(self, request, *args, **kwargs):
        return redirect(settings.DISCORD_OAUTH2_URL)


class DiscordLoginRedirect(View):

    def get(self, request, *args, **kwargs):
        """
        Endpoint function directed to once authorized from Discord.
        This method will "login" the user.
        """

        if request.GET.get("error"):
            return redirect("auth:login")

        code = request.GET.get("code")
        access_token = self.exchange_code_for_token(code)
        raw_user_data = self.get_raw_user_data(access_token)
        raw_user_data["access_token"] = access_token

        discord_user = authenticate(request, discord_user_data=raw_user_data)
        login(request, discord_user)

        return redirect("home:index")

    def exchange_code_for_token(self, code: str) -> dict:
        """
        Exchanges the given code for an access token.
        A call is made to the Discord API.
        """

        request_data = settings.DISCORD_CODE_EXCHANGE_REQUEST
        request_data["data"]["code"] = code

        log.debug("request data: %s", request_data)

        # Fetch the access token
        response = requests.post(
            url=f"{settings.DISCORD_API_URL}/oauth2/token",
            data=request_data["data"],
            headers=request_data["headers"]
        )

        log.debug(response)

        return response.json()["access_token"]

    def get_raw_user_data(self, access_token: str):
        """
        Fetches the raw user data using the given access token.
        A call is made to the Discord API.
        """

        response = requests.get(
            url=f"{settings.DISCORD_API_URL}/users/@me",
            headers={"Authorization": f"Bearer {access_token}"}
        )

        log.debug(response)

        return response.json()


class Login(TemplateView):

    template_name = "accounts/login.html"


class GuildsView(View):

    def get(self, request, *args, **kwargs):

        response = requests.get(
            url=f"{settings.DISCORD_API_URL}/users/@me/guilds",
            headers={"Authorization": f"Bearer {request.user.access_token}"}
        )

        content = response.json()
        status = response.status_code

        if status != 200:
            log.debug("Bad status code getting guilds: %s", status_code)
            return JsonResponse(content, safe=False, status=status)

        valid_guilds = [guild for guild in response.json() if self._has_permissions(guild)]

        return JsonResponse(valid_guilds, safe=False, status=status)

    def _has_permissions(self, guild):

        permissions = guild["permissions"]
        is_owner = guild["owner"]

        return (int(permissions) & 1 << 3) == 1 << 3 or is_owner


class GuildChannelsView(View):

    def get(self, request, *args, **kwargs):

        guild_id = request.GET.get("guild")

        log.debug("fetching channels from %s using token: %s", guild_id, settings.BOT_TOKEN)

        response = requests.get(
            url=f"{settings.DISCORD_API_URL}/guilds/{guild_id}/channels",
            headers={"Authorization": f"Bot {settings.BOT_TOKEN}"}
        )

        return JsonResponse(response.json(), safe=False)
        

class SaveGuildView(View):

    pass
