from rest_framework import serializers
from django.db.models import Sum
from .models import *
from customers.models import Customer
from datetime import date
import pytz
from .shares_balance_helper import get_client_shares_balance

class SharesSettingsSerializer(serializers.ModelSerializer):
    id = serializers.CharField(read_only=True)
    share_setting_added_by = serializers.CharField(read_only=True)
    organisation = serializers.CharField(read_only=True)

    class Meta:
        model = SharesSettings
        fields = '__all__'

class SharesTransactionSerializer(serializers.ModelSerializer):
    id = serializers.CharField(read_only=True)
    share_holder_trans_added_by = serializers.CharField(source='share_holder_trans_added_by.user_staff',read_only=True)
    organisation_branch = serializers.CharField(read_only=True)
    date_added = serializers.CharField(read_only=True)
    last_updated = serializers.CharField(read_only=True)
    customer = serializers.SerializerMethodField(read_only=True)
    receiving_customer = serializers.SerializerMethodField(read_only=True)
    transaction_details = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = SharesTransaction
        fields = '__all__'
    
    def get_customer(self, obj):
        customer = Customer.objects.get(pk=obj.shareholder.customer.id)
        return {"names": customer.name, "member_number":customer.member_number, "old_member_number":customer.old_member_number,"telephone":customer.telephone}

    def get_receiving_customer(self, obj):
        customer = SharesTransfer.objects.filter(transfering_share_transaction=obj).first()
        if customer:
            return {"names": customer.to_customer.name, "member_number":customer.to_customer.member_number, "old_member_number":customer.to_customer.old_member_number}
        return {}
    
    def get_transaction_details(self, obj):
        data = {"amount": obj.system_transaction.amount, "heading":obj.system_transaction.heading, "reference_no": obj.system_transaction.reference_no,
            "payment_method": obj.system_transaction.payment_method, "record_date":obj.system_transaction.record_date, "voucher_no":obj.system_transaction.voucher_no,
            "date_added":obj.date_added
        }

        return data

class ShareHoldersSerializer(serializers.ModelSerializer):
    id = serializers.CharField(read_only=True)
    share_holder_added_by = serializers.CharField(read_only=True)
    date_added = serializers.CharField(read_only=True)
    last_updated = serializers.CharField(read_only=True)
    customer_details = serializers.SerializerMethodField(read_only=True)
    share_details = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = ShareHolders
        fields = '__all__'
    
    def get_customer_details(self, obj):
        customer = Customer.objects.get(pk=obj.customer.id)
        return {"names": customer.name, "member_number":customer.member_number, "old_member_number":customer.old_member_number}

    def get_share_details(self, obj):
        as_at = self.context.get('as_at', None)
        
        inwards = ['transfer-in', 'purchase']
        outwards = ['transfer-out', 'withdrawal']
        if as_at:
            # total in
            all_shares_transaction = SharesTransaction.objects.filter(system_transaction__record_date__date__lte=as_at, shareholder=obj, transaction_type__in=inwards).aggregate(total_no_of_shares=Sum('no_of_shares'))
            all_total_no_of_shares = all_shares_transaction['total_no_of_shares'] if all_shares_transaction['total_no_of_shares'] else 0

            # total out
            share_out_transaction = SharesTransaction.objects.filter(system_transaction__record_date__date__lte=as_at, shareholder=obj, transaction_type__in=outwards).aggregate(total_no_of_shares=Sum('no_of_shares'))
            total_no_of_shares_out = share_out_transaction['total_no_of_shares'] if share_out_transaction['total_no_of_shares'] else 0
        else:
            # total in
            all_shares_transaction = SharesTransaction.objects.filter(shareholder=obj, transaction_type__in=inwards).aggregate(total_no_of_shares=Sum('no_of_shares'))
            all_total_no_of_shares = all_shares_transaction['total_no_of_shares'] if all_shares_transaction['total_no_of_shares'] else 0

            # total out
            share_out_transaction = SharesTransaction.objects.filter(shareholder=obj, transaction_type__in=outwards).aggregate(total_no_of_shares=Sum('no_of_shares'))
            total_no_of_shares_out = share_out_transaction['total_no_of_shares'] if share_out_transaction['total_no_of_shares'] else 0
            

        # get current share value 
        customer = Customer.objects.get(pk=obj.customer.id)
        share = SharesSettings.objects.filter(organisation=customer.customer_branch.branch_organisation).first()
        if share:
            no_of_shares = (all_total_no_of_shares - total_no_of_shares_out)
            return {"total_share_value": share.share_value * no_of_shares , "share_value":share.share_value, "no_of_shares": no_of_shares }
        return {}

