from rest_framework.views import APIView
from rest_framework.response import Response
from django.db.models import Q
from rest_framework import viewsets
from rest_framework.filters import SearchFilter, OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend
import requests
from rest_framework import status
from decouple import config
from .models import *
from .serializers import *
from customers.models import Customer
from ledgers.ledgers_helper import generate_reference_no, get_inter_branch_chart
from ussdbanking.helpers import get_branch_wallet_chart, get_basic_auth_token
from savings.models import *
from savings.savings_bal_helper import get_account_balance
from exservices.exservices_helper import send_customer_sms, format_phone_number
from savings.savings_helper import (
    assert_savings_account_can_debit,
    assert_savings_account_can_credit,
    save_reciever_transactions,
    save_sender_transactions,
    sync_savings_account_lifecycle,
    thread_multiple_booking_payments,
    update_savings_account_statuses,
)
from questbanker_api.utils import get_current_user
from mmbanking.models import MobileBankingSubscription
from integrations.helper import *

class SaccoCustomerValidationViewSet(APIView):
    ''' Validate sacco customer '''

    def get(self, request, format=None):
        return  Response({"message":" Method Supported"})
    
    def post(self, request, format=None):
        saccoId    = request.data.get('saccoId')
        requestReference   = request.data.get('requestReference')
        memberId    = request.data.get('memberId')
        amount = request.data.get('Amount')
        thirdParty = request.data.get('thirdParty')

        response = {"StatusCode":"52", "StatusDesc":"Invalid Sacco ID"}
        sacco_details = OrganisationThirdPartyIntegration.objects.filter(sacco_id__iexact=saccoId, is_active=True, third_party=thirdParty).first()
        if sacco_details:
            customer = Customer.objects.filter((Q(member_number__iexact=memberId) | Q(old_member_number__iexact=memberId)), customer_branch__branch_organisation=sacco_details.organisation).first()
            if customer:
                customer_account = SavingAccount.objects.filter(
                    account_customer=customer,  deleted=False,status='active').order_by('-id').first()

                available_balance = 0
                if customer_account:
                    account_balance   = get_account_balance(customer_account.id)
                    available_balance = account_balance['balance_raw'] if account_balance['balance_raw'] > 0 else 0
                response =  {"StatusCode": "00","StatusDesc": "Completed successfully", "requestReference": requestReference, "customer_name": customer.name, "available_balance": available_balance}
            else:
                response = {"StatusCode":"53", "StatusDesc":"Invalid Member ID"}

        return Response(response)

class RequestToDepositViewSet(APIView):
    ''' Request to deposit '''

    def get(self, request, format=None):
        return  Response({"message":" Method Supported"})
    
    def post(self, request, format=None):
        saccoId    = request.data.get('saccoId')
        requestReference   = request.data.get('requestReference')
        memberId    = request.data.get('memberId')
        amount = request.data.get('Amount')
        customerMobile = request.data.get('customerMobile')
        narrative = request.data.get('Narrative')
        thirdParty = request.data.get('thirdParty')

        response = {"StatusCode": '57', "StatusDesc": "Failed to make deposit"}

        # customer
        if not memberId:
            return Response({"StatusCode": '53', "StatusDesc": "Invalid Member ID"})

        if not saccoId:
            return Response({"StatusCode": '52', "StatusDesc": "Invalid Sacco ID"})

        sacco_details = OrganisationThirdPartyIntegration.objects.filter(sacco_id__iexact=saccoId, is_active=True, third_party=thirdParty).first()
        if sacco_details:
            customer = Customer.objects.filter((Q(member_number__iexact=memberId) | Q(old_member_number__iexact=memberId)), customer_branch__branch_organisation=sacco_details.organisation).first()
            if customer:
                update_savings_account_statuses(customer_id=customer.id)

                depositor_name = customer.name
                heading = 'FlexiPay Deposit: by ' + depositor_name + \
                    '-' + str(customerMobile) + ' Ref:' + str(requestReference)

                organisation_id = customer.customer_branch.branch_organisation.id
                organisation_branch_id = customer.customer_branch.id

                customer_account = SavingAccount.objects.filter(
                    account_customer=customer,  deleted=False,status='active').order_by('-id').first()

                if customer_account:
                    assert_savings_account_can_credit(customer_account, 'deposits')
                    reference_no = generate_reference_no(
                        customer_account.account_product.accounts_chart.account_line, organisation_id, 'mm-dep')

                    mobile_money_wallet_chart = get_branch_wallet_chart(organisation_id, organisation_branch_id)
                    if mobile_money_wallet_chart:
                        data = {"amount": amount, "heading": heading, "reference_no": reference_no, "payment_method": "offset", "voucher_no": "", "branch_id": organisation_branch_id,
                                "coment": narrative, "debit_chart_id": mobile_money_wallet_chart.id, "credit_chart_id": customer_account.account_product.accounts_chart.id}
                        system_transaction = SystemTransactions.objects.create(
                            **data)
                        if system_transaction:
                            saved_transaction_fields = {
                                "transaction_type": 'deposit',
                                "customer_account_id": customer_account.id,
                                "transaction_id": system_transaction.id
                            }
                            save_trans = SavingAccountTransactions.objects.create(
                                **saved_transaction_fields)
                            
                            data = {"sms_key": "cash_deposit_sms", "customer_account": customer_account, "user": self.request.user, "branch_id": organisation_branch_id, "save_trans": save_trans,"customer":customer_account.account_customer}
                            send_customer_sms(data)
                            sync_savings_account_lifecycle(customer_account)

                            # Process account booking payments
                            thread_multiple_booking_payments(customer_account, organisation_id, customer_account.customer_branch.id, self.request.user.id)

                            response = {"StatusCode": "00","StatusDesc": "Completed successfully", "requestReference": requestReference}
        
        return Response(response)

