from rest_framework import serializers
from savings.models import *
from customers.helper import get_all_customer_files
from locations.models import CustomerAddress
from locations.serializers import  CustomerAddressSerializer
from users.serializers import UserSerializer
from ledgers.serializers import SystemTransactionsSerializer,OrganisationSubAccountSerializer
from ledgers.models import SystemTransactions
from django.db.models import Sum,Count
from django.conf import settings
from datetime import datetime, timedelta, date
from django.utils.timezone import make_aware
from savings.savings_bal_helper import get_account_balance
from .data import savings_blocking_types
from urllib.parse import quote

class SavingsProductSerializer(serializers.ModelSerializer):
    accounts_chart = serializers.CharField(source='accounts_chart.id',read_only=True)
    account_name = serializers.CharField(source='accounts_chart.account_name',read_only=True)
    account_code = serializers.CharField(source='accounts_chart.account_code',read_only=True)
    closing_fee_account = serializers.CharField(source='closing_fee_account.id', read_only=True)
    max_withdraw_limit_charge_type = serializers.CharField(required=False)
    ledger_fees_frequency = serializers.CharField(read_only=True,required=False)
    saving_product_org = serializers.CharField(source='saving_product_org.id',read_only=True)
    saving_product_added_by = serializers.CharField(read_only=True)
    product_charges = serializers.SerializerMethodField(read_only=True)
    
    def get_product_charges(self, saving_product):
        charges    = SavingProductCharge.objects.filter(saving_product=saving_product)
        serializer = SavingProductChargeSerializer(charges, many=True)
        return  serializer.data

    def validate_activation_period(self, value):
        if value is not None and int(value) < 0:
            raise serializers.ValidationError("Activation period must be zero or greater.")
        return value

    def validate_dormancy_period(self, value):
        if value is not None and int(value) < 0:
            raise serializers.ValidationError("Dormancy period must be zero or greater.")
        return value

    def validate_deactivation_period(self, value):
        if value is not None and int(value) < 0:
            raise serializers.ValidationError("Deactivation period must be zero or greater.")
        return value

    def validate_account_closure_fee(self, value):
        if value is not None and float(value) < 0:
            raise serializers.ValidationError("Account closure fee must be zero or greater.")
        return value
       
    class Meta:
        model = SavingsProduct
        fields = '__all__'''
    
class SavingProductChargeSerializer(serializers.ModelSerializer):
    charge_added_by = serializers.CharField(read_only=True)
    saving_product_org = serializers.CharField(source='saving_product.saving_product_org.id',read_only=True)
    class Meta:
        model = SavingProductCharge
        fields = '__all__'''

class SavingProductCustomChargeSerializer(serializers.ModelSerializer):
    charge_added_by = serializers.CharField(read_only=True)
    class Meta:
        model = SavingProductCustomCharge
        fields = '__all__'''

class BulkSavingsChargeInitiationSerializer(serializers.ModelSerializer):
    charge_added_by = serializers.CharField(read_only=True)
    saving_product_org  = serializers.CharField(source='saving_product.saving_product_org.id', read_only=True)
    product_id          = serializers.CharField(source='saving_product.id', read_only=True)
    product_name        = serializers.CharField(source='saving_product.product_name', read_only=True)
    accounts_chart_name = serializers.CharField(source='accounts_chart.account_name', read_only=True)
    accounts_chart_code = serializers.CharField(source='accounts_chart.account_code', read_only=True)
    branch_name         = serializers.CharField(source='branch.name', read_only=True)

    class Meta:
        model = BulkSavingsChargeInitiation
        fields = '__all__'

    def validate(self, data):
        """
        Ensure either record_date is provided or both start_date and end_date are provided.
        Also, start_date must not be after end_date.
        Skip validation for action operations.
        """
        # Skip validation if this is an action operation
        if hasattr(self, 'context') and self.context.get('request'):
            request = self.context['request']
            if (request.method == 'DELETE' or 
                request.data.get('action') in ['delete_transaction', 'reverse_transaction', 'process']):
                return data
        
        record_date = data.get('record_date')
        start_date = data.get('start_date')
        end_date = data.get('end_date')

        if not record_date and not (start_date and end_date):
            raise serializers.ValidationError("Either 'record_date' or both 'start_date' and 'end_date' must be provided.")

        if start_date and end_date and start_date > end_date:
            raise serializers.ValidationError("'start_date' cannot be after 'end_date'.")

        return data

