from rest_framework.fields import SerializerMethodField
from rest_framework.serializers import ModelSerializer

from backoffice.models import *
from rest_framework import serializers
from rest_framework import filters
from rest_framework.pagination import PageNumberPagination
from django.db.models import F,Q
from django.db.models import Sum

import logging
# Get an instance of a logger
logger = logging.getLogger('django')

class NoPaginationResults(PageNumberPagination):
    page_size = 100
    page_size_query_param = 'page_size'
    max_page_size = 100

class SellerSerializer(ModelSerializer):

    class Meta:
        model = Seller
        fields = '__all__'

class TasksSerializer(ModelSerializer):
    class Meta:
        model = Tasks
        fields = '__all__'
           

class FullUserSerializer(ModelSerializer):
    seller = SellerSerializer(read_only=True)
    extraInfo = serializers.SerializerMethodField()
    class Meta:
        model = User
        exclude =  ('is_superuser','is_active','user_permissions','is_staff',)
        read_only_fields = ['is_staff','is_superuser','is_active','user_permissions']

    def get_extraInfo(self,obj):
        try:
            # calcule nb events crees pour cet organisateur et nombre de tickets vendus
            # ainsi que revenus total
            nbEvents = Event.objects.filter(refOrganiser_id=obj.id).count()
            nbTickets = Ticket.objects.filter(refTicketType__refEvent__refOrganiser_id=obj.id).count()
            revenusDico = Payment.objects.filter(status=1,refTicketType__refEvent__refOrganiser_id=obj.id).aggregate(Sum('amount'),Sum('feesSelltix'),Sum('feesStripeForSellTix'))
            # return json object
            return {
                
                    "nbEvents":nbEvents,
                    "nbTickets":nbTickets,
                    "revenusDico":revenusDico
              
            }
        except:
            return None  
class UserSerializer(ModelSerializer):
    seller = SellerSerializer(read_only=True)
    extraInfo = serializers.SerializerMethodField()
    
    class Meta:
        model = User
        ref_name = "selltix_user"
        exclude =  ('groups','user_permissions','privateKey','password','appleGoogleWallet', 'words','publicKey','pinCode','is_staff','is_superuser','is_active','lastLoginCode','lastLoginCodeDate','nonce',)
        read_only_fields = ['is_staff','is_superuser','is_active','user_permissions']
    
    def get_extraInfo(self,obj):
        try:
            # calcule nb events crees pour cet organisateur et nombre de tickets vendus
            # ainsi que revenus total
            nbEvents = Event.objects.filter(refOrganiser_id=obj.id).count()
            nbTickets = Ticket.objects.filter(refTicketType__refEvent__refOrganiser_id=obj.id).count()
            revenusDico = Payment.objects.filter(status=1,refTicketType__refEvent__refOrganiser_id=obj.id).aggregate(Sum('amount'),Sum('feesSelltix'),Sum('feesStripeForSellTix'))
            # return json object
            return {
                
                    "nbEvents":nbEvents,
                    "nbTickets":nbTickets,
                    "revenusDico":revenusDico
              
            }
        except:
            return None

class CategorySerializer(ModelSerializer):

    class Meta:
        model = Category
        fields = '__all__'

class ContentSerializer(ModelSerializer):
    organizerStripeAccountId = serializers.SerializerMethodField()
    class Meta:
        model = Content
        fields = '__all__'
    def get_organizerStripeAccountId(self,obj):
        try:
            return obj.refOrganiser.seller.stripe_user_id
        except:
            return None

class ContentToSellSerializer(ModelSerializer):
    organizerStripeAccountId = serializers.SerializerMethodField()
    organizerCurrency = serializers.SerializerMethodField()
    class Meta:
        model = Content
        exclude = ('contentFile',)
        
    def get_organizerStripeAccountId(self,obj):
        try:
            return obj.refOrganiser.seller.stripe_user_id
        except:
            return None  
    def get_organizerCurrency(self,obj):
        return obj.refOrganiser.organizerCurrency
    
class EventPageTemplateSerializer(ModelSerializer):

    class Meta:
        model = EventPageTemplate
        fields = '__all__'

class EventParticipantSerializer(ModelSerializer):
    class Meta:
        model = EventParticipant
        fields = '__all__'

class TicketTypeTemplateSerializer(ModelSerializer):
    class Meta:
        model = TicketTypeTemplate
        fields = '__all__'


class TicketTypeSerializer(ModelSerializer):
    refTicketTypeTemplate = TicketTypeTemplateSerializer()
    bookingStartDate = serializers.DateTimeField(default_timezone=timezone.utc)
    bookingEndDate = serializers.DateTimeField(default_timezone=timezone.utc)
    revealStartDate = serializers.DateTimeField(default_timezone=timezone.utc)
    discountEndDate = serializers.DateTimeField(default_timezone=timezone.utc)
    # stock available in real time ? 
    nbSold = serializers.SerializerMethodField()
    class Meta:
        model = TicketType
        fields = '__all__'
    
    def get_nbSold(self,obj):
        #On ne prend que les tickets achetés (pas les offerts ni revendus)
        dict = Payment.objects.filter(status=1,refTicketType=obj,typePayment=0).aggregate(Sum('nbTickets'))
        if dict:
            logger.info(dict)
            if dict["nbTickets__sum"]==None:
                return 0 
            else:
                return dict["nbTickets__sum"]
        else:
            return 0
class TicketTypeCreateSerializer(ModelSerializer):
    class Meta:
        model = TicketType
        fields = '__all__'