class RequestToWithdrawViewSet(APIView):
    ''' Request to withdraw '''

    def get(self, request, format=None):
        return  Response({"message":" Method Supported"})
    
    def post(self, request, format=None):
        saccoId    = request.data.get('saccoId')
        requestReference   = request.data.get('requestReference')
        memberId    = request.data.get('memberId')
        amount = int(request.data.get('Amount'))
        customerMobile = request.data.get('customerMobile')
        narrative = request.data.get('Narrative')
        thirdParty = request.data.get('thirdParty')

        response = {"StatusCode": '57', "StatusDesc": "Failed to make withdraw"}

        # customer 
        if not memberId:
            return Response({"StatusCode": '53', "StatusDesc": "Invalid Member ID"})

        if not saccoId:
            return Response({"StatusCode": '52', "StatusDesc": "Invalid Sacco ID"})

        sacco_details = OrganisationThirdPartyIntegration.objects.filter(sacco_id__iexact=saccoId, is_active=True, third_party=thirdParty).first()
        if sacco_details:
            customer = Customer.objects.filter((Q(member_number__iexact=memberId) | Q(old_member_number__iexact=memberId)), customer_branch__branch_organisation=sacco_details.organisation).first()
            if customer:
                update_savings_account_statuses(customer_id=customer.id)

                # validate phone number
                member_mm_sub = MobileBankingSubscription.objects.filter(customer=customer, active=True).order_by('-id').first()
                if not member_mm_sub:
                    return Response({"StatusCode": '54', "StatusDesc": "Invalid Wallet Phone Number"})

                telephone = format_phone_number(member_mm_sub.telephone_no)
                if telephone != customerMobile:
                    return Response({"StatusCode": '54', "StatusDesc": "Invalid Wallet Phone Number"})

                depositor_name = customer.name
                heading = 'FlexiPay Withdrawal by ' + depositor_name + '-' + str(customerMobile) + ' Ref:'+ str(requestReference)
                organisation_id = customer.customer_branch.branch_organisation.id
                organisation_branch_id = customer.customer_branch.id

                customer_account = SavingAccount.objects.filter(
                    account_customer=customer,  deleted=False,status='active' ).order_by('-id').first()

                if customer_account:
                    assert_savings_account_can_debit(customer_account, 'withdrawals')
                    reference_no = generate_reference_no(
                        customer_account.account_product.accounts_chart.account_line, organisation_id, 'mm-wd')
                    
                    mobile_money_wallet_chart = get_branch_wallet_chart(organisation_id, organisation_branch_id)
                    account_balance   = get_account_balance(customer_account.id)
                    if account_balance['balance_raw'] >= (amount) and mobile_money_wallet_chart:
                        transaction_fields = {
                            "heading": heading,
                            "coment": narrative,
                            "amount": amount,
                            "debit_chart": customer_account.account_product.accounts_chart,
                            "credit_chart": mobile_money_wallet_chart,
                            "reference_no": reference_no,
                            "voucher_no": '',
                            "payment_method": 'offset',
                            "branch": customer.customer_branch
                        }

                        system_transaction = SystemTransactions.objects.create(
                            **transaction_fields)
                        if system_transaction:
                            saved_transaction_fields = {
                                "transaction_type": 'withdrawal',
                                "customer_account_id": customer_account.id,
                                "transaction_id": system_transaction.id
                            }
                            save_trans = SavingAccountTransactions.objects.create(
                                **saved_transaction_fields)
                            
                            # send sms
                            data = {"sms_key": "cash_withdraw_sms", "customer_account": customer_account,
                                "user": self.request.user, "branch_id": customer.customer_branch.id, "save_trans": save_trans,"customer":customer_account.account_customer}
                            send_customer_sms(data)
                            sync_savings_account_lifecycle(customer_account)

                            response = {"StatusCode": "00","StatusDesc": "Completed successfully", "requestReference": requestReference}
                    else:
                        response = {"StatusCode": "51","StatusDesc": "Insufficient Balance", "requestReference": requestReference}
        return Response(response)