class BulkSavingsChargesTransactionsSerializer(serializers.ModelSerializer):
    #Trnasaction details
    amount       =  serializers.CharField(source="saving_transaction.transaction.amount",read_only=True)
    heading      = serializers.CharField(source="saving_transaction.transaction.heading",read_only=True)
    reference_no = serializers.CharField(source="saving_transaction.transaction.reference_no",read_only=True)
    transaction_type = serializers.CharField(source="saving_transaction.transaction.transaction_type",read_only=True)
    branch       =  serializers.CharField(source="saving_transaction.transaction.branch",read_only=True)
    record_date  =  serializers.CharField(source="saving_transaction.transaction.record_date",read_only=True)
    transaction  = serializers.CharField(source='saving_transaction.transaction.id',read_only=True)
    #Account details
    customer_name = serializers.CharField(source='saving_transaction.customer_account.account_customer.name',read_only=True)
    customer_member_number = serializers.CharField(source='saving_transaction.customer_account.account_customer.member_number',read_only=True)
    telephone = serializers.CharField(source='saving_transaction.customer_account.account_customer.telephone',read_only=True)
    customer_type = serializers.CharField(source='saving_transaction.customer_account.account_customer.branch_customer_type.id',read_only=True)
    product_name  = serializers.CharField(source='saving_transaction.customer_account.account_product.product_name',read_only=True)
    currency      = serializers.CharField(source='saving_transaction.customer_account.account_product.currency',read_only=True)
    customer_type_name = serializers.CharField(source="saving_transaction.customer_account.account_customer.branch_customer_type.customer_type",read_only=True)
    customer_address = serializers.CharField(source="saving_transaction.customer_account.customer_address",read_only=True)
    customer_account = serializers.CharField(source='saving_transaction.customer_account.id',read_only=True)
    account_no = serializers.CharField(source='saving_transaction.customer_account.account_no',read_only=True)
    
    class Meta:
        model = BulkSavingsChargesTransactions
        fields = '__all__'



class SavingProductInterestSerializer(serializers.ModelSerializer):
    interest_added_by  = serializers.CharField(read_only=True)
    interest_last_updated_by  = serializers.CharField(read_only=True)
    saving_product = serializers.CharField(source='saving_product.id',read_only=True)
    
    class Meta:
        model = SavingProductInterest
        fields = '__all__'''

class SavingAccountSerializer(serializers.ModelSerializer):
    customer_branch  = serializers.CharField(read_only=True)
    customer_branch_id  = serializers.CharField(source='customer_branch.id',read_only=True)
    customer_name = serializers.CharField(source='account_customer.name',read_only=True)
    customer_member_number = serializers.CharField(source='account_customer.member_number',read_only=True)
    customer_old_member_number = serializers.CharField(source='account_customer.old_member_number',read_only=True)
    customer_has_members = serializers.CharField(source='account_customer.branch_customer_type.has_members',read_only=True)
    telephone = serializers.CharField(source='account_customer.telephone',read_only=True)
    customer_type    = serializers.CharField(source='account_customer.branch_customer_type.id',read_only=True)
    default_charge_type = serializers.CharField(source='account_product.default_charge_type',read_only=True)
    product_name  = serializers.CharField(source='account_product.product_name',read_only=True)
    currency      = serializers.CharField(source='account_product.currency.currency_code',read_only=True)
    customer_type_name = serializers.CharField(read_only=True, source="account_customer.branch_customer_type.customer_type")
    customer_files    = serializers.SerializerMethodField(read_only=True)
    customer_address  = serializers.SerializerMethodField(read_only=True)
    account_balance   = serializers.SerializerMethodField(read_only=True)
    opened_by_name  = serializers.CharField(source='opened_by.name',read_only=True)
    max_withdraws   = serializers.FloatField(source='account_product.max_withdraws',read_only=True)
    deposit_custom_charge   = serializers.BooleanField(source='account_product.deposit_custom_charge',read_only=True)
    withdraw_custom_charge  = serializers.BooleanField(source='account_product.withdraw_custom_charge',read_only=True)
    transfer_custom_charge  = serializers.BooleanField(source='account_product.transfer_custom_charge',read_only=True)
    max_withdraw_limit_charge_type  = serializers.CharField(source='account_product.max_withdraw_limit_charge_type',read_only=True)
    account_closure_fee = serializers.FloatField(source='account_product.account_closure_fee', read_only=True)
    saving_account_added_by = serializers.CharField(source='saving_account_added_by.user_staff.name',read_only=True)
    saving_account_last_updated_by = serializers.CharField(read_only=True)
    user_details    = serializers.SerializerMethodField(read_only=True)
    aml_verification_status = serializers.SerializerMethodField(read_only=True)
    latest_aml_verification = serializers.SerializerMethodField(read_only=True)

    
    def get_customer_files(self, saving_account):
        return get_all_customer_files(saving_account.account_customer)
    
    def get_customer_address(self, saving_account):
        addresses    = CustomerAddress.objects.filter(customer=saving_account.account_customer)
        serializer = CustomerAddressSerializer(addresses, many=True)
        return  serializer.data

    def get_account_balance(self, account):
        if not isinstance(account, SavingAccount):
            account = SavingAccount.objects.get(pk=account)
        return get_account_balance(account)
    
    def get_user_details(self, user):
        user_details = User.objects.filter(pk=user.id)
        serializer   = UserSerializer(user_details, many=True)
        return serializer.data

    def _get_latest_aml_verification(self, saving_account):
        prefetched_verifications = getattr(saving_account, 'latest_aml_verifications', None)
        if prefetched_verifications is not None:
            return prefetched_verifications[0] if prefetched_verifications else None

        request = self.context.get('request') if hasattr(self, 'context') else None
        query_params = getattr(request, 'query_params', None) if request else None
        if query_params and any(param in query_params for param in ['aml_status', 'aml_blocked']):
            return saving_account.aml_verifications.order_by('-verified_at', '-id').first()

        return None

    def get_aml_verification_status(self, saving_account):
        if saving_account.is_aml_withdrawal_blocked:
            return 'blocked'

        if self._get_latest_aml_verification(saving_account):
            return 'verified'

        return ''

    def get_latest_aml_verification(self, saving_account):
        verification = self._get_latest_aml_verification(saving_account)
        if not verification:
            return None

        return SavingsAMLVerificationSerializer(verification).data

    def to_representation(self, instance):
        if (
            isinstance(instance, SavingAccount)
            and not instance.deleted
            and (
                not instance.is_active
                or instance.status in ['inactive', 'dormant']
                or instance.dormancy_date is not None
            )
        ):
            from savings.savings_helper import sync_savings_account_lifecycle
            sync_savings_account_lifecycle(instance)
        return super().to_representation(instance)
        
    class Meta:
        model = SavingAccount
        fields = '__all__'''


