from django.conf import settings
from djoser import views as djoser_views
from djoser.conf import settings as djoser_settings
from djoser.permissions import CurrentUserOrAdmin
from djoser.utils import login_user
from rest_framework import views, status
from rest_framework.decorators import action
from rest_framework.exceptions import NotFound, ValidationError, MethodNotAllowed
from rest_framework.permissions import AllowAny
from rest_framework.renderers import StaticHTMLRenderer
from rest_framework.response import Response

from account.models import User
from account.serializers import SetInitialPasswordSerializer, BonusProgramTransactionSerializer, \
    UserBalanceUpdateSerializer, TelegramCallbackSerializer
from tg_bot.handlers.start import request_phone_sync
from tg_bot.messages import TGCoreMessage


class UserViewSet(djoser_views.UserViewSet):
    def permission_denied(self, request, **kwargs):
        if (
                djoser_settings.HIDE_USERS
                and request.user.is_authenticated
                and self.action in ["balance"]
        ):
            raise NotFound()
        super().permission_denied(request, **kwargs)

    def get_permissions(self):
        if self.action == "set_initial_password":
            self.permission_classes = djoser_settings.PERMISSIONS.set_password

        return super().get_permissions()

    def get_serializer_class(self):
        if self.action == "set_initial_password":
            return SetInitialPasswordSerializer

        return super().get_serializer_class()

    @action(["post"], detail=False)
    def set_initial_password(self, request, *args, **kwargs):
        return super().set_password(request, *args, **kwargs)

    @action(["get", "patch"], detail=True, permission_classes=[CurrentUserOrAdmin])
    def balance(self, request, *args, **kwargs):
        user = self.get_object()

        if request.method == "GET":
            serializer = BonusProgramTransactionSerializer(user.bonus_history, many=True)
            return Response(serializer.data)

        elif request.method == "PATCH":
            if not request.user.is_superuser:
                return self.permission_denied(request)

            # No balance underflow or dummy transactions allowed, no error will be raised
            serializer = UserBalanceUpdateSerializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            data = serializer.data
            user.update_balance(amount=data['amount'], bonus_type=data['type'], comment=data['comment'])

            list_serializer = BonusProgramTransactionSerializer(user.bonus_history, many=True)
            return Response(list_serializer.data)

    @action(["get"], url_path="me/balance", detail=False, permission_classes=[CurrentUserOrAdmin])
    def me_balance(self, request, *args, **kwargs):
        self.get_object = self.get_instance
        return self.balance(request, *args, **kwargs)


class TelegramLoginForm(views.APIView):
    permission_classes = [AllowAny]

    def get_renderers(self):
        if self.request.method == "GET" and settings.DEBUG:
            return [StaticHTMLRenderer()]

        return super().get_renderers()

    def get(self, request, *args, **kwargs):
        if not settings.DEBUG:
            raise MethodNotAllowed(request.method)

        source = """
        <html>
            <body>
                <script async src="https://telegram.org/js/telegram-widget.js?22" 
                data-telegram-login="phzhik_dev_bot" 
                data-size="large" 
                data-onauth="onTelegramAuth(user)"
                data-request-access="write"></script>
                
                <script type="text/javascript">
                    function onTelegramAuth(user) {
                        console.log(user);

                        const request = new Request("/auth/telegram/", {
                          method: "post",
                          body: JSON.stringify(user),
                          headers: {
                            'Accept': 'application/json',
                            'Content-Type': 'application/json'
                          }
                        });
                    
                        fetch(request)
                        .then(response => {
                            if (!response.ok) {
                                throw new Error('HTTP error ' + response.status);
                            }
                            return response.json();
                        })
                        .then(data => console.log(data))
                        .catch(error => console.error(error));
                    }
                </script>
            </body>
        </html>
        """

        return Response(source)

    def post(self, request, *args, **kwargs):
        serializer = TelegramCallbackSerializer(data=request.data)

        try:
            serializer.is_valid(raise_exception=True)

        except ValidationError as e:
            return Response(e.detail, status=status.HTTP_401_UNAUTHORIZED)

        except:
            return Response(status=status.HTTP_401_UNAUTHORIZED)

        data = serializer.data

        # Authenticate user with given tg_user_id
        tg_user_id = data["id"]

        user: User = User.objects.filter(tg_user_id=tg_user_id).first()
        if not user:
            # Sign up user
            user = User.objects.create_draft_user(tg_user_id=tg_user_id)
            # Request the phone through the bot
            request_phone_sync(tg_user_id, TGCoreMessage.TG_AUTH_SHARE_PHONE)

        token = login_user(request, user)
        return Response({"auth_token": token.key})