class RequestToValidateBalanceViewSet(APIView):
    ''' Request to withdraw '''

    def get(self, request, format=None):
        return  Response({"message":" Method Supported"})
    
    def post(self, request, format=None):
        saccoId    = request.data.get('saccoId')
        requestReference   = request.data.get('requestReference')
        memberId    = request.data.get('memberId')
        customerMobile = request.data.get('customerMobile')
        thirdParty = request.data.get('thirdParty')
        amount = int(request.data.get('Amount'))

        response = {"StatusCode": '51', "StatusDesc": "Insufficient Balance"}

        # customer 
        if not memberId:
            return Response({"StatusCode": '53', "StatusDesc": "Invalid Member ID"})

        if not saccoId:
            return Response({"StatusCode": '52', "StatusDesc": "Invalid Sacco ID"})

        sacco_details = OrganisationThirdPartyIntegration.objects.filter(sacco_id__iexact=saccoId, is_active=True, third_party=thirdParty).first()
        if sacco_details:
            customer = Customer.objects.filter((Q(member_number__iexact=memberId) | Q(old_member_number__iexact=memberId)), customer_branch__branch_organisation=sacco_details.organisation).first()
            if customer:
                customer_account = SavingAccount.objects.filter(
                    account_customer=customer,  deleted=False,status='active').order_by('-id').first()

                if customer_account:
                    account_balance   = get_account_balance(customer_account.id)
                    if account_balance['balance_raw'] >= (amount):
                        response = {"StatusCode": "00","StatusDesc": "Completed successfully", "requestReference": requestReference, 'balance':account_balance['balance_raw']}

        return Response(response)


class ClassificationsView(viewsets.ModelViewSet):
    queryset = Classifications.objects.all().order_by('id')
    serializer_class = ClassificationsSerializer
    filter_backends = (SearchFilter, OrderingFilter, DjangoFilterBackend, )
    filterset_fields = ['name', 'classification_type']
    search_fields = ('name', )
    ordering_fields = ['name', ]

class ClassificationItemsView(viewsets.ModelViewSet):
    queryset = ClassificationItems.objects.all().order_by('id')
    serializer_class = ClassificationItemsSerializer
    filter_backends = (SearchFilter, OrderingFilter, DjangoFilterBackend, )
    filterset_fields = ['name', 'classification']
    search_fields = ('name', )
    ordering_fields = ['name', ]

class ClassificationItemLoansView(viewsets.ModelViewSet):
    queryset = ClassificationItemLoans.objects.all().order_by('id')
    serializer_class = ClassificationItemLoansSerializer
    filter_backends = (SearchFilter, OrderingFilter, DjangoFilterBackend, )
    filterset_fields = ['id', ]
    search_fields = ('id', )
    ordering_fields = ['id', ]

    def get_queryset(self):
        organisation_id = get_current_user(self.request, 'organisation_id', 1) 
        return  ClassificationItemLoans.objects.filter(classification_item_loan__organisation_branch__branch_organisation__id=organisation_id ) 
    
    def perform_create(self, serializer):
        instance = serializer.save(item_loan_added_by=self.request.user)


