from django.db import IntegrityError
from django.core.exceptions import ObjectDoesNotExist
from warpauth.models import LdapUser
from warppay.models import UserCredit, UserCreditSerializer, Product, ProductSerializer, Transaction
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.decorators import authentication_classes, permission_classes
from rest_framework.authtoken.models import Token
from django.contrib.auth.models import User
from rest_framework import status

# logging.getLogger('main').info(token.key)

@api_view(['GET', 'PUT'])
#@authentication_classes((TokenAuthentication,))
#@permission_classes((IsAuthenticated,))
def product_list(request):
    if request.method == 'GET':
        products = Product.objects.all()
        serializer = ProductSerializer(products,context={'request': request}, many=True)
        return Response(serializer.data)
    elif request.method == 'PUT':
        return Response()
    return Response()


@api_view(['GET'])
def gen_token(request):
    if request.method == 'GET': 
        token = Token.objects.create(user=User.objects.get(username='api'))    
        return Response(token)
    return Response()

@api_view(['GET', 'PUT'])
#@authentication_classes((TokenAuthentication,))
#@permission_classes((IsAuthenticated,))
def user_list(request, user_id = 0):
    if request.method == 'GET':
        sync_users()
        if not user_id:
            users = UserCredit.objects.all()
            serializer = UserCreditSerializer(users, many=True)
        else:
            user = UserCredit.objects.get(uid=user_id)
            serializer = UserCreditSerializer(user)
        return Response(serializer.data)        
    elif request.method == 'PUT':
        if not user_id:
            return Response(status=status.HTTP_406_NOT_ACCEPTABLE)
        try:
            user = UserCredit.objects.get(uid=user_id)
            if "card_id" in request.data:
                try:
                    ldap_user = LdapUser.objects.get(uid=str(request.data['uid']))
                    if not ldap_user.card_id:
                        ldap_user.card_id = request.data['card_id']
                        ldap_user.save()
                    else:
                        return Response(status=status.HTTP_403_FORBIDDEN)
                except:
                    pass
            sync_users()

            return Response(UserCreditSerializer(user).data)
        except UserCredit.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)
        return Response()
        
    elif request.method == 'POST':
        card_id=""
        if not 'uid' in request.data:
            return Response(status=status.HTTP_406_NOT_ACCEPTABLE)
        if 'card_id' in request.data:
            card_id = request.data['card_id']
        u = UserCredit(uid=request.data['uid'], card_id=card_id, credit=0.0)
        try:
            u.save()
            state=status.HTTP_201_CREATED
        except IntegrityError as e:
            u = UserCredit.objects.get(uid=request.data['uid'])
            state=status.HTTP_409_CONFLICT
        
        serializer = UserCreditSerializer(u)
        return Response(serializer.data, status=state)
    return Response()


@api_view(['PUT'])
#@authentication_classes((TokenAuthentication,))
#@permission_classes((IsAuthenticated,))
def transaction(request):
    if request.method == 'PUT':
        if 'type' not in request.data or 'amount' not in request.data or 'uid' not in request.data or ('amount' in request.data and int(request.data['amount'] < 0)):
            return Response(status=status.HTTP_406_NOT_ACCEPTABLE)

        try:
            u = UserCredit.objects.get(uid=str(request.data['uid']))
        except ObjectDoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        t = Transaction()
        t.type = request.data['type']
        t.amount = float(request.data['amount'])

        if request.data['type'] == 1:
            u.credit +=t.amount
        elif request.data['type'] == 2:
            #product = models.ForeignKey(Product, on_delete=models.CASCADE, null=True)
            if 'cash_paid' in request.data:
                t.cash_paid = bool(request.data['cash_paid'])
            u.credit -=t.amount
        else:
            return Response(status=status.HTTP_406_NOT_ACCEPTABLE)

        t.save()
        u.save()
        return Response()


def sync_users():
    for user in LdapUser.objects.all():
        try:
            u = UserCredit.objects.get(uid=user.uid)
            if user.card_id:
                u.card_id = user.card_id
                u.save()
        except ObjectDoesNotExist:
            u = UserCredit(uid=user.uid, card_id=user.card_id, credit=0.0)
            u.save()