class MobileAppSavingAccountCreateSerializer(serializers.ModelSerializer):
    account_product = serializers.PrimaryKeyRelatedField(queryset=SavingsProduct.objects.filter(is_active=True, deleted=False))

    class Meta:
        model = SavingAccount
        fields = ['account_product', 'open_date']

    def validate_account_product(self, value):
        customer = self.context.get('customer')
        if not customer:
            raise serializers.ValidationError("Authenticated customer is required.")

        organisation_id = customer.customer_branch.branch_organisation_id
        if value.saving_product_org_id != organisation_id:
            raise serializers.ValidationError("Selected savings product is invalid for the current customer.")

        return value

class SavingsBlockedAmountSerializer(serializers.ModelSerializer):
    customer_branch  = serializers.CharField(read_only=True)
    account_no = serializers.CharField(source='customer_account.account_no',read_only=True)
    customer_branch_id  = serializers.CharField(source='customer_account.customer_branch.id',read_only=True)
    customer_name = serializers.CharField(source='customer_account.account_customer.name',read_only=True)
    customer_member_number = serializers.CharField(source='customer_account.account_customer.member_number',read_only=True)
    customer_old_member_number = serializers.CharField(source='customer_account.account_customer.old_member_number',read_only=True)
    telephone = serializers.CharField(source='customer_account.account_customer.telephone',read_only=True)
    customer_type = serializers.CharField(source='customer_account.account_customer.branch_customer_type.id',read_only=True)
    default_charge_type = serializers.CharField(source='customer_account.account_product.default_charge_type',read_only=True)
    product_name  = serializers.CharField(source='customer_account.account_product.product_name',read_only=True)
    currency      = serializers.CharField(source='customer_account.account_product.currency.currency_code',read_only=True)
    customer_type_name = serializers.CharField(read_only=True, source="customer_account.account_customer.branch_customer_type.customer_type")
    opened_by_name  = serializers.CharField(source='customer_account.opened_by.name',read_only=True)
    blocked_amount_added_by = serializers.CharField(source='blocked_amount_added_by.user_staff.name',read_only=True)
    blocked_amount_last_updated_by  = serializers.CharField(source='blocked_amount_last_updated_by.user_staff.name',read_only=True)
    blocking_type_name = serializers.SerializerMethodField(read_only=True, required=False)

    def get_blocking_type_name(self,instance):
        blocking_type_name = ''
        for savings_blocking_type in savings_blocking_types:
            if savings_blocking_type['key'] == instance.block_type:
                blocking_type_name = savings_blocking_type['value']
        return blocking_type_name


    class Meta:
        model = SavingsBlockedAmount
        fields = '__all__'''


class SavingsAMLVerificationSerializer(serializers.ModelSerializer):
    customer_branch = serializers.CharField(
        source='saving_account.customer_branch.name',
        read_only=True,
    )
    account_no = serializers.CharField(
        source='saving_account.account_no',
        read_only=True,
    )
    customer_name = serializers.CharField(
        source='saving_account.account_customer.name',
        read_only=True,
    )
    customer_member_number = serializers.CharField(
        source='saving_account.account_customer.member_number',
        read_only=True,
    )
    product_name = serializers.CharField(
        source='saving_account.account_product.product_name',
        read_only=True,
    )
    currency = serializers.CharField(
        source='saving_account.account_product.currency.currency_code',
        read_only=True,
    )
    verified_by_name = serializers.SerializerMethodField(read_only=True)
    supporting_document_url = serializers.SerializerMethodField(read_only=True)

    def get_verified_by_name(self, instance):
        if instance.verified_by and getattr(instance.verified_by, 'user_staff', None):
            return instance.verified_by.user_staff.name
        return ''

    def get_supporting_document_url(self, instance):
        supporting_document = instance.supporting_document
        if not supporting_document:
            return None

        supporting_document = str(supporting_document).strip()
        if supporting_document.startswith(('http://', 'https://')):
            return supporting_document

        if not settings.AWS_STORAGE_BUCKET_NAME:
            return supporting_document

        if settings.AWS_S3_REGION_NAME:
            return (
                f'https://{settings.AWS_STORAGE_BUCKET_NAME}.s3.{settings.AWS_S3_REGION_NAME}.amazonaws.com/'
                f'{quote(supporting_document, safe="/")}'
            )

        return (
            f'https://{settings.AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/'
            f'{quote(supporting_document, safe="/")}'
        )

    def validate_source_of_income(self, value):
        if not str(value).strip():
            raise serializers.ValidationError('Source of income is required.')
        return value.strip()

    class Meta:
        model = SavingsAMLVerification
        fields = [
            'id',
            'saving_account',
            'source_of_income',
            'supporting_document',
            'threshold_amount',
            'trigger_amount',
            'block_reason',
            'blocked_at',
            'trigger_transaction',
            'verified_by',
            'verified_at',
            'customer_branch',
            'account_no',
            'customer_name',
            'customer_member_number',
            'product_name',
            'currency',
            'verified_by_name',
            'supporting_document_url',
        ]
        read_only_fields = [
            'saving_account',
            'threshold_amount',
            'trigger_amount',
            'block_reason',
            'blocked_at',
            'trigger_transaction',
            'verified_by',
            'verified_at',
            'customer_branch',
            'account_no',
            'customer_name',
            'customer_member_number',
            'product_name',
            'currency',
            'verified_by_name',
            'supporting_document_url',
        ]