class SchoolFeesSearchStudentViewSet(APIView):
    """Search for a student for school fees payment."""

    def get(self, request, format=None):
        return Response({"message": "Method Supported"})

    def post(self, request, format=None):
        results = []
        student_number = request.data.get('student_number')

        if not student_number:
            return Response({"results": results, "count": 0})

        organisation_id = get_current_user(self.request, 'organisation_id', None)
        school_code = student_number[:5]

        # Fetch the school integration
        school = SchoolFeesIntegrations.objects.filter(
            school_code=school_code,
            school_organisation__id=organisation_id
        ).first()

        if not school:
            return Response({"results": results, "count": 0})

        # Fetch the customer's active saving account
        customer_account = SavingAccount.objects.filter(
            account_customer=school.customer,
            deleted=False,
            status='active'
        ).order_by('-id').first()

        if not customer_account:
            return Response({"results": results, "count": 0})

        # Check if school hub integration is active
        service_provider = SchoolFeesOrganIntegration.objects.filter(
            organisation__id=organisation_id,
            is_active=True
        ).order_by('-id').first()

        if service_provider and service_provider.third_party == 'school_hub':
            results = handle_school_hub_validate(customer_account, student_number, school)
            return Response({"results": results, "count": len(results)})

        # Fallback: Akello-Pay integration
        try:
            basic_token = get_basic_auth_token()
            auth_response = requests.post(
                config('PAYMENT_GATEWAY_URL') + 'akello-pay/token-auth',
                json={"grant_type": "client_credentials"},
                headers={
                    "Content-Type": "application/x-www-form-urlencoded",
                    "Authorization": f"Basic {basic_token}"
                },
                timeout=10
            )
            auth_response.raise_for_status()
            access_token = auth_response.json().get('access_token')

            if access_token:
                validate_response = requests.post(
                    config('PAYMENT_GATEWAY_URL') + 'api/akello-pay/sure-pay/request-to-validate-student/',
                    json={"accountNumber": student_number},
                    headers={
                        "Content-Type": "application/json",
                        "Authorization": f"Bearer {access_token}"
                    },
                    timeout=10
                )
                validate_response.raise_for_status()
                student = validate_response.json()
                results.append({
                    "accountNumber": student.get('accountNumber'),
                    "accountName": student.get('accountName'),
                    "accountProvider": student.get('accountProvider'),
                    "outstandingBalance": student.get('outstandingBalance'),
                    "accountType": student.get('accountType'),
                    "customer_id": school.customer.id,
                    "customer_name": school.customer.name,
                    "saving_account_id": customer_account.id
                })

        except requests.exceptions.RequestException as e:
            # Optionally log e
            pass

        return Response({"results": results, "count": len(results)})