class ShareReportsSerializer(serializers.ModelSerializer):
    customer_names = serializers.CharField(source='customer.name',read_only=True)
    member_number = serializers.CharField(source='customer.member_number',read_only=True)
    gender = serializers.CharField(source='customer.gender',read_only=True)
    customer_type = serializers.CharField(source='customer.branch_customer_type.customer_type',read_only=True)
    customer_type_id = serializers.CharField(source='customer.branch_customer_type.id',read_only=True)
    customer_branch = serializers.CharField(source='customer.customer_branch.id',read_only=True)
    shares = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = ShareHolders
        fields = ['customer_names', 'member_number', 'gender', 'customer_type', 'shares', 'customer_branch', 'customer_type_id']

    def get_shares(self, shareholder):
        as_at = None
        request = self.context.get('request', None)
        if request:
            as_at = request.query_params.get('as_at', None)
        
        if not as_at:
            as_at = self.context.get('as_at', None)
            if not as_at:
                as_at = date.today().isoformat()

        as_at = as_at.split(' ')[0]
        share_details = ShareHoldersSerializer(
            shareholder,
            context={
                'as_at': as_at
            }
        ).data
        
        # Get total share value
        inwards = ['transfer-in', 'purchase']
        outwards = ['transfer-out', 'withdrawal']
        shares_in = SharesTransaction.objects.filter(system_transaction__record_date__date__lte=as_at, shareholder__customer__customer_branch__branch_organisation=shareholder.customer.customer_branch.branch_organisation, transaction_type__in=inwards).aggregate(total_shares=Sum('no_of_shares'))['total_shares']
        shares_in = shares_in if shares_in else 0

        # total out
        shares_out = SharesTransaction.objects.filter(system_transaction__record_date__date__lte=as_at, transaction_type__in=outwards).aggregate(total_shares=Sum('no_of_shares'))['total_shares']
        shares_out = shares_out if shares_out else 0
        
        share_details['share_details']['percentage'] = format((share_details['share_details']['no_of_shares'] / (shares_in - shares_out + 0.00000001) * 100), '.2f')
        return share_details['share_details']

class SharesLedgerSerializer(serializers.ModelSerializer):
   
    id = serializers.CharField(read_only=True)
    amount     = serializers.CharField(source = 'system_transaction.amount',read_only=True)
    dr_amount  = serializers.SerializerMethodField(read_only=True)
    cr_amount  = serializers.SerializerMethodField(read_only=True)
    reference_no = serializers.CharField(source = 'system_transaction.reference_no')
    record_date = serializers.CharField(source = 'system_transaction.record_date')
    heading = serializers.CharField(source = 'system_transaction.heading', read_only=True)

    class Meta:
        model = SharesTransaction
        fields = '__all__'

    def get_dr_amount(self, obj):
        dr_amount = 0
        if obj.transaction_type == 'withdrawal' or  obj.transaction_type == 'transfer-out':
            dr_amount = obj.system_transaction.amount
        return dr_amount

    def get_cr_amount(self, obj):
        cr_amount = 0
        if obj.transaction_type == 'purchase'  or  obj.transaction_type == 'transfer-in':
            cr_amount = obj.system_transaction.amount
        return cr_amount


class ShareDividendCustomersSerializer(serializers.ModelSerializer):
    id = serializers.CharField(read_only=True)
    share_dividend_customer_added_by = serializers.CharField(read_only=True)
    date_added = serializers.CharField(read_only=True)
    last_updated = serializers.CharField(read_only=True)
    member_number = serializers.CharField(read_only=True, source="customer.member_number")
    name = serializers.CharField(read_only=True, source="customer.name")
    share_details = serializers.SerializerMethodField(read_only=True)
    withholdingtax = serializers.CharField(read_only=True, source="system_transaction_tax.amount")

    class Meta:
        model = ShareDividendCustomers
        fields = '__all__'

    def get_share_details(self, obj):
        shares_balance = get_client_shares_balance(obj.customer)
        # total_shares = 0

        # customers = Customer.objects.filter(customer_branch__branch_organisation=obj.customer.customer_branch.branch_organisation)
        # for customer in customers:
        #     share_holder = ShareHolders.objects.filter(customer=customer).first()
        #     if share_holder:
        #         customer_balance = get_client_shares_balance(customer)
        #         total_shares += (customer_balance['all_total_no_of_shares'] if customer_balance else 0 )

        # if shares_balance:
        #     percent = (shares_balance['all_total_no_of_shares']/total_shares) * 100 if total_shares > 0 else 0
        #     shares_balance['percent'] = round(percent, 2)

        return shares_balance

class ShareDividendsSerializer(serializers.ModelSerializer):
    id = serializers.CharField(read_only=True)
    share_dividend_added_by = serializers.CharField(read_only=True)
    organisation_branch = serializers.CharField(read_only=True)
    share_dividends_details = serializers.SerializerMethodField(read_only=True)  

    def get_share_dividends_details(self, obj):
        return {}

    class Meta:
        model = ShareDividends
        fields = '__all__'

class SharesTemplateSerializer(serializers.ModelSerializer):
    customer_names = serializers.CharField(read_only=True, source="shareholder.customer.name")
    new_member_number = serializers.CharField(read_only=True, source="shareholder.customer.member_number")
    member_number = serializers.CharField(read_only=True, source="shareholder.customer.old_member_number")
    customer_type = serializers.CharField(read_only=True, source="shareholder.customer.branch_customer_type.customer_type")
    customer_type_id = serializers.CharField(read_only=True, source="shareholder.customer.branch_customer_type.id")
    customer_branch = serializers.CharField(read_only=True, source="organisation_branch.id")
    share_amount = serializers.FloatField(read_only=True, source="system_transaction.amount")
    transaction_type = serializers.SerializerMethodField(read_only=True) 
    record_date = serializers.SerializerMethodField(read_only=True)
    telephone = serializers.CharField(read_only=True, source="shareholder.customer.telephone")

    class Meta:
        model = SharesTransaction
        fields = ['customer_names', 'member_number', 'new_member_number', 'customer_type', 'customer_type_id', 'customer_branch', 'share_amount', 'no_of_shares', 'transaction_type', 'shareholder', 'record_date','telephone']

    def get_record_date(self, tranasation):
        kampala_timezone = pytz.timezone('Africa/Kampala')

        return tranasation.system_transaction.record_date.astimezone(kampala_timezone).strftime('%Y-%m-%d')

    def get_transaction_type(self, tranasation):
        return 'in' if tranasation.transaction_type in ['purchase', 'transfer-in'] else 'out'
