from django.contrib.auth.models import User
from rest_framework.permissions import IsAdminUser
from users.serializers import *
from django.shortcuts import render
from django.contrib.auth.models import User, Group
from rest_framework import viewsets
from users.models import *
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny
import requests
from rest_framework.response import Response
from rest_framework import status
from core.mixin import LoggingMixin
from rest_auth.registration.views import SocialConnectView
from rest_auth.social_serializers import TwitterConnectSerializer

from allauth.socialaccount.providers.twitter.views import TwitterOAuthAdapter
from rest_auth.social_serializers import TwitterLoginSerializer

from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter
from rest_auth.registration.views import SocialLoginView

from allauth.socialaccount.providers.oauth2.client import OAuth2Client
from django_currentuser.middleware import get_current_authenticated_user

from allauth.account.models import EmailConfirmation, EmailConfirmationHMAC
from django.contrib.auth import get_user_model
from django.utils.translation import ugettext_lazy as _
from rest_auth.registration.serializers import VerifyEmailSerializer
from rest_framework.decorators import api_view, APIView
from rest_framework.viewsets import ModelViewSet
from rest_framework.decorators import action
from django.shortcuts import get_object_or_404
from rolepermissions.roles import assign_role, remove_role
from rolepermissions.checkers import has_permission, has_role
from .roles import SuperAdminRole, ManagerRole, EmployeeRole, CustomerRole, AuthenticatedUser
import logging
db_logger = logging.getLogger('db')
from users.permissions import IsAuthenticated, AllowAny, IsManager, IsSuperAdmin, IsEmployee, IsCustomer


@api_view()
def django_rest_auth_null():
    return Response(status=status.HTTP_400_BAD_REQUEST)