class SavingAccountTransactionsSerializer(serializers.ModelSerializer):
    #Trnasaction details
    amount       =  serializers.CharField(source="transaction.amount",read_only=True)
    heading      = serializers.CharField(source="transaction.heading",read_only=True)
    reference_no = serializers.CharField(source="transaction.reference_no",read_only=True)
    branch       =  serializers.CharField(source="transaction.branch",read_only=True)
    voucher_no   =  serializers.CharField(source="transaction.voucher_no",read_only=True)
    payment_method   = serializers.CharField(source="transaction.payment_method",read_only=True)
    transaction_type =  serializers.CharField(source="transaction.transaction_type",read_only=True)
    coment      = serializers.CharField(source="transaction.coment",read_only=True)
    record_date = serializers.CharField(source="transaction.record_date",read_only=True)
    added_by    = serializers.CharField(source="transaction.added_by.user_staff",read_only=True)
    date_added  = serializers.CharField(source="transaction.date_added",read_only=True)

    #Account details
    customer_name = serializers.CharField(source='customer_account.account_customer.name',read_only=True)
    customer_member_number = serializers.CharField(source='customer_account.account_customer.member_number',read_only=True)
    telephone = serializers.CharField(source='customer_account.account_customer.telephone',read_only=True)
    customer_type = serializers.CharField(source='customer_account.account_customer.branch_customer_type.id',read_only=True)
    customer_type_name = serializers.CharField(source='customer_account.account_customer.branch_customer_type.customer_type',read_only=True)
    product_name  = serializers.CharField(source='customer_account.account_product.product_name',read_only=True)
    currency      = serializers.CharField(source='customer_account.account_product.currency',read_only=True)
    customer_type_name = serializers.CharField(source="customer_account.account_customer.branch_customer_type.customer_type",read_only=True)
    customer_address = serializers.CharField(source="customer_account.customer_address",read_only=True)
    customer_account = serializers.CharField(source='customer_account.id',read_only=True)
    account_no = serializers.CharField(source='customer_account.account_no',read_only=True)
    transaction      = serializers.CharField(source='transaction.id',read_only=True)
    depositor_name = serializers.CharField(source='transaction.depositor_name', read_only=True)
    
    class Meta:
        model = SavingAccountTransactions
        fields = '__all__'
        
class GroupSavingTransactionSerializer(serializers.ModelSerializer):
    #Trnasaction details
    transaction  = serializers.CharField(source='savings.transaction.id',read_only=True)
    amount       =  serializers.CharField(source="savings.transaction.amount",read_only=True)
    heading      = serializers.CharField(source="savings.transaction.heading",read_only=True)
    reference_no = serializers.CharField(source="savings.transaction.reference_no",read_only=True)
    credit_chart = serializers.CharField(source="savings.transaction.credit_chart.id",read_only=True)
    debit_chart  = serializers.CharField(source="savings.transaction.debit_chart.id",read_only=True)
    branch       =  serializers.CharField(source="savings.transaction.branch",read_only=True)
    voucher_no   =  serializers.CharField(source="savings.transaction.voucher_no",read_only=True)
    payment_method   = serializers.CharField(source="savings.transaction.payment_method",read_only=True)
    transaction_type =  serializers.CharField(source="savings.transaction.transaction_type",read_only=True)
    coment      = serializers.CharField(source="savings.transaction.coment",read_only=True)
    record_date = serializers.CharField(source="savings.transaction.record_date",read_only=True)
    added_by    = serializers.CharField(source="savings.transaction.added_by.user_staff",read_only=True)
    date_added  = serializers.CharField(source="savings.transaction.date_added",read_only=True)

    #Member details
    customer_name = serializers.CharField(source='membership.member.name',read_only=True)
    customer_member_number = serializers.CharField(source='membership.member.member_number',read_only=True)
    telephone = serializers.CharField(source='membership.member.telephone',read_only=True)
    customer_type = serializers.CharField(source='membership.member.branch_customer_type.id',read_only=True)
    customer_type_name = serializers.CharField(source="membership.member.branch_customer_type.customer_type",read_only=True)
   
    class Meta:
        model = GroupSavingTransaction
        fields = '__all__'