class MakeFeesPaymentViewSet(APIView):
    ''' Make Payment '''

    def get(self, request, format=None):
        return  Response({"message":" Method Supported"})
    
    def post(self, request, format=None):
        results = {"statusDesc": 'Error Occurred'}
        status_code = status.HTTP_500_INTERNAL_SERVER_ERROR

        payment_method    = request.data.get('payment_method', None)
        account    = request.data.get('account', None)
        amount    = request.data.get('amount', None)
        record_date    = request.data.get('record_date', None)
        deposited_by    = request.data.get('deposited_by', None)
        comment    = request.data.get('comment', None)
        voucher_no    = request.data.get('voucher_no', None)
        saving_account_id    = request.data.get('saving_account_id', None)

        account_number    = request.data.get('account_number', None)
        account_name    = request.data.get('account_name', None)
        account_provider = request.data.get('account_provider', None)

        organisation_id = get_current_user(self.request, 'organisation_id', None)
        branch_id = get_current_user(self.request, 'organisation_branch_id', None)

        if not payment_method:
            return Response({"statusDesc":"No payment method provided"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        
        if not account:
            return Response({"statusDesc":"No account provided"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        
        if not record_date:
            return Response({"statusDesc":"No date provided"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        if not amount:
            return Response({"statusDesc":"No amount provided"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        if not account_number:
            return Response({"statusDesc":"No student acc"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        if not account_name:
            return Response({"statusDesc":"No student name"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        if not account_provider:
            return Response({"statusDesc":"No School name"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        if not saving_account_id:
            return Response({"statusDesc":"No School Saving Account"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        savings_account = None
        selected_account = None
        if payment_method == 'offset':
            savings_account = SavingAccount.objects.get(pk=account)
            if not savings_account:
                return Response({"statusDesc":"No account provided"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

            selected_account = savings_account.account_product.accounts_chart
            account_balance = get_account_balance(savings_account)['balance_raw']
            
            if account_balance < int(amount):
                return Response({"statusDesc":"Insufficient balance"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        else:
            selected_account = OrganisationSubAccount.objects.get(pk=account)
            if not selected_account:
                return Response({"statusDesc":"account not found"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        # school account
        destination_saving_account = SavingAccount.objects.filter(id=saving_account_id).first()
        if not destination_saving_account:
            return Response({"statusDesc":"No School Saving Account"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        destination_chart_account = destination_saving_account.account_product.accounts_chart


        service_provider = SchoolFeesOrganIntegration.objects.filter(organisation__id=organisation_id, is_active=True).order_by('-id').first()
        response = None
        if service_provider and service_provider.third_party == 'school_hub':
            data = {
                "accountNumber": account_number,
                "accountName": account_name,
                "amount":amount,
                "record_date":record_date,
                "narration":"Fees Payment",
                "source":"sacco"
            }
            response = handle_school_hub_payment(data)
            print(response)
        else:

            # Make sure pay payment
            basic_token = get_basic_auth_token()
            auth_response = requests.post(
                config('PAYMENT_GATEWAY_URL') + 'akello-pay/token-auth',
                json = {"grant_type": "client_credentials"},
                headers = {
                    "Content-Type": "application/x-www-form-urlencoded",
                    "Authorization": f"Basic {basic_token}"
                }
            )

            if auth_response.status_code == 200:
                data = {
                    "accountNumber": account_number,
                    "accountName": account_name,
                    "amount":amount,
                    "record_date":record_date,
                    "narration":"Fees Payment"
                }
                response_data = response.json()
                response = requests.post(
                    config('PAYMENT_GATEWAY_URL') + 'api/akello-pay/sure-pay/request-to-pay/',
                    json = data,
                    headers = {
                        "Content-Type": "application/json",
                        "Authorization": f"Bearer {response_data['access_token']}"
                    }
                )

        if response and response.status_code == 200:
            payment_obj = response.json()
            if payment_method == 'offset':
                heading = f'Cash transfer: for {account_name} - {account_number} by {deposited_by}'

                sender_obj= {"charge": 0, "id": destination_saving_account.id, "amount": amount, "date": record_date}
                extra_data = { "sender_id": savings_account.id, "send_sms": True, "description": comment if comment else 'Fees Payment', "heading":heading, "voucher_no":voucher_no }

                # Save sender transactions details
                saved_transaction = save_sender_transactions(request.user, request, sender_obj, extra_data)
                if not saved_transaction:
                    return Response({"statusDesc":"Sender transaction not posted."}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

                # Save reciever transactions details
                receiver_obj= {"charge": 0, "id": destination_saving_account.id, "amount": amount, "date": record_date}
                extra_data = { "sender_id": savings_account.id, "send_sms": True, "description": comment if comment else 'Fees Payment', "heading":heading, "voucher_no":voucher_no }
                saved_reciever = save_reciever_transactions(request.user, request, receiver_obj, extra_data)
                if not saved_reciever:
                    return Response({"statusDesc":"Reciever transaction not posted."}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

                # Reconcile inter-branch transactions
                if savings_account.customer_branch.id != destination_saving_account.customer_branch.id:
                    inter_branch_trans_field = {
                        "source_transaction":saved_transaction.transaction,
                        "destination_transaction":saved_reciever.transaction,
                        "added_by":request.user
                    }
                    InterBranchTransactions.objects.create(**inter_branch_trans_field)
            
                # Save transfer transactions details mapping
                transfer_fields = {
                    "sender_transaction": saved_transaction,
                    "reciever_transaction": saved_reciever
                }
                transfer_details = TransferTransactions.objects.create(**transfer_fields)
                if not transfer_details:
                    return Response({"statusDesc":"Mapping transaction not posted."}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

                # save school fees transaction
                payment_data = {"transaction": saved_transaction.transaction, "third_party_transaction_id": payment_obj['transactionId'], "student_number": account_number, "student_name":account_name,
                "third_party_school_name": account_provider, "customer_account":destination_saving_account, "branch": OrganisationBranch.objects.get(pk=branch_id) }
                SchoolFeesPaymentTransactions.objects.create(**payment_data)
                
                results = {"statusDesc": 'Payment Successfully'}
                status_code =status.HTTP_200_OK
                thread_multiple_booking_payments(destination_saving_account, organisation_id, destination_saving_account.customer_branch.id, self.request.user.id)

            else:
                # InterBranch chart
                interbranch_chart = get_inter_branch_chart(OrganisationBranch.objects.get(pk=branch_id), destination_saving_account.customer_branch)
                reference_no = generate_reference_no(destination_chart_account.account_line, organisation_id, 'dep')
                transaction_fields = {
                    "heading": f'Deposit: for {account_name} - {account_number} by {deposited_by}',
                    "coment": comment,
                    "amount": amount,
                    "credit_chart": destination_chart_account,
                    "debit_chart": selected_account,
                    "reference_no": reference_no,
                    "voucher_no": self.request.data.get('voucher_no'),
                    "record_date": self.request.data.get('record_date'),
                    "payment_method": self.request.data.get('payment_method'),
                    "added_by": request.user,
                    "branch": OrganisationBranch.objects.get(pk=branch_id),
                }

                # Handle inter-branch transactions update  -> soure branch
                if branch_id != destination_saving_account.customer_branch.id:
                    transaction_fields["heading"] = f'Inter-branch deposit: for {account_name} - {account_number} by {deposited_by}', 
                    transaction_fields["credit_chart"] = interbranch_chart

                # Register deposit transactions
                saved_transaction = SystemTransactions.objects.create(**transaction_fields)

                if saved_transaction:
                    save_trans = None
                    # Handle inter-branch transactions update  -> destination branch
                    if branch_id != destination_saving_account.customer_branch.id:
                        transaction_fields["credit_chart"] = destination_chart_account
                        transaction_fields["branch"] = destination_saving_account.customer_branch
                        transaction_fields["debit_chart"] = interbranch_chart
                        transaction_fields["payment_method"] = 'settlement'
                        inter_branch_trans = SystemTransactions.objects.create(**transaction_fields)

                        # Reconcile inter-branch transactions
                        if inter_branch_trans:
                            inter_branch_trans_field = {
                                "source_transaction": saved_transaction,
                                "destination_transaction": inter_branch_trans,
                                "added_by": request.user,
                            }
                            InterBranchTransactions.objects.create(**inter_branch_trans_field)

                            # Register saving deposit transaction mapping for inter-branch
                            savings_trans_field = {
                                "transaction_type": 'deposit',
                                "transaction": inter_branch_trans,
                                "customer_account": destination_saving_account,
                            }
                            save_trans = SavingAccountTransactions.objects.create(**savings_trans_field)
                    else:
                        # add saving deposit transaction mapping for single branch
                        savings_trans_field = {
                            "transaction_type": 'deposit',
                            "transaction": saved_transaction,
                            "customer_account": destination_saving_account,
                        }
                        save_trans = SavingAccountTransactions.objects.create(**savings_trans_field)
                    
                    if save_trans:
                        # save school fees transaction
                        payment_data = {"transaction": saved_transaction, "third_party_transaction_id": payment_obj['transactionId'], "student_number": account_number, "student_name":account_name,
                        "third_party_school_name": account_provider, "customer_account":destination_saving_account, "branch": OrganisationBranch.objects.get(pk=branch_id) }
                        SchoolFeesPaymentTransactions.objects.create(**payment_data)
                        
                        results = {"statusDesc": 'Payment Successfully'}
                        status_code =status.HTTP_200_OK
                        thread_multiple_booking_payments(destination_saving_account, organisation_id, destination_saving_account.customer_branch.id, self.request.user.id)

                        # send customer message
                        # data = {"sms_key": "cash_deposit_sms", "customer_account": destination_saving_account, "user": self.request.user, "branch_id": branch_id, "save_trans": save_trans,"customer":destination_saving_account.account_customer}
                        # send_customer_sms(data)

                        # send sms to depositer
                            
        return  Response(results, status_code)

class RequestToSettleSchoolFeesPaymentViewSet(APIView):
    ''' Request to settle payment '''

    def get(self, request, format=None):
        return  Response({"message":" Method Supported"})
    
    def post(self, request, format=None):
        results = {"statusDesc": 'Error Occurred', "statusCode": "57"}

        accountNumber    = request.data.get('accountNumber', None)
        accountName    = request.data.get('accountName', None)
        amount    = request.data.get('amount', None)
        narration    = request.data.get('narration', None)
        record_date    = request.data.get('record_date', None)

        if not record_date or not accountNumber or not accountName or not amount:
            results = {"statusDesc": 'Missing Fields', "statusCode": "57"}
            return  Response(results)


        school_code = accountNumber[:5]

        school_account = SchoolFeesIntegrations.objects.filter(school_code=school_code).first()
        if not school_account:
            results = {"statusDesc": 'Error Occurred: school account not found', "statusCode": "57"}
            return  Response(results)

        savings_account = SavingAccount.objects.filter(
                account_customer=school_account.customer,  deleted=False,status='active' ).order_by('-id').first()

        is_school_fees_activate = SchoolFeesOrganIntegration.objects.filter(is_active=True, organisation=school_account.school_organisation).first()
        if not is_school_fees_activate or not savings_account:
            results = {"statusDesc": 'Error Occurred: account not active', "statusCode": "57"}
            return  Response(results)

        reference_no = generate_reference_no(savings_account.account_product.accounts_chart.account_line, is_school_fees_activate.organisation.id, 'dep')
        transaction_fields = {
            "heading": f'Deposit: by {accountName} for {school_account.customer.name} - {school_account.customer.old_member_number}',
            "coment": narration,
            "amount": amount,
            "credit_chart": savings_account.account_product.accounts_chart,
            "debit_chart": is_school_fees_activate.account_chart,
            "reference_no": reference_no,
            "voucher_no": '',
            "record_date": record_date,
            "payment_method": 'bank',
            "branch": savings_account.customer_branch
        }

        # Register deposit transactions
        saved_transaction = SystemTransactions.objects.create(**transaction_fields)
        if not saved_transaction:
            results = {"statusDesc": 'Error Occurred: failed to save transaction', "statusCode": "57"}
            return  Response(results)

        savings_trans_field = {
            "transaction_type": 'deposit',
            "transaction": saved_transaction,
            "customer_account": savings_account,
        }
        SavingAccountTransactions.objects.create(**savings_trans_field)

        results = {"statusDesc": 'Payment Successful', "statusCode": "00"}
        return  Response(results)


class GnugridIntegration(viewsets.ViewSet):
    """
    Handles GNUGrid credit score retrieval using customer's NIN and phone number.
    """

    def create(self, request, format=None):
      try:
        nin = request.data.get('nin')
        phone_number = request.data.get('phone_number')
        print(">>> Received request for credit score <<<")
        print("NIN:", nin, "Phone:", phone_number)

        auth_response = gnugrid_authenticate()
        print("Auth response:", auth_response)

        access_token = auth_response.get("access_token")
        if not access_token:
            print("Failed to authenticate")
            return Response({"error": "Failed to authenticate with GNUGrid"}, status=500)

        postData = {
            "identifier": nin,
            "entity_type": 0,
            "entity_type_category": "CONSUMER",
            "identification_type": "ii_national_id",
            "phone_number": phone_number,
            "client_consented": "Yes",
            "type": "CRB"
        }
        print("Payload:", postData)

        credit_score_response = gnugrid_credit_score(access_token, postData)
        print("Credit Score Response:", credit_score_response)

        return Response(credit_score_response, status=status.HTTP_200_OK)


      except Exception as e:
            return Response(
                {"error": "Error retrieving credit score", "details": str(e)},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