class UserViewSet(LoggingMixin, viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited
    """
    queryset = UserModel.objects.all()
    serializer_class = UserSerializer
    # permission_classes = [IsAdminUser]
    # Create employee
    # Manager


class UserAdminViewSet(LoggingMixin, viewsets.ViewSet):
    """
    API endpoint that allows users to be viewed or edited
    """
    queryset = UserModel.objects.all()
    serializer_class = UserAdminSerializer
    permission_classes = [IsAuthenticated]

    @action(detail=True, methods=['post'])
    def create_employee(self, request, pk=None):
        user = get_object_or_404(self.queryset, pk=pk)
        assign_role(user, EmployeeRole)
        assign_role(user, CustomerRole)
        user.save()
        user_s = UserAdminSerializer(intance=user)
        return Response(user_s.data, status.HTTP_200_OK)

    @action(detail=True, methods=['post'])
    def create_manager(self, request, pk=None):
        user = get_object_or_404(self.queryset, pk=pk)
        assign_role(user, ManagerRole)
        user.save()
        user_s = UserAdminSerializer(intance=user)
        return Response(user_s.data, status.HTTP_200_OK)

    @action(detail=True, methods=['post'])
    def clear_roles(self, request, pk=None):
        roles = request.data['roles']
        user = get_object_or_404(self.queryset, pk=pk)
        for role in roles:
            try:
                if role == 'super_admin':
                    remove_role(user, SuperAdminRole)
                if role == 'manager':
                    remove_role(user, ManagerRole)
                if role == 'employee':
                    remove_role(user, EmployeeRole)
                if role == 'customer':
                    remove_role(user, CustomerRole)
                if role == 'authenticated_user':
                    remove_role(user, AuthenticatedUser)
            except Exception as e:
                db_logger.error("clearing role error: %s" % (e))
                return Response("status: Error clearing roles",
                                status.HTTP_500_INTERNAL_SERVER_ERROR)
        user.save()
        return Response("status: Roles cleared", status.HTTP_200_OK)

    @action(detail=True, methods=['post'])
    def add_user_roles(self, request, pk=None):
        roles = request.data['roles']
        user = get_object_or_404(self.queryset, pk=pk)
        for role in roles:
            try:
                if role == 'super_admin':
                    assign_role(user, SuperAdminRole)
                if role == 'manager':
                    assign_role(user, ManagerRole)
                if role == 'employee':
                    assign_role(user, EmployeeRole)
                if role == 'customer':
                    assign_role(user, CustomerRole)
                if role == 'authenticated_user':
                    assign_role(user, AuthenticatedUser)
            except Exception as e:
                db_logger.error("clearing role error: %s" % (e))
                return Response("status: Error assigning roles",
                                status.HTTP_500_INTERNAL_SERVER_ERROR)
        user.save()
        return Response("status: succes", status.HTTP_200_OK)

    # Allow authenticated users  create
    def get_permissions(self):
        if self.action in [
                'update', 'partial_update', 'list', 'create_employee',
                'add_user_roles', 'clear_roles', 'create_manager', 'destroy'
        ]:
            # which is permissions.IsAdminUser
            permission_classes = [IsManager]
        else:
            # which is permissions.AllowAny
            permission_classes = [IsEmployee]
        return [permission() for permission in permission_classes]


@api_view(['POST'])
@permission_classes([AllowAny])
def user_exist(request):
    """
    Allows unauthenticated user to checks if a user exist in the system. request = {username: $username} ,  return True/False
    """
    keys = request.data.keys()
    exist = False
    if len(keys) > 0:
        if keys.__contains__('username'):
            if UserModel.objects.filter(
                    username=request.data['username'], ).exists():
                exist = True
        elif keys.__contains__('email'):
            if UserModel.objects.filter(
                    email=request.data['email'], ).exists():
                exist = True
        elif keys.__contains__('phone'):
            if UserModel.objects.filter(
                    phone=request.data['phone'], ).exists():
                exist = True
    return Response({"exist": exist}, status.HTTP_200_OK)


class VerifyEmailView(APIView):
    permission_classes = (AllowAny, )
    allowed_methods = ('POST', 'OPTIONS', 'HEAD')

    def get_serializer(self, *args, **kwargs):
        return VerifyEmailSerializer(*args, **kwargs)

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.kwargs['key'] = serializer.validated_data['key']
        try:
            confirmation = self.get_object()
            confirmation.confirm(self.request)
            return Response({'detail': _('Successfully confirmed email.')},
                            status=status.HTTP_200_OK)
        except EmailConfirmation.DoesNotExist:
            return Response({'detail': _('Error. Incorrect key.')},
                            status=status.HTTP_404_NOT_FOUND)

    def get_object(self, queryset=None):
        key = self.kwargs['key']
        emailconfirmation = EmailConfirmationHMAC.from_key(key)
        if not emailconfirmation:
            if queryset is None:
                queryset = self.get_queryset()
            try:
                emailconfirmation = queryset.get(key=key.lower())
            except EmailConfirmation.DoesNotExist:
                raise EmailConfirmation.DoesNotExist
        return emailconfirmation

    def get_queryset(self):
        qs = EmailConfirmation.objects.all_valid()
        qs = qs.select_related("email_address__user")
        return qs


class UserDocumentViewSet(LoggingMixin, viewsets.ModelViewSet):
    """
    API endpoint to set or update user documents
    """
    serializer_class = UserDocumentSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        return UserDocument.objects.filter(
            owner=self.request.user).order_by("pk")



# SOCIAL  ACCOUNT AUTHENTICATION
class FacebookLogin(SocialLoginView):
    adapter_class = FacebookOAuth2Adapter


class TwitterLogin(SocialLoginView):
    serializer_class = TwitterLoginSerializer
    adapter_class = TwitterOAuthAdapter


class FacebookConnect(SocialConnectView):
    adapter_class = FacebookOAuth2Adapter


class TwitterConnect(SocialConnectView):
    serializer_class = TwitterConnectSerializer
    adapter_class = TwitterOAuthAdapter