class FixedDepositSerializer(serializers.ModelSerializer):
    
    #Account details
    customer_id = serializers.CharField(source='saving_account.account_customer.id',read_only=True)
    customer_name = serializers.CharField(source='saving_account.account_customer.name',read_only=True)
    customer_member_number = serializers.CharField(source='saving_account.account_customer.member_number',read_only=True)
    customer_type = serializers.CharField(source='saving_account.account_customer.branch_customer_type.id',read_only=True)
    product_name  = serializers.CharField(source='saving_account.account_product.product_name',read_only=True)
    currency      = serializers.CharField(source='saving_account.account_product.currency',read_only=True)
    customer_type_name = serializers.CharField(source="saving_account.account_customer.branch_customer_type.customer_type",read_only=True)
    customer_address   = serializers.CharField(source="saving_account.account_customer.customer_address",read_only=True)
    saving_account     = serializers.CharField(source='saving_account.id',read_only=True)
    account_no         = serializers.CharField(source='saving_account.account_no',read_only=True)
    branch             = serializers.CharField(read_only=True)
    fixed_deposit_added_by        = serializers.CharField(source='fixed_deposit_added_by.user_staff',read_only=True)
    fixed_deposit_last_updated_by = serializers.CharField(source='fixed_deposit_added_by.user_staff',read_only=True)
    formatted_period  = serializers.SerializerMethodField(read_only=True, required=False)
    maturity_days = serializers.SerializerMethodField(read_only=True, required=False)
    format_frequency = serializers.SerializerMethodField(read_only=True, required=False)
    reference_transaction = SystemTransactionsSerializer(read_only=True, required=False)
    closure_transaction = SystemTransactionsSerializer(read_only=True, required=False)
    maturity_date = serializers.SerializerMethodField(read_only=True, required=False)
    
    def get_maturity_date(self, fixed_deposit):
        last_schedule = FixedDepositSchedule.objects.active().filter(
            fixed_deposit=fixed_deposit
        ).order_by('-expected_date').first()

        if last_schedule:
            return last_schedule.expected_date
        
        return None

    def get_maturity_days(self,instance):
        current_date  = make_aware(datetime.strptime(datetime.now().strftime("%Y-%m-%d"), '%Y-%m-%d'))
        expected_date = make_aware(datetime.strptime(instance.record_date.strftime("%Y-%m-%d") + ' 23:59:59','%Y-%m-%d %H:%M:%S'))

        if instance.period_type == 'y':
            expected_date = expected_date +  timedelta(days= 12 * 30 * instance.period)
        if instance.period_type == 'q':
            expected_date = expected_date + timedelta(days= 3 * 30 * instance.period)
        if instance.period_type == 'm':
            expected_date = expected_date + timedelta(days= 1 * 30 * instance.period)
        if instance.period_type == 'd':
            expected_date = expected_date + timedelta(days= 1 * instance.period) 

        days = (current_date - expected_date).days
        return days if days > 0 else 0
        
       
        
    def get_formatted_period(self, instance):
        return str(instance.period) + ' ' + self.format_period(instance.period_type)
    
    def format_period(self,periodType):
        if periodType == 'y':
           return 'Year(s)'
        if periodType == 'q':
           return 'Quarters'
        if periodType == 'm':
           return 'Months'
        if periodType == 'd':
           return 'Days'
        if periodType == 'w':
           return 'Weeks'
        if periodType == 'bw':
           return 'Bi-Weeks'
        
    def format_interval(self,periodType):
        if periodType == 'y':
           return 'Annually'
        if periodType == 'q':
           return 'Daily'
        if periodType == 'm':
           return 'Monthly'
        if periodType == 'd':
           return 'Daily'
        if periodType == 'w':
           return 'Weekly'
        if periodType == 'bw':
           return 'Bi Weekly'
        
    def get_format_frequency(self, instance):
        if instance.frequency == 1:
           return self.format_interval(instance.period_type)
        
        return f'Every {instance.frequency} {self.format_period(instance.period_type)}'
        
        
    class Meta:
        model = FixedDeposit
        fields = '__all__'

class PendingWithdrawalsSerializer(serializers.ModelSerializer):
    id               = serializers.IntegerField(read_only=True)
    last_updated_by  = serializers.CharField(read_only=True)
    customer_branch  = serializers.CharField(read_only=True)
    saving_account_transaction = serializers.CharField(read_only=True)
    added_by = serializers.CharField(source='added_by.user_staff',read_only=True)

    #Account details
    customer_name = serializers.CharField(source='customer_account.account_customer.name',read_only=True)
    customer_member_number = serializers.CharField(source='customer_account.account_customer.member_number',read_only=True)
    customer_type = serializers.CharField(source='customer_account.account_customer.branch_customer_type.id',read_only=True)
    telephone = serializers.CharField(source='customer_account.account_customer.telephone',read_only=True)
    product_id  = serializers.CharField(source='customer_account.account_product.id',read_only=True)
    product_name  = serializers.CharField(source='customer_account.account_product.product_name',read_only=True)
    currency      = serializers.CharField(source='customer_account.account_product.currency',read_only=True)
    customer_type_name = serializers.CharField(source="customer_account.account_customer.branch_customer_type.customer_type",read_only=True)
    customer_address = serializers.CharField(source="customer_account.customer_address",read_only=True)
    account_no = serializers.CharField(source='customer_account.account_no',read_only=True)
    credit_chart_name = serializers.CharField(source='credit_chart.account_name',read_only=True) 
   
    class Meta:
        model = PendingWithdrawals
        fields = '__all__' 