class EventSerializer(ModelSerializer):
    eventDate = serializers.DateTimeField(default_timezone=timezone.utc)
    categoryName  = serializers.SerializerMethodField()
    ticketTypes = serializers.SerializerMethodField()
    organiserName = serializers.SerializerMethodField()
    organiserWebsite = serializers.SerializerMethodField()
    stripeAccepted = serializers.SerializerMethodField()
    organizerStripeAccountId = serializers.SerializerMethodField()
    organizerCurrency = serializers.SerializerMethodField()
    payments = serializers.SerializerMethodField()
    nbParticipants = serializers.SerializerMethodField()
    class Meta:
        model = Event
        fields = '__all__'

    def get_ticketTypes(self, obj):
        queryset = TicketType.objects.filter(refEvent=obj.id).order_by('createdAt').select_related("refEvent").select_related("refTicketTypeTemplate")
        return TicketTypeSerializer(queryset, many=True).data

    def get_categoryName(self, obj):
        if obj.refCategory:
            return obj.refCategory.name
        else:
            return None

    def get_organiserName(self, obj):
        if obj.refOrganiser:
            return obj.refOrganiser.organizerCompany
        else:
            return None
       
    
    def get_organiserWebsite(self, obj):
        if obj.refOrganiser:
            return obj.refOrganiser.organizeWebsite
        else:
            return None
        

    def get_organizerStripeAccountId(self,obj):
        try:
            if obj.refOrganiser:
                return obj.refOrganiser.seller.stripe_user_id
            else:
                return None
           
        except Exception as e:
            return None 
    def get_organizerCurrency(self,obj):
        return obj.refOrganiser.organizerCurrency

    def get_stripeAccepted(self,obj):
        try:
            if obj.refOrganiser:
                if obj.refOrganiser.seller:
                    #check status
                    return obj.refOrganiser.seller.stripe_charges_enabled
                else:
                    return None
            else:
                return None
        except Exception as e:
            return None 
        
    def get_payments(self, obj):
        if obj.refOrganiser:
            return {"cb":obj.refOrganiser.cbAccepted,"usdt":obj.refOrganiser.usdtAccepted,"usdc":obj.refOrganiser.usdcAccepted}
        else:
            return {"cb":False,"matic":False,"usdt":False,"usdc":False}
    
    def get_nbParticipants(self, obj):
        #Get all tickets for event
        nbTickets = Ticket.objects.filter(refTicketType__refEvent=obj.id,status=1,typeTicket=0).count()
        return nbTickets
        
class EventPayeesSerializer(ModelSerializer):

    class Meta:
        model = EventPayees
        fields = '__all__'

class ScanUsersSerializer(ModelSerializer):

    class Meta:
        model = ScanUsers
        fields = '__all__'


class EventForTicketSerializer(ModelSerializer):
    eventDate = serializers.DateTimeField(default_timezone=timezone.utc)
    nbParticipants = serializers.SerializerMethodField()
    organizerStripeAccountId = serializers.SerializerMethodField()
    class Meta:
        model = Event
        fields = ('id','status','ticketContract','name','slug','venueName','venueAddress','venueGeoloc','eventDate','duration','eventType','onlineUrl','recordedVideo','recordedStreamingUrl','streamWithSelltix','streamingId','isConference','nbParticipants','organizerStripeAccountId',)
    def get_nbParticipants(self, obj):
        #Get all tickets for event
        nbTickets = Ticket.objects.filter(refTicketType__refEvent=obj.id,status=1,typeTicket=0).count()
        return nbTickets

    def get_organizerStripeAccountId(self,obj):
        try:
            if obj.refOrganiser:
                return obj.refOrganiser.seller.stripe_user_id
            else:
                return None
           
        except Exception as e:
            return None 

class TicketSerializer(ModelSerializer):
    refTicketType = TicketTypeSerializer()
    event = serializers.SerializerMethodField()
    
    class Meta:
        model = Ticket
        exclude =  ('owners', )
    
    def get_event(self,obj):
        #Get event
        try:
            if obj.refTicketType:
                qs = Event.objects.get(id=obj.refTicketType.refEvent_id)
                return EventForTicketSerializer(qs,many=False).data 
            else:
                return None
            
        except Event.DoesNotExist:
            return None
    
class TicketSoldSerializer(ModelSerializer):
    refTicketType = TicketTypeSerializer()
    refUser = UserSerializer() 
    hasParticipated = serializers.SerializerMethodField() 
    class Meta:
        model = Ticket
        exclude =  ('owners', )
    
    def get_hasParticipated(self,obj):
        try:
            #Regarde dans EventParticipant si l'user a participé
            #refEvent 
            #refUser 
            part = EventParticipant.objects.get(refEvent=obj.refTicketType.refEvent,refUser=obj.refUser)
            return True
        except EventParticipant.DoesNotExist:
            return False
     
        
class InvitationSerializer(ModelSerializer):
    refTicket = TicketSerializer()
    fromUser = UserSerializer()
    userExists = serializers.SerializerMethodField()
    class Meta:
        model = Invitation
        fields = '__all__'
    
    def get_userExists(self,obj):
        try:
            user = User.objects.get(email=obj.toUser)
            from rest_framework_simplejwt.tokens import RefreshToken
            refresh = RefreshToken.for_user(user)
            jsonToReturn = {
                            "refUser":UserSerializer(user,many=False).data,
                            'refresh': str(refresh),
                            'access': str(refresh.access_token),
            }
            return jsonToReturn
        except:
            return None

class InscriptionNewsletterSerializer(ModelSerializer):
    class Meta:
        model = InscriptionNewsletter
        fields = '__all__'