from django.db import IntegrityError
from django.core.exceptions import ObjectDoesNotExist
from warpauth.models import LdapUser
from warppay.models import UserCredit, UserCreditSerializer, Product, ProductSerializer, ProductCategory, ProductCategorySerializer, 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 category_list(request):
    if request.method == 'GET':
        products = ProductCategory.objects.all()
        serializer = ProductCategorySerializer(products,context={'request': request}, many=True)
        return Response(serializer.data)

    return Response()


@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(['PUT'])
def addBarcode(request, prod_id=0):
    if request.method == 'PUT':
        try:
            product = Product.objects.get(id=prod_id)
        except ObjectDoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)
        if not product.barcode:
            product.barcode = request.data['barcode']
            product.save()
            return Response()
        else:
            return Response(status=status.HTTP_406_NOT_ACCEPTABLE)
    else:
        return Response(status=status.HTTP_406_NOT_ACCEPTABLE)


@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:
            print(request.data)
            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, user_id=None):
    if request.method == 'PUT':
        if 'trans_type' not in request.data or not user_id:
            return Response(status=status.HTTP_406_NOT_ACCEPTABLE)

        try:
            u = UserCredit.objects.get(uid=str(user_id))
        except ObjectDoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        t = Transaction()
        t.type = int(request.data['trans_type'])

        if t.type == 1:
            if 'amount' not in request.data or ('amount' in request.data and float(request.data['amount'] < 0)):
                return Response(status=status.HTTP_406_NOT_ACCEPTABLE)
            if 'cash_paid' in request.data:
                t.cash_paid = bool(request.data['cash_paid'])
            else:
                t.cash_paid = True
            t.amount = float(request.data['amount'])
            u.credit +=t.amount
        elif t.type == 2:
            try:
                product = Product.objects.get(id=request.data['product']['id'])
                t.product = product
                if 'cash_paid' in request.data:
                    t.cash_paid = bool(request.data['cash_paid'])
                t.amount = product.price_vk
                if not t.cash_paid:
                    u.credit -= t.amount
            except:
                return Response(status=status.HTTP_406_NOT_ACCEPTABLE)
        else:
            return Response(status=status.HTTP_406_NOT_ACCEPTABLE)

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

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