class SavingAccountClosureSerializer(serializers.ModelSerializer):
    saving_account_no = serializers.CharField(source='saving_account.account_no', read_only=True)
    saving_account_status = serializers.CharField(source='saving_account.status', read_only=True)
    customer_name = serializers.CharField(source='saving_account.account_customer.name', read_only=True)
    customer_member_number = serializers.CharField(source='saving_account.account_customer.member_number', read_only=True)
    product_name = serializers.CharField(source='saving_account.account_product.product_name', read_only=True)
    currency = serializers.CharField(source='saving_account.account_product.currency.currency_code', read_only=True)
    fee_collection_account_name = serializers.CharField(source='fee_collection_account.account_name', read_only=True)
    withdrawal_destination_chart_name = serializers.CharField(source='withdrawal_destination_chart.account_name', read_only=True)
    closure_added_by_name = serializers.CharField(source='closure_added_by.user_staff.name', read_only=True)
    closure_completed_by_name = serializers.CharField(source='closure_completed_by.user_staff.name', read_only=True)
    withdrawable_balance = serializers.SerializerMethodField(read_only=True)
    account_balance = serializers.SerializerMethodField(read_only=True)

    def get_withdrawable_balance(self, closure):
        from savings.savings_helper import get_savings_account_closure_available_balance
        return get_savings_account_closure_available_balance(closure.saving_account)

    def get_account_balance(self, closure):
        return get_account_balance(closure.saving_account)

    class Meta:
        model = SavingAccountClosure
        fields = '__all__'

class AccountBookingPaymentsSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(read_only=True)
    reference_transaction = SystemTransactionsSerializer(read_only=True, required=False)
    booking = serializers.PrimaryKeyRelatedField(read_only=True, required=False)
    
    class Meta:
        model = AccountBookingPayments
        fields = '__all__'


class AccountBookingsSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(read_only=True)
    account = serializers.PrimaryKeyRelatedField(read_only=True, required=False)
    chart = serializers.PrimaryKeyRelatedField(read_only=True, required=False)
    account_number = serializers.CharField(source='account.account_no',read_only=True)
    customer_name = serializers.CharField(source='account.account_customer.name',read_only=True)
    member_no = serializers.CharField(source='account.account_customer.member_number',read_only=True)
    payments = serializers.SerializerMethodField(read_only=True, required=False)
    reference_transaction = serializers.PrimaryKeyRelatedField(read_only=True, required=False)
    
    def get_payments(self, booking):
        payments = AccountBookingPayments.objects.filter(booking=booking)
        paymentTotals = payments.aggregate(total=Sum('reference_transaction__amount'))['total']
        payments = {
            'total': paymentTotals if paymentTotals else 0,
            'list': AccountBookingPaymentsSerializer(payments, many=True).data
        }

        return payments
    
    class Meta:
        model = AccountBookings
        fields = '__all__'

class TransferTransactionsSerializer(serializers.ModelSerializer):
    #transaction details
    amount       =  serializers.CharField(source="reciever_transaction.transaction.amount",read_only=True)
    heading      = serializers.CharField(source="reciever_transaction.transaction.heading",read_only=True)
    reference_no = serializers.CharField(source="reciever_transaction.transaction.reference_no",read_only=True)
    branch       =  serializers.CharField(source="reciever_transaction.transaction.branch",read_only=True)
    voucher_no   =  serializers.CharField(source="reciever_transaction.transaction.voucher_no",read_only=True)
    payment_method   = serializers.CharField(source="reciever_transaction.transaction.payment_method",read_only=True)
    transaction_type =  serializers.CharField(source="reciever_transaction.transaction.transaction_type",read_only=True)
    coment      = serializers.CharField(source="reciever_transaction.transaction.coment",read_only=True)
    record_date = serializers.CharField(source="reciever_transaction.transaction.record_date",read_only=True)
    added_by    = serializers.CharField(source="reciever_transaction.transaction.added_by",read_only=True)
    date_added  = serializers.CharField(source="reciever_transaction.transaction.date_added",read_only=True)

    #Sender Account details
    sender_customer_name = serializers.CharField(source='sender_transaction.customer_account.account_customer.name',read_only=True)
    sender_customer_member_number = serializers.CharField(source='sender_transaction.customer_account.account_customer.member_number',read_only=True)
    sender_customer_type = serializers.CharField(source='sender_transaction.customer_account.account_customer.branch_customer_type.id',read_only=True)
    sender_product_name  = serializers.CharField(source='sender_transaction.customer_account.account_product.product_name',read_only=True)
    sender_currency      = serializers.CharField(source='sender_transaction.customer_account.account_product.currency',read_only=True)
    sender_customer_type_name = serializers.CharField(source="sender_transaction.customer_account.account_customer.branch_customer_type.customer_type",read_only=True)
    sender_customer_address = serializers.CharField(source="sender_transaction.customer_account.customer_address",read_only=True)
    sender_customer_account = serializers.CharField(source='sender_transaction.customer_account.id',read_only=True)
    sender_account_no = serializers.CharField(source='sender_transaction.customer_account.account_no',read_only=True)
    sender_transaction      = serializers.CharField(source='sender_transaction.transaction.id',read_only=True)
    

    #Reciever Account details
    reciever_customer_name = serializers.CharField(source='reciever_transaction.customer_account.account_customer.name',read_only=True)
    reciever_customer_member_number = serializers.CharField(source='reciever_transaction.customer_account.account_customer.member_number',read_only=True)
    reciever_customer_type = serializers.CharField(source='reciever_transaction.customer_account.account_customer.branch_customer_type.id',read_only=True)
    reciever_product_name  = serializers.CharField(source='reciever_transaction.customer_account.account_product.product_name',read_only=True)
    reciever_currency      = serializers.CharField(source='reciever_transaction.customer_account.account_product.currency',read_only=True)
    reciever_customer_type_name = serializers.CharField(source="reciever_transaction.customer_account.account_customer.branch_customer_type.customer_type",read_only=True)
    reciever_customer_address = serializers.CharField(source="reciever_transaction.customer_account.customer_address",read_only=True)
    reciever_customer_account = serializers.CharField(source='reciever_transaction.customer_account.id',read_only=True)
    reciever_account_no = serializers.CharField(source='reciever_transaction.customer_account.account_no',read_only=True)
    reciever_transaction      = serializers.CharField(source='reciever_transaction.transaction.id',read_only=True)
    
    class Meta:
        model = TransferTransactions
        fields = '__all__'

class CustomerSavingAccountsSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(read_only=True)
    product_name = serializers.CharField(source='account_product.product_name',read_only=True)
    account_no = serializers.CharField(read_only=True)
    saving_product_id = serializers.CharField(source='account_product.id',read_only=True)
    product_chart = serializers.CharField(source='account_product.accounts_chart.id',read_only=True)
    status = serializers.CharField(read_only=True)
    account_closure_fee = serializers.FloatField(source='account_product.account_closure_fee', read_only=True)

    class Meta:
        model = SavingAccount
        fields = ['id', 'product_name', 'account_no','saving_product_id', 'product_chart', 'status', 'account_closure_fee']


class SavingAccountStatementSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(read_only=True)
    transaction = SystemTransactionsSerializer()
    
    class Meta:
        model = SavingAccountTransactions
        fields = ['id', 'transaction']

class FixedDepositSceduleSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(read_only=True)
    reference_transaction = SystemTransactionsSerializer()
    
    class Meta:
        model = FixedDepositSchedule
        fields = '__all__'

class FixedDepositSummarySerializer(serializers.ModelSerializer):
    
    #Account details
    product_name  = serializers.CharField(source='saving_account.account_product.product_name',read_only=True)
    currency      = serializers.CharField(source='saving_account.account_product.currency.currency_code',read_only=True)
    account_no         = serializers.CharField(source='saving_account.account_no',read_only=True)
    branch             = serializers.CharField(read_only=True)
    formatted_period  = serializers.SerializerMethodField(read_only=True, required=False)
    maturity_days = serializers.SerializerMethodField(read_only=True, required=False)
    interest_rate =  serializers.SerializerMethodField(read_only=True, required=False)
    interest =  serializers.SerializerMethodField(read_only=True, required=False)
    schedule =  serializers.SerializerMethodField(read_only=True, required=False)
    
    def get_interest(self, fixed_deposit):
        interest = {
            'paid': 0,
            'pending': 0,
            'acrued': 0
        }
        paid = FixedDepositSchedule.objects.active().filter(fixed_deposit=fixed_deposit, status='paid').aggregate(total=Sum('interest'))['total']
        pending = FixedDepositSchedule.objects.active().filter(fixed_deposit=fixed_deposit, status='pending').aggregate(total=Sum('interest'))['total']
        acrued = FixedDepositSchedule.objects.active().filter(fixed_deposit=fixed_deposit, expected_date__date__lte=date.today()).aggregate(total=Sum('interest'))['total']

        if paid:
            interest['paid'] = paid

        if pending:
            interest['pending'] = pending

        if acrued:
            interest['acrued'] = acrued
        
        
        return interest
    
    def get_schedule(self, fixed_deposit):
        schedule = FixedDepositSchedule.objects.active().filter(fixed_deposit=fixed_deposit).order_by('id')
        return FixedDepositSceduleSerializer(schedule, many=True).data
    
    def get_maturity_days(self,instance):
        current_date  = make_aware(datetime.strptime(datetime.now().strftime("%Y-%m-%d"), '%Y-%m-%d'))
        expected_date = make_aware(datetime.strptime(instance.record_date.strftime("%Y-%m-%d") + ' 23:59:59','%Y-%m-%d %H:%M:%S'))

        if instance.period_type == 'y':
            expected_date = expected_date +  timedelta(days= 12 * 30 * instance.period)
        if instance.period_type == 'q':
            expected_date = expected_date + timedelta(days= 3 * 30 * instance.period)
        if instance.period_type == 'm':
            expected_date = expected_date + timedelta(days= 1 * 30 * instance.period)
        if instance.period_type == 'd':
            expected_date = expected_date + timedelta(days= 1 * instance.period) 
    
        return (expected_date - current_date).days
    
    def get_interest_rate(self, instance):
        return instance.interest
   
    def get_formatted_period(self, instance):
        return str(instance.period) + ' ' + self.format_period(instance.period_type)
    
    def format_period(self,periodType):
        if periodType == 'y':
           return 'Years'
        if periodType == 'q':
           return 'Quarters'
        if periodType == 'm':
           return 'Months'
        if periodType == 'd':
           return 'Days'
        
    class Meta:
        model = FixedDeposit
        fields = '__all__'

class CustomerFixedDepositSerializer(serializers.ModelSerializer):
    fixed_deposits = serializers.SerializerMethodField(read_only=True, required=False)

    def get_fixed_deposits(self, customer):
        deposits = FixedDeposit.objects.filter(saving_account__account_customer=customer, deleted=False)
        return FixedDepositSummarySerializer(deposits, many=True).data

    class Meta:
        model = Customer
        fields = ['fixed_deposits']

class SavingsProductInterestPaymentSerializer(serializers.ModelSerializer):
    branch_name      = serializers.CharField(source='branch.name',read_only=True)
    product_name     = serializers.CharField(source='product.product_name',read_only=True)
    days_from        = serializers.SerializerMethodField(read_only=True)

    def get_days_from(self, interest_payment):
        time = timezone.now()
        time = make_aware(datetime.strptime(time.strftime("%Y-%m-%d"), '%Y-%m-%d'))
        date_diff = time - interest_payment.record_date
        return  date_diff.days + 1
    
    class Meta:
        model  = SavingsProductInterestPayment
        fields = '__all__'
        

class InterestPaymentTransactionSerializer(serializers.ModelSerializer):
    #Interest details
    int_rate     =  serializers.CharField(source="interest_payment.int_rate",read_only=True)
    tax_on_int   = serializers.CharField(source="interest_payment.tax_on_int",read_only=True)
    
    #Trnasaction details
    amount       =  serializers.CharField(source="savings.transaction.amount",read_only=True)
    heading      = serializers.CharField(source="savings.transaction.heading",read_only=True)
    reference_no = serializers.CharField(source="savings.transaction.reference_no",read_only=True)
    branch       =  serializers.CharField(source="savings.transaction.branch",read_only=True)
    voucher_no   =  serializers.CharField(source="savings.transaction.voucher_no",read_only=True)
    payment_method   = serializers.CharField(source="savings.transaction.payment_method",read_only=True)
    transaction_type =  serializers.CharField(source="savings.transaction.transaction_type",read_only=True)
    coment      = serializers.CharField(source="savings.transaction.coment",read_only=True)
    record_date = serializers.CharField(source="savings.transaction.record_date",read_only=True)
    added_by    = serializers.CharField(source="savings.transaction.added_by.user_staff",read_only=True)
    date_added  = serializers.CharField(source="savings.transaction.date_added",read_only=True)

    #Account details
    customer_name = serializers.CharField(source='savings.customer_account.account_customer.name',read_only=True)
    customer_member_number = serializers.CharField(source='savings.customer_account.account_customer.member_number',read_only=True)
    telephone = serializers.CharField(source='savings.customer_account.account_customer.telephone',read_only=True)
    customer_type = serializers.CharField(source='savings.customer_account.account_customer.branch_customer_type.id',read_only=True)
    product_name  = serializers.CharField(source='savings.customer_account.account_product.product_name',read_only=True)
    currency      = serializers.CharField(source='savings.customer_account.account_product.currency',read_only=True)
    customer_type_name = serializers.CharField(source="savings.customer_account.account_customer.branch_customer_type.customer_type",read_only=True)
    customer_address = serializers.CharField(source="savings.customer_account.customer_address",read_only=True)
    customer_account = serializers.CharField(source='savings.customer_account.id',read_only=True)
    account_no = serializers.CharField(source='savings.customer_account.account_no',read_only=True)
    transaction      = serializers.CharField(source='savings.transaction.id',read_only=True)
    
    class Meta:
        model  = InterestPaymentTransaction
        fields = '__all__'


class SchoolFeesOrganIntegrationSerializer(serializers.ModelSerializer):
    id = serializers.CharField(read_only=True)
    date_added = serializers.CharField(read_only=True)
    organisation_name = serializers.CharField(read_only=True, source='organisation.name')
    chart_name = serializers.CharField(read_only=True, source='account_chart.account_name')

    class Meta:
        model  = SchoolFeesOrganIntegration
        fields = '__all__'


class CutomerOrganObligationSerializer(serializers.ModelSerializer):
    added_by  = serializers.CharField(read_only=True)
    date_added  = serializers.CharField(read_only=True)
    last_updated = serializers.CharField(read_only=True)
    organisation = serializers.CharField(read_only=True)
    source_chart_name = serializers.CharField(read_only=True, source='source_chart.account_name')
    destination_chart_name = serializers.CharField(read_only=True, source='destination_chart.account_name')
    
    class Meta:
        model = CustomerObligations
        fields = '__all__'''

class CutomerSubscribeObligationSerializer(serializers.ModelSerializer):
    added_by  = serializers.CharField(read_only=True)
    date_added  = serializers.CharField(read_only=True)
    last_updated = serializers.CharField(read_only=True)
    obligation_type = serializers.CharField(read_only=True, source='obligation.obligation_type')
    source_chart_name = serializers.CharField(read_only=True, source='customer_source_chart.account_name')
    destination_chart_name = serializers.CharField(read_only=True, source='obligation.destination_chart.account_name')
    start_day = serializers.CharField(read_only=True, source='obligation.start_day')
    end_day = serializers.CharField(read_only=True, source='obligation.end_day')
    name = serializers.CharField(read_only=True, source='obligation.name')
    
    class Meta:
        model = CustomerObligationSubscription
        fields = '__all__'''
