import base64
import re
from django.db.models.signals import post_save
from django.dispatch import receiver
from datetime import datetime, date
import decimal
from django.contrib.sessions.models import Session
import os
import threading
from django.db import close_old_connections, transaction
import time
from dateutil.parser import parse as parse_datetime
from django.apps import apps
from django.utils.timezone import now, timedelta, make_aware
import io
from django.db.models import Q , Exists, OuterRef  # Add this import at the top of your file
from django.db import IntegrityError, transaction
import django.db.models as md
import random
from django.core.cache import cache
import uuid
from django.http import HttpResponseRedirect, JsonResponse, HttpResponseBadRequest
from django.http import HttpResponse
import requests
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
from openpyxl import Workbook, load_workbook
from openpyxl.utils import get_column_letter
from io import BytesIO
from rest_framework import status
import json
from mimetypes import guess_type
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404, render
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.hashers import check_password
from django.utils.decorators import method_decorator
from django.contrib.auth import authenticate, login, logout
from django.core.mail import send_mail, EmailMessage
from django.utils import timezone
import vonage
from django.conf import settings
from django.urls import reverse
from django.contrib.auth.hashers import make_password
import paypalrestsdk
from urllib.parse import urlencode
from django_daraja.mpesa.core import MpesaClient
from django.contrib.auth.decorators import login_required
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.authentication import TokenAuthentication
from rest_framework.parsers import MultiPartParser, FormParser
from requests.structures import CaseInsensitiveDict
from django.middleware.csrf import get_token
from django.views.decorators.csrf import csrf_protect
from .resources.LoanProducts import PRODUCTS

# from django_api_kwara.kwara_api_django.settings import DEFAULT_FROM_EMAIL
from .helpers import helper_return_fosa_balance, helper_return_fosa_account, helper_fosa_withdrawal,helper_send_sms, helper_return_member_phone_number, helper_send_guarantor_sms, helper_fetch_balances, helper_return_share_capital_balance
from .models import Payment, WithdrawRequest, ContactMessage,PassportPhoto, MpesaTransaction, BoardResolution, KraPin,ChamaOfficial, SpouseClaim, PrincipalClaim, ParentClaim, ParentInLawClaim, DependantClaim, InpatientClaim
from .serializers import LoanApplicationSerializer, SavingsApplicationSerializer, MemberSerializer, UserActivityLogSerializer, SpouseClaimSerializer, PrincipalClaimSerializer, ParentClaimSerializer, ParentInLawClaimSerializer, DependantClaimSerializer, InpatientClaimSerializer
import jwt
# from .serializers import MemberSerializer
from .helpers import get_P_access_token, get_access_token, get_iprs_access_token, get_id_access_token, generate_password, get_timestamp, generate_access_token, generate_mpesa_live_access_token, generate_kbs_mpesa_live_access_token
from .models import CustomUser, SavingsApplication, LoanApplication, NextOfKin, Guarantor, SavingsAccount, UserActivityLog, CorporateDocuments, SigningMandate, Security, LoanOriginationDocuments, Document, IndividualDocuments, ChamaMember, ChamaSigningMandate, PaypalDeposit, MpesaB2CCallback, TransactionLog, SMSLog

access_token = get_P_access_token()
# access_token = get_access_token()
# access_sandbox_token = get_access_token()
# access_PR_token = get_P_access_token()
# ID_access_token = get_id_access_token()

def extract_user(token):
    print("extract user called")
    try:
        payload = jwt.decode(f'{token}',settings.SECRET_KEY, algorithms=["HS256"] )
        # print(payload)
        return payload  # Dictionary containing token data
        # return JsonResponse(payload)
    except jwt.ExpiredSignatureError:
        return {"error": "Permission denied"}
    except jwt.InvalidTokenError:
        return {"error": "Permission denied"}


def index(request):
    return render(request, "api/index.html")

# def get_id_access_token(request):
#     consumer_key = "CK_NDIzODNmMTJiNmZh"
#     consumer_secret = "CS_NGZkNmM0MTc3NmI4ZDkzYWJj"
#     url = "https://api.spinmobile.co/api/analytics/auth/"
#     data = {
#         'consumer_key': consumer_key,
#         'consumer_secret': consumer_secret,
#     }
#     try:
#         print(f"Sending POST request to {url} with data: {data}")  # Debug request payload
#         response = requests.post(url, data=data)
#         print(f"API Response: {response.text}")
#         if response.status_code == 200:
#             token = response.json().get('token')
#             expires = response.json().get('expires')
#             if token:
#                 return JsonResponse({
#                     "token": token,
#                     "expires": expires
#                 }, status=200)
#             else:
#                 return JsonResponse({"error": "Token not found in the response"}, status=500)
#         else:
#             return JsonResponse({
#                 "error": f"Failed to fetch token, status code: {response.status_code}",
#                 "details": response.json()
#             }, status=response.status_code)
#     except Exception as e:
#         return JsonResponse({"error": f"An error occurred: {str(e)}"}, status=500)

def log_user_activity(user, activity, api_endpoint):
    """Function to log user activities."""
    UserActivityLog.objects.create(
        user=user,
        activity=activity,
        api_endpoint=api_endpoint,
        timestamp=timezone.now()  # Capture the timestamp of the activity
    )

def log_user_transaction(user, transaction_type,transaction_id,description,account_no,account_name,amount,status):
    """Function to log user transactions."""
    TransactionLog.objects.create(
        user=user,
        transaction_type=transaction_type,
        transaction_id=transaction_id,
        description=description,
        account_no=account_no,
        amount=amount,
        status=status,
        account_name=account_name,
    )

class SendOtpView(APIView):
    def post(self, request):
        phone = request.data.get('phone')
        if not phone:
            return JsonResponse({"error": "Phone number is required."}, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            user = CustomUser.objects.get(phone=phone)
        except CustomUser.DoesNotExist:
            return JsonResponse({"error": "Phone number does not exist."}, status=status.HTTP_404_NOT_FOUND)
        
        # Generate a 6-digit OTP
        otp_code = f"{random.randint(100000, 999999)}"
        cache_key = f"otp_{phone}"
        cache_timeout = 300  # 5 minutes

        # Store OTP in cache
        cache.set(cache_key, otp_code, timeout=cache_timeout)

        number = phone.lstrip("+")
        if number.startswith("254"):
                # Send SMS OTP
            sms_response = helper_send_sms(phone=number, message=f"Your KBS Internet Banking Password Reset OTP is: {otp_code}", department="User")

            if sms_response["responses"][0]["response-code"] == 200:
                return JsonResponse({"message": "OTP sent successfully."}, status=status.HTTP_200_OK)
                # log_user_activity(user, "Login initiated, OTP sent via SMS", request.path)
                otp_sent_via = "sms"
            else:
                return JsonResponse({'error': "Failed to send OTP via SMS. Please try again."}, status=500)
            
        else:
            # Send Email OTP
            try:
                send_mail(
                    "Kenya Bankers Internet Banking Password Reset OTP Verification",
                    f"Your Kenya Bankers Internet Banking Password Reset OTP is: {otp_code}",
                    settings.DEFAULT_FROM_EMAIL,
                    [user.email],  # Make sure user has an email field
                    fail_silently=False,
                    html_message=f'<p>Your Kenya Bankers Internet Banking Password Reset OTP is <strong>{otp_code}</strong></p>'
                )
                return JsonResponse({"message": "OTP sent successfully."}, status=status.HTTP_200_OK)
                # log_user_activity(user, "Login initiated, OTP sent via Email", request.path)
                otp_sent_via = "email"
            except Exception as e:
                return JsonResponse({'error': f"Failed to send OTP via Email: {str(e)}"}, status=500)

class VerifyOtpView(APIView):
    def post(self, request):
        phone = request.data.get('phone')
        entered_otp = request.data.get('otp')

        if not phone or not entered_otp:
            return JsonResponse({"error": "Phone and OTP are required."}, status=status.HTTP_400_BAD_REQUEST)

        cache_key = f"otp_{phone}"
        cached_otp = cache.get(cache_key)

        if cached_otp and str(cached_otp) == entered_otp:
            # OTP is valid; you can clear it from the cache if necessary
            cache.delete(cache_key)
            return JsonResponse({"message": "OTP verified successfully."}, status=status.HTTP_200_OK)
        else:
            return JsonResponse({"error": "Invalid or expired OTP."}, status=status.HTTP_400_BAD_REQUEST)


class ResetPasswordView(APIView):
    def post(self, request):
        phone = request.data.get('phone')
        new_password = request.data.get('newPassword')

        if not phone or not new_password:
            return JsonResponse({"error": "Phone and new password are required."}, status=status.HTTP_400_BAD_REQUEST)

        try:
            user = CustomUser.objects.get(phone=phone)
        except CustomUser.DoesNotExist:
            return JsonResponse({"error": "Phone number does not exist."}, status=status.HTTP_404_NOT_FOUND)

        user.password = make_password(new_password)
        user.save()

        return JsonResponse({"message": "Password reset successfully."}, status=status.HTTP_200_OK)
    
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def verify_session(request):
    return Response({"message": "Session is valid"}, status=200)

def get_csrf_token(request):
    return JsonResponse({'csrfToken': get_token(request)})

def health_check(request):
    return JsonResponse({"message" : "Server is On"}, status=200)

# @csrf_exempt
class DeactivateView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        user = request.user

        # Invalidate tokens by updating last_login (or last_logout if you use a separate field)
        user.last_login = now()
        user.save(update_fields=['last_login'])

        # Optionally blacklist refresh token if it was sent
        refresh_token = request.data.get("refresh")
        if refresh_token:
            try:
                token = RefreshToken(refresh_token)
                token.blacklist()  # requires blacklist app enabled
            except Exception as e:
                return Response({"detail": "Invalid refresh token."}, status=status.HTTP_400_BAD_REQUEST)

        return Response({"detail": "User logged out successfully."}, status=status.HTTP_200_OK)
    
class DeactivateUserAccount(APIView):
    def post(self, request,admin_sacco_user_id):
        token = request.headers.get("Authorization")
        if not token:
            return JsonResponse({"error": 'Permission denied'}, status=403)

        auth_response = extract_user(token=token)

        if "error" in auth_response:
            return JsonResponse({"error": auth_response["error"]}, status=401)
        user_id = auth_response.get("user_id") # user id from token

        auth_user = CustomUser.objects.get(sacco_user_id=user_id) #user from token
        
        sacco_user_id = request.data.get("sacco_user_id") # user to be updated from frontend

        if not sacco_user_id:
            return Response({"detail": "sacco_user_id is required."}, status=status.HTTP_400_BAD_REQUEST)

        if sacco_user_id != admin_sacco_user_id and auth_user.role != "Admin":
            # we're checking if the user making an update is an admin 
            return JsonResponse({"error": 'permission denied'}, status=403)

        try:
            user = CustomUser.objects.get(pk=sacco_user_id)
        except CustomUser.DoesNotExist:
            return Response({"detail": "User not found."}, status=status.HTTP_404_NOT_FOUND)

        # Invalidate access token (via last_login timestamp)
        user.last_login = now()
        user.is_active = not user.is_active
        user.save()

        User_status = "Activated" if user.is_active else "Deactivated"

        log_user_activity(auth_user,f"{sacco_user_id} user status {User_status}" , request.path)

        return Response({"detail": f"User {sacco_user_id} logged out successfully."}, status=status.HTTP_200_OK)

# @csrf_protect
@csrf_exempt
def login_view(request):
    if request.method == 'POST':
        # csrf_token = get_token(request)
        data = json.loads(request.body)
        phone = data.get('phone')
        password = data.get('password')

        # user = authenticate(phone=phone, password=password)
        try:
            user = CustomUser.objects.get(phone=phone)  # Adjust according to your User model
        except CustomUser.DoesNotExist:
            # log_user_activity(user, "Invalid login phone number from user", request.path)
            return JsonResponse({'error': 'Invalid phone'}, status=400)
        
        if user.is_active == False:
            log_user_activity(user, "Deactivated member trying to login", request.path)
            return JsonResponse({'error': "User Deactivated"})

        if not user.check_password(password):  # Ensure you hash and check the password securely
            log_user_activity(user, "Invalid login password from user", request.path)
            return JsonResponse({'error': 'Invalid password'}, status=400)
        
        # Check if user already has an active session
        # existing_session = cache.get(f"session_{user.sacco_user_id}")
        # if existing_session:
        #     return JsonResponse({'error': 'User is already logged in from another device'}, status=403)
        
        # if user is not None:
        login(request, user)
        # refresh = RefreshToken.for_user(user)
        # Generate OTP
        otp = random.randint(100000, 999999)
        # Store OTP in cache (or save in the database)
        cache.set(f"otp_{user.sacco_user_id}", otp, timeout=600)  # 10 minutes timeout

        # sending otp to phone
        number_to_sms_otp = phone.lstrip("+")
        # Fetch additional member data
        url = f'https://api.kwara.com/members/{user.sacco_user_id}'
        headers = {
            'Authorization': f'Bearer {access_token}',
            'accept': 'application/json',
        }
        try:
            response = requests.get(url, headers=headers)
            response.raise_for_status()
            member_data = response.json().get('data', {}).get('attributes', {})

            # Send SMS via TextSMS
            # Check if phone starts with "254"
            if number_to_sms_otp.startswith("254"):
                # Send SMS OTP
                sms_response = helper_send_sms(phone=number_to_sms_otp, message=f"Your KBS Internet Banking OTP for login is: {otp}", department="User")

                if sms_response["responses"][0]["response-code"] == 200:
                    # print(f"OTP for loggin: {otp}")
                    log_user_activity(user, "Login initiated, OTP sent via SMS", request.path)
                    otp_sent_via = "sms"
                else:
                    return JsonResponse({'error': "Failed to send OTP via SMS. Please try again."}, status=500)
                
            else:
                # Send Email OTP
                try:
                    send_mail(
                        "Kenya Bankers Internet Banking OTP Verification",
                        f"Your Kenya Bankers Internet Banking OTP Verification Code is: {otp}",
                        settings.DEFAULT_FROM_EMAIL,
                        [user.email],  # Make sure user has an email field
                        fail_silently=False,
                        html_message=f'<p>Your Kenya Bankers Internet Banking OTP Verification Code is <strong>{otp}</strong></p>'
                    )
                    log_user_activity(user, "Login initiated, OTP sent via Email", request.path)
                    otp_sent_via = "email"
                except Exception as e:
                    return JsonResponse({'error': f"Failed to send OTP via Email: {str(e)}"}, status=500)
                
            # text_response_sms = helper_send_sms(phone=number_to_sms_otp,message=f"Your KBS Internet Banking OTP for login is: {otp}", department="User")
            # # print("log", text_response_sms)
            # # Handle success or failure
            # # if response_sms["messages"][0]["status"] == "9":
            # if text_response_sms["responses"][0]["response-code"] == 200:
            #     # Send OTP via email (optional, if you still want to do this)
            #     send_mail(
            #         "OTP Verify Account",
            #         f"Use OTP to verify your account: {otp}",
            #         "email",
            #         [phone],
            #         fail_silently=False,
            #         html_message=f'<p>Your OTP is </p><p>{otp}</p>'
            #     )

            #     # Log user activity for login
            #     log_user_activity(user, "Login initiated, OTP generated", request.path)
                
            corp_name = user.business
            username = user.name

            return JsonResponse({
                'message': 'Login successful',
                'sacco_user_id': user.sacco_user_id,
                'home':user.physical_address,
                'work':user.profession,
                # 'access': str(refresh.access_token),
                # 'refresh': str(refresh),
                # 'phone': str(phone),
                'member_data': member_data,
                'role' : user.role,
                'type' : user.notes,
                'corp_name': corp_name,
                'username': username,
                'otp_sent_via': otp_sent_via
                
            }, status=200)
            # else:
            #     # Handle SMS sending failure
            #     return JsonResponse({'error': "Failed to send OTP via SMS. Please try again."}, status=500)
            
        except requests.RequestException:
            log_user_activity(user, "Blacklisted member trying to login", request.path)
            return JsonResponse({'error': 'Member Account Inaccessible'}, status=500)
        # else:
        #     return JsonResponse({'error': 'Invalid credentials'}, status=400)
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)

@csrf_exempt
def login_verify_otp(request, sacco_user_id):
    if request.method == 'POST':

        entered_otp = request.POST.get('otp_digit')

        # Retrieve the OTP from cache (or database)
        cached_otp = cache.get(f"otp_{sacco_user_id}")

        if cached_otp and str(cached_otp) == entered_otp:
            user = CustomUser.objects.get(sacco_user_id=sacco_user_id)
            login(request, user)  # Log in the user

            phone = user.phone

            # Delete the OTP from cache
            cache.delete(f"otp_{sacco_user_id}")

            refresh = RefreshToken.for_user(user)
            # Fetch savings details
            # access_token = get_access_token()
            # Generate unique session token
            session_token = str(uuid.uuid4())  # Random unique session identifier
            cache.set(f"session_{user.sacco_user_id}", session_token, timeout=86400)  # 1-day timeout

            url = f"https://api.kwara.com/members/{sacco_user_id}/savings"
            DormantUrl = f"https://api.kwara.com/members/{sacco_user_id}/savings?filter[state]=DORMANT"
            headers = {
                'Authorization': f'Bearer {access_token}',
                'accept': 'application/json',
            }
            try:
                response = requests.get(url, headers=headers)
                DormantResponse = requests.get(DormantUrl, headers=headers)
                response.raise_for_status()
                DormantResponse.raise_for_status()
                savings_data = response.json().get('data', [])
                Dormant_savings_data = DormantResponse.json().get('data', [])

                # Extract details of "FOSA Current", "Staff Account" or product id "6006", "6008"
                fosa_savings = next(
                    (s for s in savings_data if s.get('attributes', {}).get('product_name') == "FOSA Current" or s.get('attributes', {}).get('product_id') == "6006"),
                    None
                )
                
                staff_savings = next(
                    (s for s in savings_data if s.get('attributes', {}).get('product_name') == "Staff Account" or s.get('attributes', {}).get('product_id') == "6008"),
                    None
                )
                
                share_capital = next(
                    (s for s in savings_data if s.get('attributes', {}).get('product_name') == "Share Capital" or s.get('attributes', {}).get('product_id') == "6011"),
                    None
                )

                # If not found in the primary savings_data, look in dormant accounts
                if not share_capital:
                    share_capital = next(
                        (s for s in Dormant_savings_data if s.get('attributes', {}).get('product_name') == "Share Capital" or s.get('attributes', {}).get('product_id') == "6011"),
                        None
                    )

                # Initialize staff_account to None
                staff_account = None

                # Determine account_number based on availability
                if fosa_savings and staff_savings:
                    # If both exist, prioritize Staff Account
                    account_number = staff_savings['id']
                    staff_account = staff_savings['id']
                    user.fosa_account = staff_savings['id']
                    user.save()
                elif fosa_savings:
                    # Only FOSA exists
                    account_number = fosa_savings['id']
                    user.fosa_account = fosa_savings['id']
                    user.save()
                elif staff_savings:
                    # Only Staff Account exists
                    account_number = staff_savings['id']
                    staff_account = staff_savings['id']
                    user.fosa_account = staff_savings['id']
                    user.save()
                else:
                    if str(sacco_user_id) == "29536":
                        account_number = "1029536011"
                        staff_account = "1029536011"
                        user.fosa_account = "1029536011"
                        user.save()
                    else:
                        # Neither exists
                        return JsonResponse({
                            'error': 'Saving Account Inaccessible',
                            'sacco_user_id': user.sacco_user_id,
                            'access': str(refresh.access_token),
                        }, status=500)
                # else:
                #     # Neither exists
                #     return JsonResponse({
                #         'error': 'Saving Account Inaccessible',
                #         'sacco_user_id': user.sacco_user_id,
                #         'access': str(refresh.access_token),
                #     }, status=500)

                # Safely handle share_capital
                share_capital_id = None
                if share_capital:
                    share_capital_id = share_capital['id']
                
                # Prepare fosa_details
                fosa_details = {
                    'account_number': account_number,
                    'staff':staff_account,
                    'share_capital':share_capital_id
                    # 'available_balance': savings_data.get('attributes', {}).get('available_balance'),  # Uncomment if needed
                }

                # Log user activity after successful login
                log_user_activity(user, "Logged in via OTP", request.path)

                return JsonResponse({
                    'message': 'Login successful',
                    'sacco_user_id': user.sacco_user_id,
                    'access': str(refresh.access_token),
                    'refresh': str(refresh),
                    'phone': str(phone),
                    'fosa_details': fosa_details,
                    'session_token': session_token  # Send to frontend
                }, status=200)

            except requests.exceptions.RequestException as e:
                return JsonResponse({'error': 'Membership Pending Approval: ' + str(e)}, status=500)
        else:
            return JsonResponse({'error': 'Invalid or expired OTP'}, status=400)
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)

@csrf_exempt
def LogoutView(request, sacco_user_id):
    try:
        user = CustomUser.objects.get(sacco_user_id=sacco_user_id)

        # Log user activity for logout
        log_user_activity(user, "Logged out", request.path)
        cache.delete(f"session_{sacco_user_id}")  # Remove session

        # Ensure Django session is also invalidated
        logout(request)

        # Return a JSON response for successful logout
        return JsonResponse({"message": "Logout successful"}, status=200)
    except CustomUser.DoesNotExist:
        return JsonResponse({"error": "User not found"}, status=404)

# To fetch logs
@csrf_exempt
def get_user_logs(request):

    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    if request.method == 'GET':
        logs = UserActivityLog.objects.filter(is_archived=False).order_by('-timestamp')
        # logs = UserActivityLog.objects.all().order_by('-timestamp')
        serializer = UserActivityLogSerializer(list(logs), many=True)
        return JsonResponse(serializer.data, safe=False)
        # return JsonResponse(list(logs), safe=False)

@csrf_exempt
def get_archived_logs(request):

    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    if request.method == 'GET':
        logs = UserActivityLog.objects.filter(is_archived=True).order_by('-timestamp')
        serializer = UserActivityLogSerializer(list(logs), many=True)
        # print(serializer.data)
        return JsonResponse(serializer.data, safe=False)

@csrf_exempt
def archive_logs(request):

    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    if request.method == 'POST':
        # Count all non-archived logs
        total_logs = UserActivityLog.objects.filter(is_archived=False).count()

        # If there are less than 10,000 logs, return an error
        if total_logs < 10000:
            return JsonResponse({"error": "You can't archive logs yet, archive logs only after 10,000 logs"}, status=400)
        
        # Get the IDs of logs to archive (skip the first 10000 entries)
        logs_to_archive_ids = (
            UserActivityLog.objects.filter(is_archived=False)
            .order_by('timestamp')
            .values_list('id', flat=True)[10000:]
        )
        # Update the logs using the IDs
        UserActivityLog.objects.filter(id__in=logs_to_archive_ids).update(is_archived=True)   
        return JsonResponse({'message': 'Logs archived successfully'}, status=200)

# @csrf_exempt
# def delete_log(request, log_id):
#     if request.method == 'DELETE':
#         try:
#             log = UserActivityLog.objects.get(id=log_id)
#             log.delete()
#             return JsonResponse({'message': 'Log deleted successfully'}, status=200)
#         except UserActivityLog.DoesNotExist:
#             return JsonResponse({'error': 'Log not found'}, status=404)

# To fetch sms logs
@csrf_exempt
def get_sms_logs(request):

    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    if request.method == 'GET':
        phone_user_map = {
            user.phone: user
            for user in CustomUser.objects.filter(
                phone__in=[f"+{log.phone}" for log in SMSLog.objects.all()]
            )
        }
        data = [
           {
            'user_id': phone_user_map.get(f"+{log.phone}").sacco_user_id if phone_user_map.get(f"+{log.phone}") else '',
            'user_name': phone_user_map.get(f"+{log.phone}").name if phone_user_map.get(f"+{log.phone}") else '',
             'phone' : log.phone,
             'message': log.message,
             'department':log.department,
             'response_status': log.response_status,
             'timestamp': log.timestamp,
            }

            for log in SMSLog.objects.filter(is_archived=False).order_by('-timestamp')
        ]
        return JsonResponse(data, safe=False)

@csrf_exempt
def get_archived_sms_logs(request):

    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    if request.method == 'GET':
        phone_user_map = {
            user.phone: user
            for user in CustomUser.objects.filter(
                phone__in=[f"+{log.phone}" for log in SMSLog.objects.all()]
            )
        }
        data = [
           {
            'user_id': phone_user_map.get(f"+{log.phone}").sacco_user_id if phone_user_map.get(f"+{log.phone}") else '',
            'user_name': phone_user_map.get(f"+{log.phone}").name if phone_user_map.get(f"+{log.phone}") else '',
             'phone' : log.phone,
             'message': log.message,
             'department':log.department,
             'response_status': log.response_status,
             'timestamp': log.timestamp,
            }

            for log in SMSLog.objects.filter(is_archived=True).order_by('-timestamp')
        ]
        return JsonResponse(data, safe=False)

@csrf_exempt
def archive_sms_logs(request):

    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    if request.method == 'POST':
        # Count all non-archived logs
        # total_logs = SMSLog.objects.filter(is_archived=False).count()
        logs_to_archive_ids = (
            SMSLog.objects.filter(is_archived=False)
            .order_by('timestamp')
            .values_list('id', flat=True) 
        )
        # Update the logs using the IDs
        SMSLog.objects.filter(id__in=logs_to_archive_ids).update(is_archived=True)
        return JsonResponse({'message': 'SMS Logs archived successfully'}, status=200)
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)

# @csrf_exempt
# def delete_sms_log(request, log_id):
#     if request.method == 'DELETE':
#         try:
#             log = UserActivityLog.objects.get(id=log_id)
#             log.delete()
#             return JsonResponse({'message': 'Log deleted successfully'}, status=200)
#         except UserActivityLog.DoesNotExist:
#             return JsonResponse({'error': 'Log not found'}, status=404)

@csrf_exempt
def registers(request):
    # import requests
    # data = json.loads(request.body)
    # data = request.POST.dict()
    files = request.FILES
    files_dict = {
        'profile_photo': files.get('picture')
    }

    url = "https://api.kwara.com/members"
    # access_token = get_access_token()
    data = { "data": { "attributes": {
                    "title": "Mr",
                    "first_name": "Jen",
                    "middle_name": "Kiplagat",
                    "last_name": "Rono",
                    "date_of_birth": "20-02-2000",
                    "email": "ronocollins20003@gmail.com",
                    "notes": "developer",
                    "phone_number": "0792009586",
                    # "secondary_phone_number": "0112568131",
                    "postal_address": "00200",
                    "physical_address": "Juja Road",
                    "marital_status": "Single",
                    "marital_status_other": "Single",
                    "gender": "Male",
                    "gender_other": "Male",
                    "kin": ["Brian Rono"],
                    "profession": "Developer",
                    "employment_status": "employed",
                    "terms_of_service": "Contract",
                    "currently_working": True,
                    "joining_fee": "0",
                    "employer": "Packlines",
                    "employer_phone_number": "0112568131",
                    "business": "Developer",
                    "staff_id": "A003",
                    "kra_pin": "A013546705T",
                    "subscribed_to_mbanking": "YES",
                    "mobile_loan_disallowed": "NO",
                    # "profile_photo": files.get("picture")
                } } }
    headers = {
        "accept": "application/json",
        "content-type": "application/json",
        "Authorization": f"Bearer {access_token}"
    }
    response = requests.post(url, json=data, headers=headers)

    return JsonResponse(response.json())

def check_email_exists(request):
    email = request.GET.get('email', '')
    if CustomUser.objects.filter(email=email).exists():
        return JsonResponse({'exists': True})
    return JsonResponse({'exists': False})

def normalize_phone_variants(phone):
    """
    Generate different possible formats of the phone number for comparison.
    """
    if not phone:  # Check if phone is None or empty
        return set()  # Return an empty set to avoid errors
    
    phone = phone.strip()  # Remove spaces

    # If phone starts with '+254', remove the '+'
    if phone.startswith("+254"):
        without_plus = phone[1:]  # Remove '+'
        local_format = "0" + phone[4:]  # Convert to '07XXXXXXXX'
        return {phone, without_plus, local_format}

    # If phone starts with '254', convert to +254 and 07XXXXXXXX format
    elif phone.startswith("254"):
        with_plus = "+" + phone
        local_format = "0" + phone[3:]  # Convert to '07XXXXXXXX'
        return {phone, with_plus, local_format}

    # If phone starts with '07', assume Kenyan format and convert to +254
    elif re.match(r"^0[7-9][0-9]{8}$", phone):
        international_format = "+254" + phone[1:]  # Convert to '+254XXXXXXXXX'
        no_zero_format = "254" + phone[1:]  # Convert to '254XXXXXXXXX'
        return {phone, international_format, no_zero_format}

    return {phone}  # Default case

@csrf_exempt
def check_phone_exists(request):
    if request.method == 'POST':
        data = json.loads(request.body)
        # phone = data.get('phone', '')
        raw_phone = data.get('phone', '')

        # Generate different variations of the phone number
        phone_variants = normalize_phone_variants(raw_phone)
        # if CustomUser.objects.filter(phone=phone).exists():
        if CustomUser.objects.filter(phone__in=phone_variants).exists():
            return JsonResponse({'exists': True, 'message': 'Phone number already exists'})
        
        # Check if phone exists in the external API
        external_api_url = "https://api.kwara.com/members"
        try:
            response = requests.get(external_api_url, headers={"accept": "application/json", 'Authorization': f'Bearer {access_token}',})
            response_data = response.json()

            # # Extract phone numbers from external API response
            # external_phone_numbers = [
            #     member['attributes']['phone_number'] 
            #     for member in response_data.get('data', [])
            # ]
            # Extract and normalize phone numbers from external API
            external_phone_numbers = set()
            for member in response_data.get('data', []):
                # external_phone_numbers.update(normalize_phone_variants(member['attributes']['phone_number']))
                phone_number = member['attributes'].get('phone_number')  # Use .get() to avoid KeyError
                if phone_number:  # Ensure it's not None
                    external_phone_numbers.update(normalize_phone_variants(phone_number))

            # Validate against the external phone numbers
            # if phone in external_phone_numbers:
            if phone_variants & external_phone_numbers:
                return JsonResponse({'exists': True, 'message': 'Phone number already exists in external records'})
        
        except requests.RequestException as e:
            # Handle API errors
            return JsonResponse({'error': 'Unable to verify phone number with external system', 'details': str(e)}, status=500)
        
        return JsonResponse({'exists': False})
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)

@csrf_exempt
def check_business_exists(request):
    if request.method == 'POST':
        data = json.loads(request.body)
        business_name = data.get('business_name', '')
        if CustomUser.objects.filter(business=business_name).exists():
            return JsonResponse({'exists': True, 'message': 'Business Name already exists'})
        return JsonResponse({'exists': False})
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)

@csrf_exempt
def check_chama_exists(request):
    if request.method == 'POST':
        data = json.loads(request.body)
        business_name = data.get('business_name', '')
        if CustomUser.objects.filter(name=business_name).exists():
            return JsonResponse({'exists': True, 'message': 'Chama Name already exists'})
        return JsonResponse({'exists': False})
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)

def helper_send_email(subject,message,email,filepath):
    # subject = subject
    # message = message
    from_email = settings.EMAIL_HOST_USER
    # print(f"from email {from_email}")
    # print(f"{subject}, {message}, {email}")
    recipient_list = [email]

    # Get the full path of the file to attach
    # file_path = os.path.join(settings.BASE_DIR, 'api', 'resources', 'dd.xlsx')

    # email_sent_count = send_mail(subject, message, from_email, recipient_list)
    # Check if the email was sent successfully (if count > 0)
    email_message = EmailMessage(subject=subject, body=message, from_email="updates@kbs-internet-banking.net", to=recipient_list)
    email_message.attach_file(filepath)
    email_message_count = email_message.send()
    if email_message_count > 0:
        return {"success": "Email sent successfully"}
    else:
        return {"error": "Email failed to send"}

@csrf_exempt
def create_member(request):

    # access_token = get_access_token()
    # request.session['access_token'] = access_token  # Store access token in session
    if request.method == "POST":

        # data = json.loads(request.body)
        email = request.POST.get("email")
        password = request.POST.get("password")
        date_of_birth = request.POST.get("dateOfBirth")
        id_number = request.POST.get("idNumber")
        id_type = request.POST.get("id_type")
        phone_number = request.POST.get("phone")
        name = request.POST.get("name")
        otp_digit = request.POST.get("otp_digit")

        # Additional fields
        title = request.POST.get("title")
        region = request.POST.get("region")
        notes = 'Individual Member'
        postal_address = request.POST.get("postal_address")
        physical_address = request.POST.get("physical_address")
        marital_status = request.POST.get("marital_status")
        marital_status_other = request.POST.get("marital_status_other")
        gender = request.POST.get("gender")
        gender_other = request.POST.get("gender_other")
        kin = json.loads(request.POST.get('kin', '[]'))
        savingsAccounts = json.loads(request.POST.get('savingsAccounts', '[]'))
        # historical_member_id = request.POST.get("historical_member_id")
        profession = request.POST.get("profession")
        employment_status = request.POST.get("employment_status")
        terms_of_service = request.POST.get("terms_of_service")
        currently_working = request.POST.get("currently_working")
        joining_fee = request.POST.get("joining_fee")
        joining_fee_reference = request.POST.get("joining_fee_reference")
        share_capital_contribution = request.POST.get("share_capital_contribution")
        share_capital_reference = request.POST.get("share_capital_reference")
        employer = request.POST.get("employer")
        employer_phone_number = request.POST.get("employer_phone_number")
        business = request.POST.get("business")
        staff_id = request.POST.get("staff_id")
        kra_pin = request.POST.get("kra_pin")
        files = request.FILES
        subscribed_to_mbanking = "YES"
        mobile_loan_disallowed = "NO"

        # PDF file
        # registration_pdf = request.FILES.get('registration_pdf')

        # Convert string values to boolean
        currently_workin = currently_working.lower() == 'true'
        # print(f"Original currently_working: {currently_working}")
        # print(f"Converted currently_working_bool: {currently_workin}")

        # Now process the 'kin' list
        formatted_kin = [f"Name: {next_of_kin.get('name')}, Percentage: {next_of_kin.get('percentage')}, Phone: {next_of_kin.get('phone')}, Relationship: {next_of_kin.get('relationship')}" for next_of_kin in kin]

        name_parts = name.split(' ')
        first_name = name_parts[0]
        middle_name = ' '.join(name_parts[1:-1]) if len(name_parts) > 2 else ''
        last_name = name_parts[-1]

        # Profile picture and signature handling
        profile_picture = request.FILES.get('profile_picture')
        signature = request.FILES.get('signature')

        if profile_picture:
            profile_picture_name = default_storage.save(f"profile_pictures/{profile_picture.name}", ContentFile(profile_picture.read()))
        else:
            profile_picture_name = None

        if signature:
            signature_name = default_storage.save(f"signatures/{signature.name}", ContentFile(signature.read()))
        else:
            signature_name = None

        url = 'https://api.kwara.com/members'
        headers = {
            'accept': 'application/json',
            'content-type': 'application/json',
            'Authorization': f'Bearer {access_token}',  # Replace '..' with your actual token
        }

        attributes= {
            "title": title,
            "first_name": first_name,
            # "middle_name": middle_name,
            "last_name": last_name,
            "date_of_birth": date_of_birth,
            "email": email,
            "notes": notes,
            "phone_number": phone_number,
            # "secondary_phone_number": secondary_phone_number,
            "postal_address": postal_address,
            "physical_address": physical_address,
            "marital_status": marital_status_other if marital_status == "Other" else marital_status,
            # "marital_status": marital_status,
            # "marital_status_other": marital_status_other,
            "gender": gender_other if gender == "Other" else gender,
            # "gender": gender,
            # "gender_other": gender_other,
            "kin": formatted_kin,
            # "historical_member_id": historical_member_id,
            "profession": profession,
            "employment_status": employment_status,
            "terms_of_service": terms_of_service,
            "currently_working": currently_workin,
            "joining_fee": joining_fee,
            "joining_fee_reference": joining_fee_reference,
            "employer": employer,
            "employer_phone_number": employer_phone_number,
            "business": business,
            "kra_pin": kra_pin,
            "subscribed_to_mbanking": subscribed_to_mbanking,
            "mobile_loan_disallowed": mobile_loan_disallowed
        }

        # Conditionally add the middle_name if it exists
        if middle_name:
            attributes["middle_name"] = middle_name

        member_data = {
            "data": {
                "attributes": attributes
            }
        }

        response = requests.post(url, json=member_data, headers=headers)
        # print(f"Payload sent: {json.dumps(member_data, indent=2)}")

        if response.status_code == 201:
            sacco_user_id = response.json()['data']['id']

            # Send OTP via SMS
            try:
                # # AdminEmail = 'agbaluseun@gmail.com'
                # if registration_pdf:
                #     import tempfile
                #     with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as temp_file:
                #         # Write the content of the uploaded file to the temporary file
                #         temp_file.write(registration_pdf.read())
                #         temp_file_path = temp_file.name  # Get the path of the temporary file
                #     helper_send_email(subject='Registration Details',message=f"{sacco_user_id} - {name} is successfully onboarded. Find the details attached.",email='agbaluseun@gmail.com', filepath=temp_file_path)
                    # import tempfile
                    # with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as temp_file:
                    #     # Write the content of the uploaded file to the temporary file
                    #     temp_file.write(registration_pdf.read())
                    #     temp_file_path = temp_file.name  # Get the path of the temporary file

                    # # Send email with the PDF attached
                    # from_email="updates@kbs-internet-banking.net"
                    # Remail = 'agbaluseun@gmail.com'
                    # receipt = [Remail]
                    # email_message = EmailMessage(
                    #     subject="Registration Details",
                    #     body=f"{sacco_user_id} - {name} is successfully onboarded. Find the details attached.",
                    #     from_email=from_email,
                    #     to=receipt,
                    # )
                    # # with open(temp_file_path, 'rb') as temp_pdf:
                    # email_message.attach_file(temp_file_path)
                    # # email_message.attach('Member_Details.pdf', registration_pdf.read(), 'application/pdf')
                    # email_message.send()

                # Create user instance
                user = CustomUser.objects.create_user(
                    email=email,
                    title=title,
                    password=password,
                    id_number=id_number,
                    sacco_user_id=sacco_user_id,
                    date_of_birth=date_of_birth,
                    phone=phone_number,
                    name=name,
                    id_type=id_type,
                    notes=notes,
                    region=region,
                    postal_address=postal_address,
                    physical_address=physical_address,
                    marital_status=marital_status,
                    marital_status_other=marital_status_other,
                    gender=gender,
                    gender_other=gender_other,
                    # historical_member_id=historical_member_id,
                    profession=profession,
                    employment_status=employment_status,
                    terms_of_service=terms_of_service,
                    currently_working=currently_working,
                    joining_fee=joining_fee,
                    joining_fee_reference=joining_fee_reference,
                    share_capital_contribution=share_capital_contribution,
                    share_capital_reference=share_capital_reference,
                    employer=employer,
                    employer_phone_number=employer_phone_number,
                    business=business,
                    staff_id=staff_id,
                    kra_pin=kra_pin,
                    subscribed_to_mbanking=subscribed_to_mbanking,
                    mobile_loan_disallowed=mobile_loan_disallowed,
                    otp_digit=otp_digit,
                    profile_picture=profile_picture_name,
                    signature=signature_name
                )

                # Save Next of Kin data
                for next_of_kin in kin:
                    NextOfKin.objects.create(
                        user=user,
                        name=next_of_kin.get('name'),
                        percentage=next_of_kin.get('percentage'),
                        phone=next_of_kin.get('phone'),
                        relationship=next_of_kin.get('relationship')
                    )

                # Save Files data
                if files.get('kra_pin_doc'):
                    IndividualDocuments.objects.create(
                        user=user,
                        kra_pin_doc=files['kra_pin_doc'],
                        birth_cert_doc=files.get('birth_cert_doc'),
                        national_id=files.get('national_id'),
                    )
                
                # Save Next of Kin data
                for savings_account in savingsAccounts:
                    SavingsAccount.objects.create(
                        user=user,
                        name=savings_account,
                    )

                number_to_sms_otp = phone_number.lstrip("+")

                # Check if phone starts with "254"
                if number_to_sms_otp.startswith("254"):
                    # Send SMS OTP
                    sms_response = helper_send_sms(phone=number_to_sms_otp, message=f"Your KBS Internet Banking OTP verification is: {otp_digit}", department="User")

                    if sms_response["responses"][0]["response-code"] == 200:
                        otp_sent_via = "sms"
                    else:
                        return JsonResponse({'error': "Failed to send OTP via SMS. Please try again."}, status=500)
                    
                else:
                    # Send Email OTP
                    try:
                        send_mail(
                            "Kenya Bankers Internet Banking OTP Verification",
                            f"Your Kenya Bankers Internet Banking OTP Verification Code is: {otp_digit}",
                            settings.DEFAULT_FROM_EMAIL,
                            [email],  # Make sure user has an email field
                            fail_silently=False,
                            html_message=f'<p>Your Kenya Bankers Internet Banking OTP Verification Code is <strong>{otp_digit}</strong></p>'
                        )
                        otp_sent_via = "email"
                    except Exception as e:
                        return JsonResponse({'error': f"Failed to send OTP via Email: {str(e)}"}, status=500)

                # text_response_sms = helper_send_sms(phone=number_to_sms_otp,message=f"Your KBS Internet Banking OTP verification is: {otp_digit}", department="User")

                # # Handle success or failure
                # if text_response_sms["responses"][0]["response-code"] == 200:
                #     # Send OTP via email (optional, if you still want to do this)
                #     send_mail(
                #         "OTP Verify Account",
                #         f"Use OTP to verify your account: {otp_digit}",
                #         "email",
                #         [email],
                #         fail_silently=False,
                #         html_message=f'<p>Your OTP is </p><p>{otp_digit}</p>'
                #     )

                refresh = RefreshToken.for_user(user)

                return JsonResponse({'data': response.json(), 'sacco_user_id': sacco_user_id, 'phone':phone_number, 'access': str(refresh.access_token), 'home':physical_address, 'work':profession, 'type' : user.notes,}, status=response.status_code)
                # else:
                #     # Handle SMS sending failure
                #     return JsonResponse({'error': f"Failed to send OTP via SMS"}, status=500)

            except Exception as e:
                return JsonResponse({'error': f"An error occurred: {str(e)}"}, status=500)
        else:
            return JsonResponse({'error': 'Failed to create member'}, status=response.status_code)

# @csrf_exempt
# def create_corp_member(request):

#     # access_token = get_access_token()
#     # request.session['access_token'] = access_token  # Store access token in session
#     if request.method == "POST":

#         # data = json.loads(request.body)
#         title = request.POST.get("title")
#         name = request.POST.get("name")
#         email = request.POST.get("email")
#         password = request.POST.get("password")
#         date_of_birth = request.POST.get("dateOfBirth")
#         id_number = request.POST.get("idNumber")
#         phone_number = request.POST.get("phone")
#         otp_digit = request.POST.get("otp_digit")

#         # Additional fields
#         notes = 'Corporate Member'
#         postal_address = request.POST.get("postal_address")
#         physical_address = request.POST.get("physical_address")
#         marital_status = request.POST.get("marital_status")
#         business_name = request.POST.get("business_name")
#         gender = request.POST.get("gender")
#         kra_pin = request.POST.get("kra_pin")
#         registration_number = request.POST.get("registration_number")
#         kin = json.loads(request.POST.get('kin', '[]'))
#         account_type = json.loads(request.POST.get('savingsAccounts', '[]'))
#         files = request.FILES
#         Services = json.loads(request.POST.get('Services', '[]'))
#         registration_date = request.POST.get("registration_date")
#         business_location = request.POST.get("business_location")
#         business_county = request.POST.get("business_county")
#         company_type = request.POST.get("company_type")
#         member_type = request.POST.get("member_type")
#         member_ID = request.POST.get("member_ID")
#         business_description = request.POST.get("business_description")
#         monthly_net_cashflow = request.POST.get('monthly_net_cashflow')
#         currently_working = "TRUE"
#         joining_fee = request.POST.get("joining_fee")
#         joining_fee_reference = request.POST.get("joining_fee_reference")
#         share_capital_contribution = request.POST.get("share_capital_contribution")
#         share_capital_reference = request.POST.get("share_capital_reference")
#         signing_mandate = request.POST.get("signing_mandate")
#         employment_status = "employed"
#         subscribed_to_mbanking = "YES"
#         mobile_loan_disallowed = "NO"
#         secondary_phone_number = "0000000000"
#         marital_status_other = "N/A"
#         gender_other = "N/A"
#         historical_member_id = "00000"
#         profession = "None"
#         terms_of_service = "Contract"
#         employer = "None"
#         employer_phone_number = "0000000000"
#         staff_id = "None"

#         services_str = ', '.join([service for service in Services if service])
#         # services_str = ', '.join(Services)

#         # Convert string values to boolean
#         currently_workin = currently_working.lower() == 'true'

#         # Now process the 'kin' list
#         formatted_kin = [f"Name: {next_of_kin.get('name')}, Percentage: {next_of_kin.get('percentage')}, Phone: {next_of_kin.get('phone')}, Relationship: {next_of_kin.get('relationship')}" for next_of_kin in kin]

#         name_parts = name.split(' ')
#         first_name = name_parts[0]
#         middle_name = ' '.join(name_parts[1:-1]) if len(name_parts) > 2 else ''
#         last_name = name_parts[-1]

#         profile_picture = request.FILES.get('company_logo')
#         if profile_picture:
#             profile_picture_name = default_storage.save(f"profile_pictures/{profile_picture.name}", ContentFile(profile_picture.read()))
#         else:
#             profile_picture_name = None

        

#         url = 'https://api.kwara.com/members'
#         headers = {
#             'accept': 'application/json',
#             'content-type': 'application/json',
#             'Authorization': f'Bearer {access_token}',  # Replace '..' with your actual token
#         }

#         member_data = {
#             "data": {
#                 "attributes": {
#                     "title": title,
#                     "first_name": first_name,
#                     "middle_name": middle_name,
#                     "last_name": last_name,
#                     "date_of_birth": date_of_birth,
#                     "email": email,
#                     "notes": notes,
#                     "phone_number": phone_number,
#                     "secondary_phone_number": secondary_phone_number,
#                     "postal_address": postal_address,
#                     "physical_address": physical_address,
#                     "marital_status": marital_status,
#                     "marital_status_other": marital_status_other,
#                     "gender": gender,
#                     "gender_other": gender_other,
#                     "kin": formatted_kin,
#                     "historical_member_id": historical_member_id,
#                     "profession": profession,
#                     "employment_status": employment_status,
#                     "terms_of_service": terms_of_service,
#                     "currently_working": currently_workin,
#                     "joining_fee": joining_fee,
#                     "joining_fee_reference": joining_fee_reference,
#                     "employer": employer,
#                     "employer_phone_number": employer_phone_number,
#                     "business": business_name,
#                     "staff_id": staff_id,
#                     "kra_pin": kra_pin,
#                     "subscribed_to_mbanking": subscribed_to_mbanking,
#                     "mobile_loan_disallowed": mobile_loan_disallowed
#                 }
#             }
#         }

#         response = requests.post(url, json=member_data, headers=headers)
#         print(f"Payload sent: {json.dumps(member_data, indent=2)}")
#         print(response.json())

#         if response.status_code == 201:
#             sacco_user_id = response.json()['data']['id']

#             # Send OTP via SMS
#             try:
#                 number_to_sms_otp = phone_number.lstrip("+")

#                 text_response_sms = helper_send_sms(phone=number_to_sms_otp,message=f"Your KBS OTP for login verification is: {otp_digit}", department="User")

#                 # Handle success or failure
#                 if text_response_sms["responses"][0]["response-code"] == 200:
#                     # Send OTP via email (optional, if you still want to do this)
#                     send_mail(
#                         "OTP Verify Account",
#                         f"Use OTP to verify your account: {otp_digit}",
#                         "email",
#                         [email],
#                         fail_silently=False,
#                         html_message=f'<p>Your OTP is </p><p>{otp_digit}</p>'
#                     )

#                     # Create user instance
#                     user = CustomUser.objects.create_user(
#                         email=email,
#                         title=title,
#                         password=password,
#                         id_number=id_number,
#                         sacco_user_id=sacco_user_id,
#                         date_of_birth=date_of_birth,
#                         phone=phone_number,
#                         name=name,
#                         notes=notes,
#                         business=business_name,
#                         registration_date=registration_date,
#                         business_location=business_location,
#                         business_county=business_county,
#                         services=services_str,
#                         employment_status=employment_status,
#                         member_type=member_type,
#                         member_ID=member_ID,
#                         registration_number=registration_number,
#                         company_type=company_type,
#                         business_description=business_description,
#                         postal_address=postal_address,
#                         physical_address=physical_address,
#                         marital_status=marital_status,
#                         gender=gender,
#                         signing_mandate = signing_mandate,
#                         monthly_net_cashflow=monthly_net_cashflow,
#                         joining_fee=joining_fee,
#                         joining_fee_reference=joining_fee_reference,
#                         share_capital_contribution=share_capital_contribution,
#                         share_capital_reference=share_capital_reference,
#                         profile_picture=profile_picture_name,
#                         kra_pin=kra_pin,
#                         otp_digit=otp_digit,
#                     )

#                     # Save Next of Kin data
#                     for next_of_kin in kin:
#                         NextOfKin.objects.create(
#                             user=user,
#                             name=next_of_kin.get('name'),
#                             percentage=next_of_kin.get('percentage'),
#                             phone=next_of_kin.get('phone'),
#                             relationship=next_of_kin.get('relationship')
#                         )
                    
#                     # Save Next of Kin data
#                     for savings_account in account_type:
#                         SavingsAccount.objects.create(
#                             user=user,
#                             name=savings_account,
#                         )
                    
#                     # Save Files data
#                     if files.get('reg_certificate'):
#                         corporate_document = CorporateDocuments.objects.create(
#                             user=user,
#                             reg_certificate=files['reg_certificate'],
#                             kra_pin_doc=files.get('kra_pin_doc'),
#                             cr_12=files.get('cr_12'),
#                         )
#                         # Handle multiple passport photos
#                         # Handle multiple passport photos with `name` and `photo`
#                         passport_photos = []
#                         index = 0
#                         while True:
#                             photo_name = request.POST.get(f'passport_photo_{index}_name')  # Get name
#                             photo_file = request.FILES.get(f'passport_photo_{index}_file')  # Get file

#                             if not photo_name or not photo_file:
#                                 break  # Stop when no more photos are found

#                             # Create a unique name for each file
#                             unique_name = f"{uuid.uuid4().hex}_{photo_file.name}"
#                             passport_photos.append({
#                                 'name': photo_name,
#                                 'file': photo_file,
#                                 'unique_name': unique_name
#                             })
#                             index += 1  # Increment index for the next file

#                         # Save passport photos
#                         for photo_info in passport_photos:
#                             PassportPhoto.objects.create(
#                                 document=corporate_document,
#                                 name=photo_info['name'],
#                                 photo=photo_info['file']
#                             )
#                         # passport_photos = files.getlist('passport_photo')
#                         # for photo in passport_photos:
#                         #     print('Trying to create a photo object for each image')
#                         #     PassportPhoto.objects.create(document=corporate_document, photo=photo)
                        
#                         # Handle multiple board resolution files
#                         if files.getlist('board_resolution'):
#                             board_resolutions = files.getlist('board_resolution')
#                             for resolution in board_resolutions:
#                                 print('Trying to create a BR object for each image')
#                                 BoardResolution.objects.create(document=corporate_document, file=resolution)
                    
#                     # Save Corporate Signatures data
#                     signatures = []
#                     for key in request.FILES:
#                         if key.startswith('signature['):
#                             # Extract index from the key
#                             index = key.split('[')[1].split(']')[0]  # Get the index
#                             name = request.POST.get(f'signature[{index}][name]')
#                             signature_file = request.FILES[key]
#                             if name and signature_file:
#                                 signatures.append({'name': name, 'signature': signature_file})

#                     # Now save the signatures
#                     for sig in signatures:
#                         name = sig.get('name')
#                         signature_file = sig.get('signature')
#                         if name and signature_file:
#                             SigningMandate.objects.create(
#                                 user=user,
#                                 name=name,
#                                 signature=signature_file,  # Save the file properly
#                             )

#                     refresh = RefreshToken.for_user(user)

#                     return JsonResponse({'data': response.json(), 'sacco_user_id': sacco_user_id, 'phone':phone_number, 'access': str(refresh.access_token), 'home':physical_address, 'work':business_location, 'type' : user.notes,}, status=response.status_code)
#                 else:
#                     # Handle SMS sending failure
#                     return JsonResponse({'error': f"Failed to send OTP via SMS: {response_sms['messages'][0]['error-text']}"}, status=500)

#             except Exception as e:
#                         return JsonResponse({'error': f"An error occurred: {str(e)}"}, status=500)
#         else:
#             return JsonResponse({'error': 'Failed to create member'}, status=response.status_code)
# ss
@csrf_exempt
def create_corp_member(request):

    # access_token = get_access_token()
    # request.session['access_token'] = access_token  # Store access token in session
    if request.method == "POST":

        # data = json.loads(request.body)
        title = request.POST.get("title")
        name = request.POST.get("name")
        email = request.POST.get("email")
        password = request.POST.get("password")
        date_of_birth = request.POST.get("dateOfBirth")
        id_number = request.POST.get("idNumber")
        id_type = request.POST.get("id_type")
        phone_number = request.POST.get("phone")
        otp_digit = request.POST.get("otp_digit")

        # Additional fields
        notes = 'Corporate Member'
        postal_address = request.POST.get("postal_address")
        physical_address = request.POST.get("physical_address")
        marital_status = request.POST.get("marital_status")
        business_name = request.POST.get("business_name")
        gender = request.POST.get("gender")
        kra_pin = request.POST.get("kra_pin")
        registration_number = request.POST.get("registration_number")
        kin = json.loads(request.POST.get('kin', '[]'))
        account_type = json.loads(request.POST.get('savingsAccounts', '[]'))
        files = request.FILES
        Services = json.loads(request.POST.get('Services', '[]'))
        registration_date = request.POST.get("registration_date")
        business_location = request.POST.get("business_location")
        business_county = request.POST.get("business_county")
        company_type = request.POST.get("company_type")
        member_type = request.POST.get("member_type")
        member_ID = request.POST.get("member_ID")
        business_description = request.POST.get("business_description")
        monthly_net_cashflow = request.POST.get('monthly_net_cashflow')
        currently_working = "TRUE"
        joining_fee = request.POST.get("joining_fee")
        joining_fee_reference = request.POST.get("joining_fee_reference")
        share_capital_contribution = request.POST.get("share_capital_contribution")
        share_capital_reference = request.POST.get("share_capital_reference")
        jiinue_account_contribution=request.POST.get("jiinue_account_contribution")
        jiinue_account_reference=request.POST.get("jiinue_account_reference")
        diaspora_account_contribution=request.POST.get("diaspora_account_contribution")
        diaspora_account_reference=request.POST.get("diaspora_account_reference")
        boresha_biashara_account_contribution=request.POST.get("boresha_biashara_account_contribution")
        boresha_biashara_account_reference=request.POST.get("boresha_biashara_account_reference")

        signing_mandate = request.POST.get("signing_mandate")
        employment_status = "employed"
        subscribed_to_mbanking = "YES"
        mobile_loan_disallowed = "NO"
        # secondary_phone_number = "0000000000"
        # marital_status_other = "N/A"
        # gender_other = "N/A"
        # historical_member_id = "00000"
        # profession = "None"
        # terms_of_service = "Contract"
        # employer = "None"
        # employer_phone_number = "0000000000"
        # staff_id = "None"

        services_str = ', '.join([service for service in Services if service])
        # services_str = ', '.join(Services)

        # Convert string values to boolean
        currently_workin = currently_working.lower() == 'true'

        # Now process the 'kin' list
        formatted_kin = [f"Name: {next_of_kin.get('name')}, Percentage: {next_of_kin.get('percentage')}, Phone: {next_of_kin.get('phone')}, Relationship: {next_of_kin.get('relationship')}" for next_of_kin in kin]

        name_parts = name.split(' ')
        first_name = name_parts[0]
        middle_name = ' '.join(name_parts[1:-1]) if len(name_parts) > 2 else ''
        last_name = name_parts[-1]

        profile_picture = request.FILES.get('company_logo')
        if profile_picture:
            profile_picture_name = default_storage.save(f"profile_pictures/{profile_picture.name}", ContentFile(profile_picture.read()))
        else:
            profile_picture_name = None



        url = 'https://api.kwara.com/members'
        headers = {
            'accept': 'application/json',
            'content-type': 'application/json',
            'Authorization': f'Bearer {access_token}',  # Replace '..' with your actual token
        }

        attributes= {
            "title": title,
            "first_name": first_name,
            "last_name": last_name,
            "date_of_birth": date_of_birth,
            "email": email,
            "notes": notes,
            "phone_number": phone_number,
            # "secondary_phone_number": secondary_phone_number,
            "postal_address": postal_address,
            "physical_address": physical_address,
            "marital_status": marital_status,
            # "marital_status_other": marital_status_other,
            "gender": gender,
            # "gender_other": gender_other,
            "kin": formatted_kin,
            # "historical_member_id": historical_member_id,
            # "profession": profession,
            "employment_status": employment_status,
            # "terms_of_service": terms_of_service,
            "currently_working": currently_workin,
            "joining_fee": joining_fee,
            "joining_fee_reference": joining_fee_reference,
            # "employer": employer,
            # "employer_phone_number": employer_phone_number,
            "business": business_name,
            # "staff_id": staff_id,
            "kra_pin": kra_pin,
            "subscribed_to_mbanking": subscribed_to_mbanking,
            "mobile_loan_disallowed": mobile_loan_disallowed
        }

        # member_data = {
        #     "data": {
        #     }
        # }

        # Conditionally add the middle_name if it exists
        if middle_name:
            attributes["middle_name"] = middle_name

        member_data = {
            "data": {
                "attributes": attributes
            }
        }

        response = requests.post(url, json=member_data, headers=headers)
        # print(f"Payload sent: {json.dumps(member_data, indent=2)}")
        # print(response.json())

        if response.status_code == 201:
            sacco_user_id = response.json()['data']['id']

            # Send OTP via SMS
            try:
                # Create user instance
                user = CustomUser.objects.create_user(
                    email=email,
                    title=title,
                    password=password,
                    id_number=id_number,
                    sacco_user_id=sacco_user_id,
                    date_of_birth=date_of_birth,
                    phone=phone_number,
                    name=name,
                    id_type=id_type,
                    notes=notes,
                    business=business_name,
                    registration_date=registration_date,
                    business_location=business_location,
                    business_county=business_county,
                    services=services_str,
                    employment_status=employment_status,
                    member_type=member_type,
                    member_ID=member_ID,
                    registration_number=registration_number,
                    company_type=company_type,
                    business_description=business_description,
                    postal_address=postal_address,
                    physical_address=physical_address,
                    marital_status=marital_status,
                    gender=gender,
                    signing_mandate = signing_mandate,
                    monthly_net_cashflow=monthly_net_cashflow,
                    joining_fee=joining_fee,
                    joining_fee_reference=joining_fee_reference,
                    share_capital_contribution=share_capital_contribution,
                    share_capital_reference=share_capital_reference,
                    jiinue_account_contribution=jiinue_account_contribution,
                    jiinue_account_reference=jiinue_account_reference,
                    diaspora_account_contribution=diaspora_account_contribution,
                    diaspora_account_reference=diaspora_account_reference,
                    boresha_biashara_account_contribution=boresha_biashara_account_contribution,
                    boresha_biashara_account_reference=boresha_biashara_account_reference,
                    profile_picture=profile_picture_name,
                    kra_pin=kra_pin,
                    otp_digit=otp_digit,
                )

                # Save Next of Kin data
                for next_of_kin in kin:
                    NextOfKin.objects.create(
                        user=user,
                        name=next_of_kin.get('name'),
                        percentage=next_of_kin.get('percentage'),
                        phone=next_of_kin.get('phone'),
                        relationship=next_of_kin.get('relationship')
                    )

                # Save Next of Kin data
                for savings_account in account_type:
                    SavingsAccount.objects.create(
                        user=user,
                        name=savings_account,
                    )

                # Save Files data
                if files.get('reg_certificate'):
                    corporate_document = CorporateDocuments.objects.create(
                        user=user,
                        reg_certificate=files['reg_certificate'],
                        # kra_pin_doc=files.get('kra_pin_doc'),
                        cr_12=files.get('cr_12'),
                    )
                    # Handle multiple passport photos
                    # Handle multiple passport photos with `name` and `photo`
                    passport_photos = []
                    index = 0
                    while True:
                        photo_name = request.POST.get(f'passport_photo_{index}_name')  # Get name
                        photo_file = request.FILES.get(f'passport_photo_{index}_file')  # Get file

                        if not photo_name or not photo_file:
                            break  # Stop when no more photos are found

                        # Create a unique name for each file
                        unique_name = f"{uuid.uuid4().hex}_{photo_file.name}"
                        passport_photos.append({
                            'name': photo_name,
                            'file': photo_file,
                            'unique_name': unique_name
                        })
                        index += 1  # Increment index for the next file

                    # Save passport photos
                    for photo_info in passport_photos:
                        PassportPhoto.objects.create(
                            document=corporate_document,
                            name=photo_info['name'],
                            photo=photo_info['file']
                        )

                    # KRA PIN Photos
                    kra_photos = [] 
                    kra_index = 0

                    # Collect KRA photos from request
                    while True:
                        Kra_photo_name = request.POST.get(f'kra_pin_photo_{kra_index}_name')  # Get name
                        kra_photo_file = request.FILES.get(f'kra_pin_photo_{kra_index}_file')  # Get file

                        if not Kra_photo_name or not kra_photo_file:
                            break  # Stop when no more photos are found

                        # print(f"Received KRA photo name: {Kra_photo_name}")  # Debugging line
                        # print(f"Received KRA photo file: {kra_photo_file}")  # Debugging line

                        kra_photos.append({
                            'name': Kra_photo_name,
                            'file': kra_photo_file
                        })
                        kra_index += 1  # Increment index for the next file

                    # Check that the corporate document exists before creating KRA Pins
                    # print("Corporate Document ID:", corporate_document.id)  # Ensure corporate_document is valid

                    # Loop through kra_photos only once to save each KRA photo
                    for kra_photo_info in kra_photos:
                        try:
                            KraPin.objects.create(
                                document=corporate_document,
                                name=kra_photo_info['name'],
                                photo=kra_photo_info['file']
                            )
                            # print(f"Saved KRA Photo: {kra_photo_info['name']}")  # Log successful save
                        except Exception as e:
                            print(f"Error saving KRA Photo '{kra_photo_info['name']}'")  # Log the error

                    
                    # Handle multiple board resolution files
                    if files.getlist('board_resolution'):
                        board_resolutions = files.getlist('board_resolution')
                        for resolution in board_resolutions:
                            # print('Trying to create a BR object for each image')
                            BoardResolution.objects.create(document=corporate_document, file=resolution)

                # Save Corporate Signatures data
                # signatures = []
                # for key in request.FILES:
                #     if key.startswith('signature['):
                #         # Extract index from the key
                #         index = key.split('[')[1].split(']')[0]  # Get the index
                #         name = request.POST.get(f'signature[{index}][name]')
                #         signature_file = request.FILES[key]
                #         if name and signature_file:
                #             signatures.append({'name': name, 'signature': signature_file})

                # # Now save the signatures
                # for sig in signatures:
                #     name = sig.get('name')
                #     signature_file = sig.get('signature')
                #     if name and signature_file:
                #         SigningMandate.objects.create(
                #             user=user,
                #             name=name,
                #             signature=signature_file,  # Save the file properly
                #         )

                # Save Corporate Signatures data
                signatures = []
                for key in request.FILES:
                    if key.startswith('signature['):
                        # Extract index from the key
                        index = key.split('[')[1].split(']')[0]  # Get the index
                        name = request.POST.get(f'signature[{index}][name]')
                        id = request.POST.get(f'signature[{index}][id]')
                        signature_file = request.FILES[key]
                        if name and signature_file:
                            signatures.append({'name': name,'id':id, 'signature': signature_file})

                # Now save the signatures
                for sig in signatures:
                    name = sig.get('name')
                    id = sig.get('id')
                    signature_file = sig.get('signature')
                    if name and signature_file:
                        SigningMandate.objects.create(
                            user=user,
                            name=name,
                            id_no=id,
                            signature=signature_file,  # Save the file properly
                        )
                
                number_to_sms_otp = phone_number.lstrip("+")
                # Check if phone starts with "254"
                if number_to_sms_otp.startswith("254"):
                    # Send SMS OTP
                    sms_response = helper_send_sms(phone=number_to_sms_otp, message=f"Your KBS Internet Banking OTP verification is: {otp_digit}", department="User")

                    if sms_response["responses"][0]["response-code"] == 200:
                        otp_sent_via = "sms"
                    else:
                        return JsonResponse({'error': "Failed to send OTP via SMS. Please try again."}, status=500)
                    
                else:
                    # Send Email OTP
                    try:
                        send_mail(
                            "Kenya Bankers Internet Banking OTP Verification",
                            f"Your Kenya Bankers Internet Banking OTP Verification Code is: {otp_digit}",
                            settings.DEFAULT_FROM_EMAIL,
                            [email],  # Make sure user has an email field
                            fail_silently=False,
                            html_message=f'<p>Your Kenya Bankers Internet Banking OTP Verification Code is <strong>{otp_digit}</strong></p>'
                        )
                        otp_sent_via = "email"
                    except Exception as e:
                        return JsonResponse({'error': f"Failed to send OTP via Email: {str(e)}"}, status=500)

                # text_response_sms = helper_send_sms(phone=number_to_sms_otp,message=f"Your KBS Internet Banking OTP verification is: {otp_digit}", department="User")

                # # Handle success or failure
                # if text_response_sms["responses"][0]["response-code"] == 200:
                #     # Send OTP via email (optional, if you still want to do this)
                #     send_mail(
                #         "OTP Verify Account",
                #         f"Use OTP to verify your account: {otp_digit}",
                #         "email",
                #         [email],
                #         fail_silently=False,
                #         html_message=f'<p>Your OTP is </p><p>{otp_digit}</p>'
                #     )

                refresh = RefreshToken.for_user(user)

                return JsonResponse({'data': response.json(), 'sacco_user_id': sacco_user_id, 'phone':phone_number, 'access': str(refresh.access_token), 'home':physical_address, 'work':business_name, 'type' : user.notes,}, status=response.status_code)
                # else:
                #     # Handle SMS sending failure
                #     return JsonResponse({'error': f"Failed to send OTP via SMS"}, status=500)

            except Exception as e:
                        return JsonResponse({'error': f"An error occurred: {str(e)}"}, status=500)
        else:
            return JsonResponse({'error': 'Failed to create member'}, status=response.status_code)

@csrf_exempt
def create_chama_member(request):
    if request.method == "POST":
        chama_name = request.POST.get("chama_name")
        email = request.POST.get("email")
        password = request.POST.get("password")
        telephone_office = request.POST.get("telephone_office")
        otp_digit = request.POST.get("otp_digit")
        bank_accounts = request.POST.get('bank_accounts')
        members_number = request.POST.get('members_number')
        joining_fee_reference = request.POST.get("joining_fee_reference")
        joining_fee = request.POST.get("joining_fee")
        notes = 'Chama Member'
        postal_address = request.POST.get("postal_address")
        physical_address = request.POST.get("physical_address")
        postal_code = request.POST.get("postal_code")
        associate_company = request.POST.get('associate_company')
        kra_pin = request.POST.get("kra_pin")
        town = request.POST.get("town")
        region = request.POST.get("region")
        # files = request.FILES
        # print(f"files {files}")
        building = request.POST.get("building")
        nature_of_business = request.POST.get("nature_of_business")
        incorporation_date = request.POST.get("incorporation_date")
        certificate_of_incorporation_number = request.POST.get("certificate_of_incorporation_number")
        account_types = request.POST.get('account_types')
        members_data = request.POST.get('members')
        # print(f"members_data {members_data}")
        officials_data = request.POST.get('officials')
        signing_mandate = request.POST.get("signing_mandate")
        # employment_status = "employed"
        subscribed_to_mbanking = "YES"
        mobile_loan_disallowed = "NO"
        # secondary_phone_number = "0000000000"
        # marital_status_other = "N/A"
        # gender_other = "N/A"
        # historical_member_id = "00000"
        # profession = "None"
        # terms_of_service = "Contract"
        # employer = "None"
        # employer_phone_number = "0000000000"
        # staff_id = "None"

        name_parts = chama_name.split(' ')
        first_name = name_parts[0]
        middle_name = ' '.join(name_parts[1:-1]) if len(name_parts) > 2 else ''
        last_name = name_parts[-1]

        url = 'https://api.kwara.com/members'
        headers = {
            'accept': 'application/json',
            'content-type': 'application/json',
            'Authorization': f'Bearer {access_token}',  # Replace '..' with your actual token
        }

        attributes= {
            "title": "Mr",
            "first_name": first_name,
            "last_name": last_name,
            "date_of_birth": "1990-11-11",
            "email": email,
            "notes": notes,
            "phone_number": telephone_office,
            # "secondary_phone_number": secondary_phone_number,
            "postal_address": postal_address,
            "physical_address": physical_address,
            "marital_status": "Other",
            # "marital_status_other": marital_status_other,
            "gender": "Male",
            # "gender_other": gender_other,
            # "historical_member_id": historical_member_id,
            # "profession": profession,
            # "employment_status": employment_status,
            # "terms_of_service": terms_of_service,
            "currently_working":True,
            "joining_fee": "0",
            "joining_fee_reference": joining_fee_reference,
            # "employer": employer,
            # "employer_phone_number": employer_phone_number,
            "business": "chama",
            # "staff_id": staff_id,
            "kra_pin": kra_pin,
            "subscribed_to_mbanking": subscribed_to_mbanking,
            "mobile_loan_disallowed": mobile_loan_disallowed
        }
        
        # member_data = {
        #     "data": {
                
        #     }
        # }

        # Conditionally add the middle_name if it exists
        if middle_name:
            attributes["middle_name"] = middle_name

        member_data = {
            "data": {
                "attributes": attributes
            }
        }

        response = requests.post(url, json=member_data, headers=headers)
        # print(f"Payload sent: {json.dumps(member_data, indent=2)}")
        # print(response.json())
        # return JsonResponse(response)

        if response.status_code == 201:
            sacco_user_id = response.json()['data']['id']

            # Send OTP via SMS
            try:
                # Create user instance
                user = CustomUser.objects.create_user(
                    email=email,
                    phone=telephone_office,
                    password=password,
                    sacco_user_id=sacco_user_id,
                    name=chama_name,
                    notes=notes,
                    postal_address=postal_address,
                    physical_address=physical_address,
                    postal_code=postal_code,
                    signing_mandate = signing_mandate,
                    joining_fee_reference= joining_fee_reference,
                    joining_fee= joining_fee,
                    kra_pin=kra_pin,
                    otp_digit=otp_digit,
                    region=region,
                    chama_account_type=account_types,
                    chama_other_bank_accounts=bank_accounts,
                    chama_associate_company=associate_company,
                    chama_number_of_members=members_number,
                    chama_town=town,
                    chama_telephone_office=telephone_office,
                    chama_nature_of_business=nature_of_business,
                    chama_building=building,
                    chama_date_of_incorporation=incorporation_date,
                    chama_certificate_of_incorporation_number=certificate_of_incorporation_number,
                )
                signatures = []
                processed_indices = set()  # Track indices that have been processed

                for key in request.FILES:
                    if key.startswith('signature['):
                        # Get the index
                        index = key.split('[')[1].split(']')[0]  

                        if index not in processed_indices:
                            processed_indices.add(index)

                            # Extract form data
                            name = request.POST.get(f'signature[{index}][name]')
                            last_name = request.POST.get(f'signature[{index}][last_name]')
                            # Extract other form fields as needed

                            signature_file = request.FILES.get(f'signature[{index}][signature]')
                            passport_photo_file = request.FILES.get(f'signature[{index}][passport_photo]')

                            # Debug print statements to check for duplicate files
                            # print(f'signature file {signature_file}')
                            # print(f'passport photo file {passport_photo_file}')

                            if name and signature_file:
                                signatures.append({
                                    'name': name,
                                    'email': request.POST.get(f'signature[{index}][email]'),
                                    'physical_address': request.POST.get(f'signature[{index}][physical_address]'),
                                    'town': request.POST.get(f'signature[{index}][town]'),
                                    'postal_code': request.POST.get(f'signature[{index}][postal_code]'),
                                    'postal_address': request.POST.get(f'signature[{index}][postal_address]'),
                                    'last_name': last_name,
                                    'designation': request.POST.get(f'signature[{index}][designation]'),
                                    'ID': request.POST.get(f'signature[{index}][ID]'),
                                    'mobile_no': request.POST.get(f'signature[{index}][mobile_no]'),
                                    'signature': signature_file,
                                    'passport': passport_photo_file
                                })

                # Process the signature data and create entries
                for sig in signatures:
                    name = sig.get('name')
                    last_name = sig.get('last_name')
                    designation = sig.get('designation')
                    id_number = sig.get('ID')
                    mobile_no = sig.get('mobile_no')
                    physical_address = sig.get('physical_address')
                    postal_address = sig.get('postal_address')
                    postal_code = sig.get('postal_code')
                    town = sig.get('town')
                    email = sig.get('email')
                    signature_file = sig.get('signature')
                    passport_photo_file = sig.get('passport')

                    if name and signature_file:
                        ChamaSigningMandate.objects.create(
                            user=user,
                            first_name=name,
                            surname=last_name,
                            designation=designation,
                            id_number=id_number,
                            mobile_no=mobile_no,
                            physical_address=physical_address,
                            postal_address=postal_address,
                            postal_code=postal_code,
                            town=town,
                            email=email,
                            signature=signature_file,
                            passport_photo=passport_photo_file
                        )

                if members_data:
                    # If members_data is a string, it needs to be parsed as JSON
                    if isinstance(members_data, str):
                        try:
                            members_list = json.loads(members_data)
                        except json.JSONDecodeError as e:
                            return JsonResponse({"error": f"Invalid JSON format: {str(e)}"}, status=400)
                    else:
                        # If members_data is already a list, use it directly
                        members_list = members_data
                    for member in members_list:
                        ChamaMember.objects.create(
                            group=user,
                            name=member.get('name'),
                            id_number=member.get('id'),
                            phone=member.get('phone'),
                            address=member.get('address'),
                            position="Member",
                        )

                if officials_data:
                    if isinstance(officials_data, str):
                        try:
                            officials_list = json.loads(officials_data)
                        except json.JSONDecodeError as e:    
                            return JsonResponse({"error": f"Invalid JSON format: {str(e)}"})
                    else:
                        officials_list = officials_data
                    for official in officials_list:
                        # print(f"official {official}")
                        ChamaOfficial.objects.create(
                            group=user,
                            name=official.get("name"),
                            id_number=official.get("id"),
                            phone=official.get("mobile_no"),
                            address=official.get('address'),
                            position=official.get('designation'),
                        )
                
                number_to_sms_otp = telephone_office.lstrip("+")

                # Check if phone starts with "254"
                if number_to_sms_otp.startswith("254"):
                    # Send SMS OTP
                    sms_response = helper_send_sms(phone=number_to_sms_otp, message=f"Your KBS Internet Banking OTP verification is: {otp_digit}", department="User")

                    if sms_response["responses"][0]["response-code"] == 200:
                        otp_sent_via = "sms"
                    else:
                        return JsonResponse({'error': "Failed to send OTP via SMS. Please try again."}, status=500)
                    
                else:
                    # Send Email OTP
                    try:
                        send_mail(
                            "Kenya Bankers Internet Banking OTP Verification",
                            f"Your Kenya Bankers Internet Banking OTP Verification Code is: {otp_digit}",
                            settings.DEFAULT_FROM_EMAIL,
                            [email],  # Make sure user has an email field
                            fail_silently=False,
                            html_message=f'<p>Your Kenya Bankers Internet Banking OTP Verification Code is <strong>{otp_digit}</strong></p>'
                        )
                        otp_sent_via = "email"
                    except Exception as e:
                        return JsonResponse({'error': f"Failed to send OTP via Email: {str(e)}"}, status=500)

                # text_response_sms = helper_send_sms(phone=number_to_sms_otp,message=f"Your KBS Internet Banking OTP verification is: {otp_digit}", department="User")

                # # Handle success or failure
                # if text_response_sms["responses"][0]["response-code"] == 200:
                # # if text_response_sms["responses"][0]["response-code"] == 200:
                #     # Send OTP via email (optional, if you still want to do this)
                #     send_mail(
                #         "OTP Verify Account",
                #         f"Use OTP to verify your account: {otp_digit}",
                #         "email",
                #         [email],
                #         fail_silently=False,
                #         html_message=f'<p>Your OTP is </p><p>{otp_digit}</p>'
                #     )

                refresh = RefreshToken.for_user(user)

                return JsonResponse({'data': response.json(), 'sacco_user_id': sacco_user_id, 'phone':telephone_office, 'access': str(refresh.access_token), 'home':physical_address, 'type' : user.notes,}, status=response.status_code)
                # else:
                #     # Handle SMS sending failure
                #     return JsonResponse({'error': f"Failed to send OTP via SMS"}, status=500)

            except Exception as e:
                        return JsonResponse({'error': f"An error occurred: {str(e)}"}, status=500)
        else:
            return JsonResponse({'error': 'Failed to create member'}, status=response.status_code)

@csrf_exempt
def verify_member_via_otp(request, sacco_user_id):
    if request.method == 'POST':
        otp_digit = request.POST.get('otp_digit')
        user = CustomUser.objects.filter(sacco_user_id=sacco_user_id, otp_digit=otp_digit).first()
        if user:
            user.verify_status = True
            user.save()

            # Fetch member data
            # access_token = get_access_token()
            url = f'https://api.kwara.com/members/{sacco_user_id}'
            headers = {
                'Authorization': f'Bearer {access_token}',
                'accept': 'application/json',
            }
            response = requests.get(url, headers=headers)
            response.raise_for_status()
            member_data = response.json().get('data', {}).get('attributes', {})
            corp_name = user.business
            username = user.name
            role = user.role
            if (role == "Corporate Member"):
                member = corp_name
            else:
                member = username

            masked_sacco_user_id = str(sacco_user_id)[0] + "x" * (len(str(sacco_user_id)) - 1)

            helper_send_sms(phone='254722391827', message=f"{member} - {masked_sacco_user_id} is successfully onboarded. It is pending approval. Do your KYC and approve", department="Customer Service",)
            helper_send_sms(phone='254700531408', message=f"{member} - {masked_sacco_user_id} is successfully onboarded. It is pending approval. Do your KYC and approve", department="Customer Service",)
            helper_send_sms(phone='254790094839', message=f"{member} - {masked_sacco_user_id} is successfully onboarded. It is pending approval. Do your KYC and approve", department="Business Development",)
            send_mail(
                "Kenya Bankers Internet Banking New Member Registraion",
                f"Kenya Bankers Internet Banking New Member Registraion",
                settings.DEFAULT_FROM_EMAIL,
                ["help@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{member} - {masked_sacco_user_id} is successfully onboarded. It is pending approval. Do your KYC and approve</p>'
            )
            send_mail(
                "Kenya Bankers Internet Banking New Member Registraion",
                f"Kenya Bankers Internet Banking New Member Registraion",
                settings.DEFAULT_FROM_EMAIL,
                ["closure@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{member} - {masked_sacco_user_id} is successfully onboarded. It is pending approval. Do your KYC and approve</p>'
            )


            return JsonResponse({
                'bool': True,
                'sacco_user_id': sacco_user_id,
                'member_data': member_data,
                'corp_name': corp_name,
                'username': username,
                'role': role
            })
        else:
            return JsonResponse({'bool': False, 'msg': 'Invalid OTP. Please try again.'}, status=400)
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)

@csrf_exempt
def save_referral(request):
    if request.method == 'POST':
        data = json.loads(request.body)
        sacco_user_id = data.get('sacco_user_id')
        referral = data.get('referral')

        try:
            user = CustomUser.objects.get(sacco_user_id=sacco_user_id)
            user.referral = referral
            user.save()
            return JsonResponse({'message': 'Referral saved successfully'}, status=200)
        except CustomUser.DoesNotExist:
            return JsonResponse({'error': 'User not found'}, status=404)
        except Exception as e:
            return JsonResponse({'error': str(e)}, status=500)
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)
    
def get_profile_picture(request, sacco_user_id):
    profile = get_object_or_404(CustomUser, sacco_user_id=sacco_user_id)
    image = profile.profile_picture  # Assuming you have a FileField or ImageField

    if image:
        with image.open('rb') as img_file:
            mime_type, _ = guess_type(image.url)
            if mime_type:
                return HttpResponse(img_file.read(), content_type=mime_type)
            else:
                return HttpResponse(status=415)  # Unsupported Media Type
    else:
        return HttpResponse(status=404)

def get_signature(request, sacco_user_id):
    signature = get_object_or_404(CustomUser, sacco_user_id=sacco_user_id)
    image = signature.signature  # Assuming you have a FileField or ImageField

    if image:
        with image.open('rb') as img_file:
            # Automatically detect content type (image/jpeg, image/png, etc.)
            mime_type, _ = guess_type(image.url)
            if mime_type:
                return HttpResponse(img_file.read(), content_type=mime_type)
            else:
                return HttpResponse(status=415)  # Unsupported Media Type
    else:
        return HttpResponse(status=404)

@csrf_exempt
def show_member_for_dashboard(request, member_id):
    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": "Permission denied"}, status=403)

    auth_response = extract_user(token=token)

    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)

    user_id = auth_response.get("user_id")
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    # Ensure only admin or the specific user can access
    if user_id != member_id and auth_user.role != "Admin":
        return JsonResponse({"error": "Permission denied"}, status=403)

    if request.method == "GET":
        url = f"https://api.kwara.com/members/{member_id}"
        headers = {
            "Authorization": f"Bearer {access_token}",
            "accept": "application/json",
        }
        try:
            response = requests.get(url, headers=headers)
            response.raise_for_status()  # Raise an error for bad status codes
            response_data = response.json()  # Convert API response to a dictionary

            # # Fetch national ID from CustomUser
            try:
                user = CustomUser.objects.filter(sacco_user_id=member_id).first()
                national_id = user.id_number
            except CustomUser.DoesNotExist:
                national_id = None  # Set to None if user doesn't exist

            # Add national_id to attributes
            if "data" in response_data and "attributes" in response_data["data"]:
                response_data["data"]["attributes"]["national_id"] = national_id

            return JsonResponse(response_data, status=response.status_code)
        except requests.RequestException as e:
            return JsonResponse({"error": str(e)}, status=500)
    else:
        return JsonResponse({"error": "Invalid request method"}, status=405)
    
def member_details(request, member_id):

    token = request.headers.get("Authorization")
    memberr_id = request.headers.get("Member-ID")

    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != memberr_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    member = get_object_or_404(CustomUser, sacco_user_id=member_id)
    Auth_User = get_object_or_404(CustomUser, sacco_user_id=memberr_id)

    kin_details = [
        {
            "name": kin.name,
            "percentage": kin.percentage,
            "phone": kin.phone,
            "relationship": kin.relationship
        } 
        for kin in member.next_of_kin.all()
    ]
    
    savings_details = [
        {
            "name": savings.name
        } 
        for savings in member.savings_account.all()
    ]

    # Use the first CorporateDocuments object if it exists
    corp_docs = member.individual_files.first()
    if corp_docs:
        corp_docs_data = {
            "kra_pin_doc": corp_docs.kra_pin_doc.url if corp_docs.kra_pin_doc else None,
            "birth_cert_doc": corp_docs.birth_cert_doc.url if corp_docs.birth_cert_doc else None,
            "national_id": corp_docs.national_id.url if corp_docs.national_id else None,
        }
    else:
        corp_docs_data = {}

    member_data = {
        "title": member.title,
        "memberID": member.sacco_user_id,
        "name": member.name,
        "member_type": member.notes,
        "email": member.email,
        "dateOfBirth": member.date_of_birth,
        "idNumber": member.id_number,
        "id_type": member.id_type,
        "phone": member.phone,
        "gender": member.gender,
        "gender_other": member.gender_other,
        "postal_address": member.postal_address,
        "physical_address": member.physical_address,
        "marital_status": member.marital_status,
        "marital_status_other": member.marital_status_other,
        "region": member.region,
        "postal_address": member.postal_address,
        "physical_address": member.physical_address,
        "historical_member_id": member.historical_member_id,
        "profession": member.profession,
        "employment_status": member.employment_status,
        "terms_of_service": member.terms_of_service,
        "business_description": member.business_description,
        "business_location": member.business_location,
        "business_county": member.business_county,
        "currently_working": member.currently_working,
        "joining_fee": member.joining_fee,
        "joining_fee_reference": member.joining_fee_reference,
        "share_capital_contribution": member.share_capital_contribution,
        "share_capital_reference": member.share_capital_reference,
        "employer": member.employer,
        "employer_phone_number": member.employer_phone_number,
        "business": member.business,
        "registration_date": member.registration_date,
        "staff_id": member.staff_id,
        "kra_pin": member.kra_pin,
        "subscribed_to_mbanking": member.subscribed_to_mbanking,
        "mobile_loan_disallowed": member.mobile_loan_disallowed,
        "referral": member.referral,
        "next_of_kin": kin_details,
        "savings_account": savings_details,
        "docs_data": corp_docs_data,
        # Add other fields as needed
    }
    # Log user activity for Member Details
    log_user_activity(Auth_User, f"Viewed {member} Member Details", request.path)
    return JsonResponse(member_data)

def memberr_details(request, member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    member = get_object_or_404(CustomUser, sacco_user_id=member_id)

    kin_details = [
        {
            "name": kin.name,
            "percentage": kin.percentage,
            "phone": kin.phone,
            "relationship": kin.relationship
        } 
        for kin in member.next_of_kin.all()
    ]
    
    savings_details = [
        {
            "name": savings.name
        } 
        for savings in member.savings_account.all()
    ]

    # Use the first CorporateDocuments object if it exists
    corp_docs = member.individual_files.first()
    if corp_docs:
        corp_docs_data = {
            "kra_pin_doc": corp_docs.kra_pin_doc.url if corp_docs.kra_pin_doc else None,
            "birth_cert_doc": corp_docs.birth_cert_doc.url if corp_docs.birth_cert_doc else None,
            "national_id": corp_docs.national_id.url if corp_docs.national_id else None,
        }
    else:
        corp_docs_data = {}

    member_data = {
        "title": member.title,
        "memberID": member.sacco_user_id,
        "name": member.name,
        "member_type": member.notes,
        "email": member.email,
        "dateOfBirth": member.date_of_birth,
        "idNumber": member.id_number,
        "id_type": member.id_type,
        "phone": member.phone,
        "gender": member.gender,
        "gender_other": member.gender_other,
        "postal_address": member.postal_address,
        "physical_address": member.physical_address,
        "marital_status": member.marital_status,
        "marital_status_other": member.marital_status_other,
        "region": member.region,
        "postal_address": member.postal_address,
        "physical_address": member.physical_address,
        "historical_member_id": member.historical_member_id,
        "profession": member.profession,
        "employment_status": member.employment_status,
        "terms_of_service": member.terms_of_service,
        "business_description": member.business_description,
        "business_location": member.business_location,
        "business_county": member.business_county,
        "currently_working": member.currently_working,
        "joining_fee": member.joining_fee,
        "joining_fee_reference": member.joining_fee_reference,
        "share_capital_contribution": member.share_capital_contribution,
        "share_capital_reference": member.share_capital_reference,
        "employer": member.employer,
        "employer_phone_number": member.employer_phone_number,
        "business": member.business,
        "registration_date": member.registration_date,
        "staff_id": member.staff_id,
        "kra_pin": member.kra_pin,
        "subscribed_to_mbanking": member.subscribed_to_mbanking,
        "mobile_loan_disallowed": member.mobile_loan_disallowed,
        "referral": member.referral,
        "next_of_kin": kin_details,
        "savings_account": savings_details,
        "docs_data": corp_docs_data,
        # Add other fields as needed
    }
    return JsonResponse(member_data)

def get_member_name(request, member_ID):
    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_ID and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    try:
        # Fetch the user with the given member_ID
        user = get_object_or_404(CustomUser, sacco_user_id=member_ID)
        
        # Check the user's notes to determine the name to return
        if user.notes == "Corporate Member":
            return JsonResponse({"name": user.business}, status=200)
        else:
            return JsonResponse({"name": user.name}, status=200)
    except Exception as e:
        # Log error and return an error response
        # print(f"Error fetching member details: {e}")
        return JsonResponse({"error": "Member not found or an error occurred."}, status=404)


# @csrf_exempt
# def corp_member_details(request, member_id):
#     member = get_object_or_404(CustomUser, sacco_user_id=member_id)
#     corporate_documents = member.corp_files.all()  # Retrieve all CorporateDocuments for the user

#     kin_details = [
#         {
#             "name": kin.name,
#             "percentage": kin.percentage,
#             "phone": kin.phone,
#             "relationship": kin.relationship
#         } 
#         for kin in member.next_of_kin.all()
#     ]
    
#     savings_details = [
#         {
#             "name": savings.name
#         } 
#         for savings in member.savings_account.all()
#     ]
    
#     signatories_details = [
#         {
#             "name": signator.name,
#             "signature": signator.signature.url if signator.signature else None  # Convert to URL
#         } 
#         for signator in member.corp_signature.all()
#     ]
    
#     # Use the first CorporateDocuments object if it exists
#     corp_docs = member.corp_files.first()
#     if corp_docs:
#         corp_docs_data = {
#             "reg_certificate": corp_docs.reg_certificate.url if corp_docs.reg_certificate else None,
#             "kra_pin_doc": corp_docs.kra_pin_doc.url if corp_docs.kra_pin_doc else None,
#             "cr_12": corp_docs.cr_12.url if corp_docs.cr_12 else None,
#         }
#     else:
#         corp_docs_data = {}

#     for document in corporate_documents:
#         # Fetch all passport photos
#         passport_photos = document.passport_photos.all()
#         passport_photos_data = [
#             {
#                 "name": photo.name,  # Include the name
#                 "file": photo.photo.url if photo.photo else None  # Include the URL of the photo
#             } 
#             for photo in passport_photos if photo.photo
#         ]

#         # passport_photos_urls = [photo.photo.url for photo in passport_photos if photo.photo]
#         # print(passport_photos_urls)

#         # Fetch all board resolutions
#         board_resolutions = document.board_resolutions.all()
#         board_resolutions_urls = [resolution.file.url for resolution in board_resolutions if resolution.file]

#     member_data = {
#         "title": member.title,
#         "name": member.name,
#         "email": member.email,
#         "dateOfBirth": member.date_of_birth,
#         "idNumber": member.id_number,
#         "phone": member.phone,
#         "gender": member.gender,
#         "postal_address": member.postal_address,
#         "physical_address": member.physical_address,
#         "marital_status": member.marital_status,
#         "member_type": member.member_type,
#         "secondary_phone_number": member.secondary_phone_number,
#         "postal_address": member.postal_address,
#         "physical_address": member.physical_address,
#         "company_type": member.company_type,
#         "business_description": member.business_description,
#         "monthly_net_cashflow": member.monthly_net_cashflow,
#         "services": member.services,
#         "business_county": member.business_county,
#         "business_location": member.business_location,
#         "registration_date": member.registration_date,
#         "joining_fee": member.joining_fee,
#         "joining_fee_reference": member.joining_fee_reference,
#         "share_capital_contribution": member.share_capital_contribution,
#         "share_capital_reference": member.share_capital_reference,
#         "employer": member.employer,
#         "registration_number": member.registration_number,
#         "business": member.business,
#         "kra_pin": member.kra_pin,
#         "signing_mandate": member.signing_mandate,
#         "referral": member.referral,
#         "next_of_kin": kin_details,
#         "savings_account": savings_details,
#         "corp_docs": corp_docs_data,
#         "signatories": signatories_details,
#         "passport_photos": passport_photos_data,
#         "board_resolutions": board_resolutions_urls,
#         # Add other fields as needed
#     }
#     # Log user activity for Member Details
#     log_user_activity(member, "Viewed Member Details", request.path)
#     return JsonResponse(member_data)
# ss
@csrf_exempt
def corp_member_details(request, member_id):

    token = request.headers.get("Authorization")
    memberr_id = request.headers.get("Member-ID")

    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != memberr_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    member = get_object_or_404(CustomUser, sacco_user_id=member_id)
    Auth_User = get_object_or_404(CustomUser, sacco_user_id=memberr_id)
    corporate_documents = member.corp_files.all()  # Retrieve all CorporateDocuments for the user

    kin_details = [
        {
            "name": kin.name,
            "percentage": kin.percentage,
            "phone": kin.phone,
            "relationship": kin.relationship
        }
        for kin in member.next_of_kin.all()
    ]

    savings_details = [
        {
            "name": savings.name
        }
        for savings in member.savings_account.all()
    ]

    signatories_details = [
        {
            "name": signator.name,
            "id": signator.id_no,
            "signature": signator.signature.url if signator.signature else None  # Convert to URL
        }
        for signator in member.corp_signature.all()
    ]

    # Use the first CorporateDocuments object if it exists
    corp_docs = member.corp_files.first()
    if corp_docs:
        # Get KRA Pin photos related to this Corporate Document
        kra_pin_photos = [
            {
                "name": kra_photo.name,
                "file": kra_photo.photo.url if kra_photo.photo else None
            }
            for kra_photo in corp_docs.kra_photos.all()
        ]
        corp_docs_data = {
            "reg_certificate": corp_docs.reg_certificate.url if corp_docs.reg_certificate else None,
            # "kra_pin_doc": corp_docs.kra_pin_doc.url if corp_docs.kra_pin_doc else None,
            "kra_pin_photos": kra_pin_photos,  # Include KRA Pin photos in corp_docs_data
            "cr_12": corp_docs.cr_12.url if corp_docs.cr_12 else None,
        }
    else:
        corp_docs_data = {}

    for document in corporate_documents:
        # Fetch all passport photos
        passport_photos = document.passport_photos.all()
        passport_photos_data = [
            {
                "name": photo.name,  # Include the name
                "file": photo.photo.url if photo.photo else None  # Include the URL of the photo
            }
            for photo in passport_photos if photo.photo
        ]

        # passport_photos_urls = [photo.photo.url for photo in passport_photos if photo.photo]
        # print(passport_photos_urls)

        # Fetch all board resolutions
        board_resolutions = document.board_resolutions.all()
        board_resolutions_urls = [resolution.file.url for resolution in board_resolutions if resolution.file]

    member_data = {
        "title": member.title,
        "name": member.name,
        "email": member.email,
        "dateOfBirth": member.date_of_birth,
        "idNumber": member.id_number,
        "phone": member.phone,
        "gender": member.gender,
        "postal_address": member.postal_address,
        "physical_address": member.physical_address,
        "marital_status": member.marital_status,
        "member_type": member.member_type,
        "region": member.region,
        "postal_address": member.postal_address,
        "physical_address": member.physical_address,
        "company_type": member.company_type,
        "business_description": member.business_description,
        "monthly_net_cashflow": member.monthly_net_cashflow,
        "services": member.services,
        "business_county": member.business_county,
        "business_location": member.business_location,
        "registration_date": member.registration_date,
        "joining_fee": member.joining_fee,
        "joining_fee_reference": member.joining_fee_reference,
        "share_capital_contribution": member.share_capital_contribution,
        "share_capital_reference": member.share_capital_reference,
        "employer": member.employer,
        "registration_number": member.registration_number,
        "business": member.business,
        "kra_pin": member.kra_pin,
        "signing_mandate": member.signing_mandate,
        "referral": member.referral,
        "next_of_kin": kin_details,
        "savings_account": savings_details,
        "corp_docs": corp_docs_data,
        "signatories": signatories_details,
        "passport_photos": passport_photos_data,
        "board_resolutions": board_resolutions_urls,
        # Add other fields as needed
    }
    # Log user activity for Member Details
    log_user_activity(Auth_User, f"Viewed {member} Member Details", request.path)
    return JsonResponse(member_data)

@csrf_exempt
def chama_member_details(request, member_id):

    token = request.headers.get("Authorization")
    memberr_id = request.headers.get("Member-ID")

    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != memberr_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    member = get_object_or_404(CustomUser, sacco_user_id=member_id)
    Auth_User = get_object_or_404(CustomUser, sacco_user_id=memberr_id)
    # Deserialize account types
    account_types = []
    if member.chama_account_type:
        try:
            account_types = json.loads(member.chama_account_type)
        except json.JSONDecodeError:
            account_types = []

    # Deserialize bank accounts
    bank_accounts = []
    if member.chama_other_bank_accounts:
        try:
            bank_accounts = json.loads(member.chama_other_bank_accounts)
        except json.JSONDecodeError:
            bank_accounts = []
    signatories_details = [
        {
            "first_name": signator.first_name,
            "surname": signator.surname,
            "designation": signator.designation,
            "id_number": signator.id_number,
            "mobile_no": signator.mobile_no,
            "physical_address": signator.physical_address,
            "postal_address": signator.postal_address,
            "postal_code": signator.postal_code,
            "town": signator.town,
            "email": signator.email,
            "signature": request.build_absolute_uri(signator.signature.url) if signator.signature else None,
            "passport_photo": request.build_absolute_uri(signator.passport_photo.url) if signator.passport_photo else None,
            "created_at": signator.created_at,
            "updated_at": signator.updated_at,
        }
        for signator in member.chama_signature_mandate.all()
    ]
    # Fetch Chama Members Details
    chama_members_details = [
        {
            "name": chama_member.name,
            "id_number": chama_member.id_number,
            "phone": chama_member.phone,
            "address": chama_member.address,
            "position": chama_member.position,
        }
        for chama_member in member.members.all()
    ]
    chama_official_details = [
        {
            "name": chama_official.name,
            "id_number": chama_official.id_number,
            "phone": chama_official.phone,
            "address": chama_official.address,
            "position": chama_official.position,

        }
        for chama_official in member.officials.all()
    ]
    member_data = {
        # "title": member.title,
        "name": member.name,
        "email": member.email,
        # "dateOfBirth": member.date_of_birth,
        # "idNumber": member.id_number,
        "phone": member.chama_telephone_office,
        # "gender": member.gender,
        "role": member.role,
        "notes": member.notes,
        "postal_address": member.postal_address,
        "physical_address": member.physical_address,
        "chama_number_of_members": member.chama_number_of_members,
        "postal_code": member.postal_code,
        "chama_town": member.chama_town,
        "region": member.region,
        "chama_nature_of_business": member.chama_nature_of_business,
        # "marital_status": member.marital_status,
        # "member_type": member.member_type,
        # "secondary_phone_number": member.secondary_phone_number,
        "postal_address": member.postal_address,
        "chama_date_of_incorporation": member.chama_date_of_incorporation,
        "chama_certificate_of_incorporation_number": member.chama_certificate_of_incorporation_number,
        # "physical_address": member.physical_address,
        "company_type": member.company_type,
        "business_description": member.business_description,
        "monthly_net_cashflow": member.monthly_net_cashflow,
        "services": member.services,
        "business_county": member.business_county,
        "business_location": member.business_location,
        "registration_date": member.registration_date,
        "joining_fee": member.joining_fee,
        "joining_fee_reference": member.joining_fee_reference,
        "share_capital_contribution": member.share_capital_contribution,
        "share_capital_reference": member.share_capital_reference,
        "employer": member.employer,
        "registration_number": member.registration_number,
        "business": member.business,
        "kra_pin": member.kra_pin,
        "signing_mandate": member.signing_mandate,
        "referral": member.referral,
        "signatories": signatories_details,
        "chama_members": chama_members_details,  # Add chama members to response
        "chama_officials": chama_official_details,
        "account_types": account_types,  # Add account types
        "bank_accounts": bank_accounts,  # Add bank accounts
        # Add other fields as needed
    }
    # Log user activity for Member Details
    log_user_activity(Auth_User, f"Viewed {member} Member Details", request.path)
    return JsonResponse(member_data)

@csrf_exempt
def show_onboarded_chama_member(request, member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    member = get_object_or_404(CustomUser, sacco_user_id=member_id)
    # Deserialize account types
    account_types = []
    if member.chama_account_type:
        try:
            account_types = json.loads(member.chama_account_type)
        except json.JSONDecodeError:
            account_types = []

    # Deserialize bank accounts
    bank_accounts = []
    if member.chama_other_bank_accounts:
        try:
            bank_accounts = json.loads(member.chama_other_bank_accounts)
        except json.JSONDecodeError:
            bank_accounts = []
    signatories_details = [
        {
            "first_name": signator.first_name,
            "surname": signator.surname,
            "designation": signator.designation,
            "id_number": signator.id_number,
            "mobile_no": signator.mobile_no,
            "physical_address": signator.physical_address,
            "postal_address": signator.postal_address,
            "postal_code": signator.postal_code,
            "town": signator.town,
            "email": signator.email,
            "signature": request.build_absolute_uri(signator.signature.url) if signator.signature else None,
            "passport_photo": request.build_absolute_uri(signator.passport_photo.url) if signator.passport_photo else None,
            "created_at": signator.created_at,
            "updated_at": signator.updated_at,
        }
        for signator in member.chama_signature_mandate.all()
    ]
    # Fetch Chama Members Details
    chama_members_details = [
        {
            "name": chama_member.name,
            "id_number": chama_member.id_number,
            "phone": chama_member.phone,
            "address": chama_member.address,
            "position": chama_member.position,
        }
        for chama_member in member.members.all()
    ]
    chama_official_details = [
        {
            "name": chama_official.name,
            "id_number": chama_official.id_number,
            "phone": chama_official.phone,
            "address": chama_official.address,
            "position": chama_official.position,

        }
        for chama_official in member.officials.all()
    ]
    member_data = {
        # "title": member.title,
        "name": member.name,
        "email": member.email,
        # "dateOfBirth": member.date_of_birth,
        # "idNumber": member.id_number,
        "phone": member.chama_telephone_office,
        # "gender": member.gender,
        "role": member.role,
        "notes": member.notes,
        "postal_address": member.postal_address,
        "physical_address": member.physical_address,
        "chama_number_of_members": member.chama_number_of_members,
        "postal_code": member.postal_code,
        "chama_town": member.chama_town,
        "region": member.region,
        "chama_nature_of_business": member.chama_nature_of_business,
        # "marital_status": member.marital_status,
        # "member_type": member.member_type,
        # "secondary_phone_number": member.secondary_phone_number,
        "postal_address": member.postal_address,
        "chama_date_of_incorporation": member.chama_date_of_incorporation,
        "chama_certificate_of_incorporation_number": member.chama_certificate_of_incorporation_number,
        # "physical_address": member.physical_address,
        "company_type": member.company_type,
        "business_description": member.business_description,
        "monthly_net_cashflow": member.monthly_net_cashflow,
        "services": member.services,
        "business_county": member.business_county,
        "business_location": member.business_location,
        "registration_date": member.registration_date,
        "joining_fee": member.joining_fee,
        "joining_fee_reference": member.joining_fee_reference,
        "share_capital_contribution": member.share_capital_contribution,
        "share_capital_reference": member.share_capital_reference,
        "employer": member.employer,
        "registration_number": member.registration_number,
        "business": member.business,
        "kra_pin": member.kra_pin,
        "signing_mandate": member.signing_mandate,
        "referral": member.referral,
        "signatories": signatories_details,
        "chama_members": chama_members_details,  # Add chama members to response
        "chama_officials": chama_official_details,
        "account_types": account_types,  # Add account types
        "bank_accounts": bank_accounts,  # Add bank accounts
        # Add other fields as needed
    }
    return JsonResponse(member_data)

@api_view(['POST'])
@csrf_exempt
def change_password(request):
    if request.method == 'POST':
        data = json.loads(request.body)
        sacco_user_id = data.get('sacco_user_id')

        old_password = request.data.get('old_password')
        new_password = request.data.get('new_password')
        try:
            user = CustomUser.objects.get(sacco_user_id=sacco_user_id)
            if not check_password(old_password, user.password):
                return JsonResponse({'error': 'Old password is incorrect'}, status=400)
            user.set_password(new_password)
            user.save()

            # Log user activity for Change Password
            log_user_activity(user, "Password Changed", request.path)
            return JsonResponse({'success': 'Password changed successfully'}, status=200)
        except CustomUser.DoesNotExist:
            return JsonResponse({'error': 'User not found'}, status=404)
        except Exception as e:
            return JsonResponse({'error': str(e)}, status=500)
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)


@csrf_exempt
def validate_ID(request):
    IPRS_access_token = get_iprs_access_token()

    data = json.loads(request.body)
    id_number = data.get("id_number")

    if not id_number:
        return JsonResponse({"error": "ID number is required"}, status=400)

    if CustomUser.objects.filter(id_number=id_number).exists():
        return JsonResponse({'error': 'ID number already exists'}, status=500)
    try:
        url = f"https://api.spinmobile.co/api/analytics/account/iprs"
        headers = CaseInsensitiveDict()
        headers["Accept"] = "application/json"
        headers["Authorization"] = f"Bearer {IPRS_access_token}"
        headers["Content-Type"] = "application/json"
        data = f"""
            {{
                "search_type": "identity",
                "identifier": "{id_number}"
            }}
        """
        response = requests.post(url, headers=headers, data=data)
        response.raise_for_status()  # Raise an error for bad status codes
        api_response = response.json()
        return JsonResponse(api_response, status=response.status_code)
    except requests.RequestException as e:
        return JsonResponse({'error': str(e)}, status=500)

@csrf_exempt
def signature_validate_ID(request):
    IPRS_access_token = get_iprs_access_token()

    data = json.loads(request.body)
    id_number = data.get("id_number")

    if not id_number:
        return JsonResponse({"error": "ID number is required"}, status=400)

    try:
        url = f"https://api.spinmobile.co/api/analytics/account/iprs"
        headers = CaseInsensitiveDict()
        headers["Accept"] = "application/json"
        headers["Authorization"] = f"Bearer {IPRS_access_token}"
        headers["Content-Type"] = "application/json"
        data = f"""
            {{
                "search_type": "identity",
                "identifier": "{id_number}"
            }}
        """
        response = requests.post(url, headers=headers, data=data)
        response.raise_for_status()  # Raise an error for bad status codes
        api_response = response.json()
        return JsonResponse(api_response, status=response.status_code)
    except requests.RequestException as e:
        return JsonResponse({'error': str(e)}, status=500)
    
# def validate_ID(request):
#     if request.method == 'POST':
#         data = json.loads(request.body)
#         idNumber = data

#         # old_password = request.data.get('old_password')
#         # new_password = request.data.get('new_password')
#         try:
#             if idNumber:
#                 print(idNumber)
#                 return JsonResponse({'success': 'ID Valid'}, status=200)
#             # else:
#             #     return JsonResponse({'error': 'ID not Valid'}, status=404)

            
        
#         except Exception as e:
#             return JsonResponse({'error': str(e)}, status=500)
#     else:
#         return JsonResponse({'error': 'Invalid request method'}, status=405)

# @csrf_exempt
# def contact_us(request):
#     if request.method == 'POST':
#         try:
#             data = json.loads(request.body)
#             email = data.get('email')
#             subject = data.get('subject')
#             message = data.get('message')

#             # Save the message to the database
#             ContactMessage.objects.create(
#                 email=email,
#                 subject=subject,
#                 message=message
#             )
#             return JsonResponse({"message": "Message sent successfully!"}, status=201)
#         except Exception as e:
#             return JsonResponse({"error": str(e)}, status=400)
#     else:
#         return JsonResponse({"error": "Invalid request method"}, status=405)
    
@csrf_exempt
def show_onboarded_member(request, member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    member = CustomUser.objects.get(sacco_user_id=member_id)
    user_details = []
    # Get profile picture and signature URLs, if they exist
    profile_picture_url = member.profile_picture.url if member.profile_picture else None
    signature_url = member.signature.url if member.signature else None
    user_details.append({
        'sacco_user_id' : member.sacco_user_id,
        "name" : member.name,
        'email' : member.email,
        'title' : member.title,
        'date_of_birth': member.date_of_birth,
        'id_number': member.id_number,
        'phone_number': member.phone,
        'region': member.region,
        'postal_address' : member.postal_address,
        'physical_address': member.physical_address,
        "marital_status":member.marital_status,
        'gender':member.gender,
        "staff_id":member.staff_id,
        "kra_pin": member.kra_pin,
        "profession": member.profession,
        "employment_status": member.employment_status,
        "terms_of_service": member.terms_of_service,
        "currently_working": member.currently_working,
        "joining_fee": member.joining_fee,
        "joining_fee_reference": member.joining_fee_reference,
        "employer": member.employer,
        "employer_phone_number":member.employer_phone_number,
        "business":member.business,
        "historical_member_id":member.historical_member_id,
        "referral":member.referral,
        "subscribed_to_mbanking":member.subscribed_to_mbanking,
        "mobile_loan_disallowed":member.mobile_loan_disallowed,
        "profile_picture":profile_picture_url,
        "signature":signature_url,
        "role":member.role,
        "notes":member.notes,
    })
    return JsonResponse({"data": user_details})

@csrf_exempt
def show_onboarded_member_next_of_kin(request, member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    member = CustomUser.objects.get(sacco_user_id=member_id)
    next_of_kin_list = []
    member_next_of_kins = NextOfKin.objects.filter(user=member,is_deleted=False)

    for nok in member_next_of_kins:
        next_of_kin_list.append({
            'id': nok.id,
            'name': nok.name,
            'percentage': nok.percentage,
            'phone': nok.phone,
            'relationship': nok.relationship,
            'created_at': nok.created_at,
        })

    return JsonResponse({"data": next_of_kin_list})

@csrf_exempt
def show_onboarded_corporate_member(request, member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    member = CustomUser.objects.get(sacco_user_id=member_id)
    user_details = []
    # Get profile picture and signature URLs, if they exist
    profile_picture_url = member.profile_picture.url if member.profile_picture else None
    signature_url = member.signature.url if member.signature else None
    user_details.append({
        'sacco_user_id' : member.sacco_user_id,
        "title": member.title,
        "name": member.name,
        "email": member.email,
        "date_of_birth": member.date_of_birth,
        "id_number": member.id_number,
        "phone": member.phone,
        "gender": member.gender,
        "postal_address": member.postal_address,
        "physical_address": member.physical_address,
        "marital_status": member.marital_status,
        "member_type": member.member_type,
        "region": member.region,
        "postal_address": member.postal_address,
        "physical_address": member.physical_address,
        "company_type": member.company_type,
        "business_description": member.business_description,
        "monthly_net_cashflow": member.monthly_net_cashflow,
        "services": member.services,
        "business_county": member.business_county,
        "business_location": member.business_location,
        "registration_date": member.registration_date,
        "joining_fee": member.joining_fee,
        "joining_fee_reference": member.joining_fee_reference,
        "share_capital_contribution": member.share_capital_contribution,
        "share_capital_reference": member.share_capital_reference,
        "employer": member.employer,
        "registration_number": member.registration_number,
        "business": member.business,
        "kra_pin": member.kra_pin,
        "referral": member.referral,
        "role": member.role,
        "notes": member.notes,
        # "savings_account": savings_details,
        # "corp_docs": corp_docs_data,
        # "signatories": signatories_details,
        "profile_picture":profile_picture_url,
        "signature":signature_url,
    })
    return JsonResponse({"data": user_details})

@csrf_exempt
def update_user_profile(request, member_id):

    token = request.headers.get("Authorization")
    memberr_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != memberr_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    try:
        user = CustomUser.objects.get(sacco_user_id=member_id)
        AdminUser = CustomUser.objects.get(sacco_user_id=memberr_id)
        sender_name = user.business if user.notes == 'Corporate Member' else user.name
      
        data = json.loads(request.body)
        # Update only fields that are in the request
        for key, value in data.items():
            if hasattr(user, key):
                setattr(user, key, value)
        
        user.save()

        # Log user activity for viewing savings
        log_user_activity(AdminUser, f"{sender_name} - {member_id} Details Edited", request.path)
        return JsonResponse({"success": "User profile updated"}, status=200)
    except CustomUser.DoesNotExist:
        return JsonResponse({"error": "User not found"}, status=404)
    except Exception as e:
        return JsonResponse({"error": str(e)}, status=400)

@csrf_exempt
def update_chama_user_profile(request, member_id):

    token = request.headers.get("Authorization")
    memberr_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != memberr_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    try:
        user = CustomUser.objects.get(sacco_user_id=member_id)
        AdminUser = CustomUser.objects.get(sacco_user_id=memberr_id)
        sender_name = user.business if user.notes == 'Corporate Member' else user.name
        data = json.loads(request.body)

        # Update other fields in the user profile
        for key, value in data.items():
            if key != "chama_members" and key != "signatories" and hasattr(user, key):
                setattr(user, key, value)

        user.save()
        # Update chama_number_of_members if provided
        if "chama_number_of_members" in data:
            user.chama_number_of_members = data["chama_number_of_members"]
            user.save()

        # Update or create Chama members
        if "chama_members" in data:
            members_data = data["chama_members"]
            existing_members = ChamaMember.objects.filter(group=user)
            
            # Clear and recreate members to match the frontend
            existing_members.delete()
            for member_data in members_data:
                ChamaMember.objects.create(
                    group=user,
                    name=member_data.get("name"),
                    id_number=member_data.get("id_number"),
                    phone=member_data.get("phone"),
                    address=member_data.get("address"),
                    position=member_data.get("position"),
                )

        if "chama_officials" in data:
            officials_data = data['chama_officials']
            existing_officials = ChamaOfficial.objects.filter(group=user)
            existing_officials.delete()

            for official in officials_data:
                ChamaOfficial.objects.create(
                    group=user,
                    name=official.get("name"),
                    id_number=official.get("id_number"),
                    phone=official.get("phone"),
                    address=official.get("address"),
                    position=official.get("position"),

                )

        # Update or create Chama signing mandates (signatories)
        if "signatories" in data:
            
            signatories_data = data["signatories"]
            existing_signatory_ids = [
                signatory["id"] for signatory in signatories_data if signatory.get("id")
            ]
            # Remove signatories not in the payload
            ChamaSigningMandate.objects.filter(user=user).exclude(id__in=existing_signatory_ids).delete()

            for signatory_data in signatories_data:
                signatory_id = signatory_data.get("id")
                if signatory_id:
                    # Update existing signatory
                    signatory = ChamaSigningMandate.objects.get(id=signatory_id, user=user)
                    for field, value in signatory_data.items():
                        if hasattr(signatory, field):
                            setattr(signatory, field, value)
                    signatory.save()
                else:
                    # Create new signatory
                    ChamaSigningMandate.objects.create(
                        user=user,
                        first_name=signatory_data.get("first_name"),
                        surname=signatory_data.get("surname"),
                        designation=signatory_data.get("designation"),
                        id_number=signatory_data.get("id_number"),
                        mobile_no=signatory_data.get("mobile_no"),
                        physical_address=signatory_data.get("physical_address"),
                        postal_address=signatory_data.get("postal_address"),
                        postal_code=signatory_data.get("postal_code"),
                        town=signatory_data.get("town"),
                        email=signatory_data.get("email"),
                    )

        # Log user activity for viewing savings
        log_user_activity(AdminUser, f"{sender_name} - {member_id} Details Edited", request.path)
        return JsonResponse({"success": "User profile updated"}, status=200)
    except CustomUser.DoesNotExist:
        return JsonResponse({"error": "User not found"}, status=404)
    except Exception as e:
        return JsonResponse({"error": str(e)}, status=400)
    
@csrf_exempt
def update_chama_signatories(request, member_id):
    try:
        # Fetch the user based on the member ID
        user = CustomUser.objects.get(sacco_user_id=member_id)
        
        # Check if the request is in multipart/form-data format (for file uploads)
        if request.content_type != "multipart/form-data":
            return JsonResponse({"error": "Invalid content type. Expected multipart/form-data."}, status=400)
        
        # Extract signatories data from the request
        signatories_data = request.POST.getlist('signatories')
        files = request.FILES  # This will include the file uploads (signature, passport photo)
        
        # Clear existing signatories for this user
        ChamaSigningMandate.objects.filter(user=user).delete()
        
        # Process each signatory's data
        for i, signatory_data in enumerate(signatories_data):
            signatory_info = json.loads(signatory_data)  # Assuming the signatory data is JSON encoded

            # Extract file uploads for this signatory
            signature_file = files.get(f"signatories[{i}].signature")
            passport_photo_file = files.get(f"signatories[{i}].passport_photo")

            # Create a new ChamaSigningMandate object for each signatory
            ChamaSigningMandate.objects.create(
                user=user,
                first_name=signatory_info.get("first_name"),
                surname=signatory_info.get("surname"),
                designation=signatory_info.get("designation"),
                id_number=signatory_info.get("id_number"),
                mobile_no=signatory_info.get("mobile_no"),
                physical_address=signatory_info.get("physical_address"),
                postal_address=signatory_info.get("postal_address"),
                postal_code=signatory_info.get("postal_code"),
                town=signatory_info.get("town"),
                email=signatory_info.get("email"),
                signature=signature_file,  # File uploaded for signature
                passport_photo=passport_photo_file,  # File uploaded for passport photo
            )
        
        return JsonResponse({"success": "Signatories updated successfully."}, status=200)
    
    except CustomUser.DoesNotExist:
        return JsonResponse({"error": "User not found."}, status=404)
    
    except Exception as e:
        return JsonResponse({"error": str(e)}, status=400)

@csrf_exempt
def update_user_images(request, member_id):

    token = request.headers.get("Authorization")
    memberr_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != memberr_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    try:
        profile = get_object_or_404(CustomUser, sacco_user_id=member_id)
        AdminUser = get_object_or_404(CustomUser, sacco_user_id=memberr_id)

        sender_name = profile.business if profile.notes == 'Corporate Member' else profile.name

        # Check if files are included in the request
        if 'profile_picture' in request.FILES:
            profile.profile_picture = request.FILES['profile_picture']
        if 'signature' in request.FILES:
            profile.signature = request.FILES['signature']

        profile.save()

        # Log user activity for viewing savings
        log_user_activity(AdminUser, f"{sender_name} - {member_id} Profile Img Edited", request.path)

    # return JsonResponse({'message': 'Profile updated successfully'}, status=200)
        return JsonResponse({"success": "User profile updated"}, status=200)
    except CustomUser.DoesNotExist:
        return JsonResponse({"error": "User not found"}, status=404)
    except Exception as e:
        return JsonResponse({"error": str(e)}, status=400)

@csrf_exempt
def update_user_next_of_kin(request, member_id):

    token = request.headers.get("Authorization")
    memberr_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != memberr_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    try:
        member = CustomUser.objects.get(sacco_user_id=member_id)
        AdminUser = CustomUser.objects.get(sacco_user_id=memberr_id)
        sender_name = member.business if member.notes == 'Corporate Member' else member.name
        data = json.loads(request.body)  # Parse JSON data from request
        
        next_of_kin_data = data.get('nextOfKins', [])
        
        for nok_data in next_of_kin_data:
                delete = nok_data.get('is_deleted')
                nok_id = nok_data.get('id')  # Unique identifier for existing next of kin
                # print(f"delete input - {delete}")
                if nok_id:  # If id is present, attempt to update existing record
                    next_of_kin, created = NextOfKin.objects.update_or_create(
                        id=nok_id,  # Unique id for the existing record
                        user=member,
                        defaults={
                            'name': nok_data.get('name'),
                            'percentage': nok_data.get('percentage'),
                            'phone': nok_data.get('phone'),
                            'relationship': nok_data.get('relationship'),
                            'is_deleted':  1 if delete == True else 0
                        }
                    )
                else:  # If id is not present, create a new next of kin entry
                    NextOfKin.objects.create(
                        user=member,
                        name=nok_data.get('name'),
                        percentage=nok_data.get('percentage'),
                        phone=nok_data.get('phone'),
                        relationship=nok_data.get('relationship'),
                        is_deleted = 1 if delete == True else 0
                    )
                # NextOfKin.objects.update_or_create(
                #     user=member,
                #     name=nok_data.get('name'),
                #     defaults={
                #         'percentage': nok_data.get('percentage'),
                #         'phone': nok_data.get('phone'),
                #         'relationship': nok_data.get('relationship'),
                #         'is_deleted':  1 if delete == True else 0  # Ensure non-deleted entries are marked correctly
                #         # 1 if  delete == "true" else 0
                #     }
                # )
        NextOfKin.objects.filter(user=member, is_deleted=True).delete()

        # Log user activity for viewing savings
        log_user_activity(AdminUser, f"{sender_name} - {member_id} Next of Kin Edited", request.path)
        
        return JsonResponse({'message': 'Next of kin updated successfully'}, status=200)
    except CustomUser.DoesNotExist:
        return JsonResponse({'error': 'Member not found'}, status=404)
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)


@csrf_exempt
def show_member(request, member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    # access_token = get_access_token()
    if request.method == 'GET':
        url = f'https://api.kwara.com/members/{member_id}'
        headers = {
            'Authorization' : f'Bearer {access_token}',
            'accept': 'application/json',
        }
        try:
            response = requests.get(url, headers=headers)
            response.raise_for_status()  # Raise an error for bad status codes
            return JsonResponse(response.json(), status=response.status_code)
        except requests.RequestException as e:
            return JsonResponse({'error': str(e)}, status=500)
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)

@csrf_exempt
def check_loan_eligibility(request, member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    if request.method == 'GET':
        url = f'https://api.kwara.com/members/{member_id}'
        headers = {
            'Authorization': f'Bearer {access_token}',
            'accept': 'application/json',
        }
        try:
            response = requests.get(url, headers=headers)
            response.raise_for_status()
            data = response.json()

            # Extract `created_at` and calculate days
            created_at_str = data.get("data", {}).get("attributes", {}).get("created_at")
            if created_at_str:
                created_at = parse_datetime(created_at_str)
                today = now()
                days_since_creation = (today - created_at).days
                if days_since_creation < 90:
                    days_left = 90 - days_since_creation
                    return JsonResponse({"eligible": False, "days_left": days_left}, status=200)
                return JsonResponse({"eligible": True}, status=200)
            return JsonResponse({"error": "Missing `created_at` field"}, status=400)
        except requests.RequestException as e:
            return JsonResponse({'error': str(e)}, status=500)
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)
    
@csrf_exempt
def create_m_loan_application(request,member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    # if user_id != member_id and auth_user.role != 'Admin':
    #     return JsonResponse({"error": 'permission denied'}, status=403)

    if not (str(user_id)) == str(member_id):
        return JsonResponse({"error": 'permission denied'}, status=403)

    if request.method != 'POST':
        return JsonResponse({'error': 'Invalid request method'}, status=400)

    data = json.loads(request.body)
    amount = data.get('amount')
    user = CustomUser.objects.filter(sacco_user_id=member_id).first()
    phone = user.phone
    sender_name = user.business if user.notes == 'Corporate Member' else user.name
    anticipated_disbursement_date = datetime.today().strftime('%Y-%m-%d')

    def generate_first_repayment_date():
        today = datetime.today()
        future_date = today + timedelta(days=30)
        return future_date.strftime('%Y-%m-%d')
    first_repayment_date = generate_first_repayment_date()
    serializer = LoanApplicationSerializer(data=data)
    if serializer.is_valid():
    #     # Get the account holder based on the member_id
        account_holder = get_object_or_404(CustomUser, sacco_user_id=member_id)
        # Send the loan application to the external API
        url = f"https://api.kwara.com/members/1450UKNJ/loans"
        payload = { "data": { "attributes": {
            "repayment_period_unit": "DAYS",
            "disbursement_mode": "fosa",
            "disbursement_bank_details": {
               "bank": "Kenya Bankers",
               "bank_branch": "Kenya Bankers",
               "account_number": "FOSA"
            },
            "account_holder_id": member_id,
            "product_id": "3040",
            "amount": amount,
            "repayment_installments": 1,
            "repayment_period": 30,
            "anticipated_disbursement_date": anticipated_disbursement_date,
            "first_repayment_date": first_repayment_date
        } } }
        headers = {
            "accept": "application/json",
            "content-type": "application/json",
            "Authorization": f"Bearer {access_token}"
        }
        response = requests.post(url, json=payload, headers=headers)
        try:
            # save loan to db when response from kwara is successfull
            if response.status_code == 201:  # Loan successfully created in the external API
                loan_application = serializer.save(account_holder_id=account_holder)
                loan_application.status = LoanApplication.Status.Appraised
                loan_application.save()

                # print({"loan response": response.json()})
                response.raise_for_status()
                response_data = response.json()
                loan_state = response_data['data']['attributes']['state']
                masked_sacco_user_id = str(member_id)[0] + "x" * (len(str(member_id)) - 1)
                
                log_user_activity(user, "Mobile Loan Submitted", request.path)
                helper_send_sms(phone=phone, message=f"Dear {sender_name} - {masked_sacco_user_id}, you have successfully submitted a Mobile Loan application. It is {loan_state}.", department="Loans & Credit",)
                helper_send_sms(phone='254720861566', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a Mobile Loan application. It is {loan_state}. The member has no unsettled mobile loan and has been registered for more than 90 days", department="Loans & Credit",)
                helper_send_sms(phone='254721662453', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a Mobile Loan application. It is {loan_state}. The member has no unsettled mobile loan and has been registered for more than 90 days", department="Loans & Credit",)
                helper_send_sms(phone='254722281318', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a Mobile Loan application. It is {loan_state}. The member has no unsettled mobile loan and has been registered for more than 90 days", department="Loans & Credit",)
                helper_send_sms(phone='254727336746', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a Mobile Loan application. It is {loan_state}. The member has no unsettled mobile loan and has been registered for more than 90 days", department="Loans & Credit",)
                helper_send_sms(phone='254790094839', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a Mobile Loan application. It is {loan_state}. The member has no unsettled mobile loan and has been registered for more than 90 days", department="Business Development",)
                send_mail(
                    "Kenya Bankers Internet Banking M-Loan Application",
                    f"Kenya Bankers Internet Banking M-Loan Application",
                    settings.DEFAULT_FROM_EMAIL,
                    ["retail@kenyabankers.coop"],  # Make sure user has an email field
                    fail_silently=False,
                    html_message=f'<p>{sender_name} - {masked_sacco_user_id} has successfully submitted a Mobile Loan application. It is {loan_state}. The member has no unsettled mobile loan and has been registered for more than 90 days</p>'
                )
                return JsonResponse({"message": "Loan Application Successfull", "state": loan_state})
            else:
                return JsonResponse({"message": "Error in Loan Application", "state": "Not Applied"})
        except requests.RequestException as e:
            return JsonResponse({'error': str(e)})
    else:
        return JsonResponse({"error": "Loan product could not be saved"})

# @csrf_exempt
# def check_m_loan_eligibility(request, member_id):

#     token = request.headers.get("Authorization")
#     if not token:
#         return JsonResponse({"error": 'Permission denied'}, status=403)

#     auth_response = extract_user(token=token)

#     # Check if the token is invalid
#     if "error" in auth_response:
#         return JsonResponse({"error": auth_response["error"]}, status=401)
#     user_id = auth_response.get("user_id")
    
#     auth_user = CustomUser.objects.get(sacco_user_id=user_id)

#     if user_id != member_id and auth_user.role != 'Admin':
#         return JsonResponse({"error": 'permission denied'}, status=403)
    
#     if request.method == 'GET':
#         eligible = True
#         balances = helper_fetch_balances(sacco_member_id=member_id)

#         # Handle errors
#         if "error" in balances:
#             return JsonResponse({"error": balances["error"]}, status=500)

#         fosa_balance = balances.get("fosa_balance", 0)
#         share_capital_balance = helper_return_share_capital_balance(sacco_member_id=member_id)
#         # share_capital_balance = balances.get("share_capital_balance", 0)
#         main_savings_balance = balances.get("main_savings_balance", 0)

#         # if fosa_balance < 1000:
#         #     eligible = False
#         #     return JsonResponse({"eligible": eligible, "fosa_bal": fosa_balance, 'share_capital_balance': share_capital_balance,'main_savings_balance': main_savings_balance })
#         if not share_capital_balance:
#             eligible = False
#             return JsonResponse({"eligible": eligible, "fosa_bal": fosa_balance, 'share_capital_balance': share_capital_balance, 'main_savings_balance': main_savings_balance})
#         if not main_savings_balance:
#             eligible = False
#             return JsonResponse({"eligible": eligible, "fosa_bal": fosa_balance, 'share_capital_balance': share_capital_balance, 'main_savings_balance': main_savings_balance})
#         # user_loan_applications = LoanApplication.objects.filter(account_holder_id=member_id)

#         # for loan_application in user_loan_applications:

#         #         if loan_application.product_id == "3040":
#         #             # print(f"looan application with id {loan_application.id}")
#         #             eligible = False
#         #             # return JsonResponse({"eligibility": eligible})
#         #             return JsonResponse({"eligible": eligible, "fosa_bal": fosa_balance, 'share_capital_balance': share_capital_balance, 'main_savings_balance': main_savings_balance})

#         # check when the member was created
#         url = f'https://api.kwara.com/members/{member_id}'
#         headers = {
#             'Authorization': f'Bearer {access_token}',
#             'accept': 'application/json',
#         }
#         try:
#             response = requests.get(url, headers=headers)
#             response.raise_for_status()
#             data = response.json()

#             # Extract `created_at` and calculate days
#             created_at_str = data.get("data", {}).get("attributes", {}).get("created_at")
#             if created_at_str:
#                 created_at = parse_datetime(created_at_str)
#                 today = now()
#                 days_since_creation = (today - created_at).days
#                 if days_since_creation < 90:
#                     eligible = False
#                     return JsonResponse({"eligible": eligible, "fosa_bal": fosa_balance, 'share_capital_balance': share_capital_balance, 'main_savings_balance': main_savings_balance})

#                 # return JsonResponse({"eligible": True}, status=200)
#             else:
#                 return JsonResponse({"error": "Missing `created_at` field"}, status=400)
#         except requests.RequestException as e:
#             return JsonResponse({'error': str(e)}, status=500)
#         # check for existing loan application
#         finally:
#             # Call list_member_loans function directly
#             loan_request = list_member_loans_for_m_loan(request, member_id)
#             loan_response = loan_request.content.decode('utf-8')  # Decode JSON response
#             loan_data = json.loads(loan_response)  # Convert JSON string to dictionary

#             # Check if there's an existing loan with product_id "3040"
#             # has_mobile_loan = any(loan.get('product_name') == "Mobile Loan -" for loan in loan_data.get('loans', []))
#             has_mobile_loan = any(loan.get('product_name') in ["Mobile Loan -", "Mobile Loan"] for loan in loan_data.get('loans', []))

#             if has_mobile_loan:
#                 eligible = False

#             else:
#                 existing_loan = LoanApplication.objects.filter(account_holder_id=member_id, product_id="3040").first()
#                 if existing_loan:
#                     existing_loan.delete()
#             return JsonResponse({
#                 "eligible": eligible,
#                 "fosa_bal": fosa_balance,
#                 "share_capital_balance": share_capital_balance,
#                 "main_savings_balance": main_savings_balance
#             })

#     else:
#         return JsonResponse({'error': 'Invalid request method'}, status=405)

@csrf_exempt
def check_m_loan_eligibility(request, member_id):
    if request.method != 'GET':
        return JsonResponse({'error': 'Invalid request method'}, status=405)

    eligible = True
    existing_mobile_loan = False
    existing_mobile_loan_application = False
    before_90_days = False
    days_before_90_days = 0
    existing_loan = False

    balances = helper_fetch_balances(sacco_member_id=member_id)

    # Handle balance fetching errors
    if "error" in balances:
        return JsonResponse({"error": balances["error"]}, status=500)

    fosa_balance = balances.get("fosa_balance", 0)
    share_capital_balance = helper_return_share_capital_balance(sacco_member_id=member_id)
    main_savings_balance = balances.get("main_savings_balance", 0)

    # Check if share capital balance or main savings balance are missing
    if not share_capital_balance or not main_savings_balance:
        eligible = False

    if int(fosa_balance) < 1000:
        eligible = False
    
    # Check if there are existing loan applications today
    today_start = make_aware(datetime.combine(now().date(), datetime.min.time()))
    today_end = make_aware(datetime.combine(now().date(), datetime.max.time()))

    # print(f"start {today_start} ")
    # print(f"end {today_end} ")
    user_loan_applications = LoanApplication.objects.filter(
        account_holder_id=member_id, created_at__range=(today_start, today_end)
    )

    for loan_application in user_loan_applications:
        if loan_application.product_id == "3040":
            eligible = False
            existing_mobile_loan_application = True

    # Fetch existing mobile loans
    loan_request = list_member_loans_for_m_loan(member_id)
    loan_response = loan_request.content.decode('utf-8')
    loan_data = json.loads(loan_response)

    has_mobile_loan = any(
        loan.get('product_name') in ["Mobile Loan -", "Mobile Loan"]
        for loan in loan_data.get('loans', [])
    )
    has_any_loan = bool(loan_data.get('loans', []))

    if has_mobile_loan:
        eligible = False
        existing_mobile_loan = True
    if has_any_loan:
        eligible = False
        existing_loan = True

    # Fetch member details from Kwara API
    url = f'https://api.kwara.com/members/{member_id}'
    headers = {
        'Authorization': f'Bearer {access_token}',
        'accept': 'application/json',
    }

    try:
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        data = response.json()

        created_at_str = data.get("data", {}).get("attributes", {}).get("created_at")
        if created_at_str:
            created_at = parse_datetime(created_at_str)
            days_since_creation = (now() - created_at).days
            if days_since_creation < 90:
                eligible = False
                before_90_days = True
                days_before_90_days = 90 - days_since_creation
        else:
            return JsonResponse({"error": "Missing `created_at` field"}, status=400)

    except requests.RequestException as e:
        return JsonResponse({'error': str(e)}, status=500)

    # Final response after checking all conditions
    return JsonResponse({
        "eligible": eligible,
        "fosa_bal": fosa_balance,
        "share_capital_balance": share_capital_balance,
        "main_savings_balance": main_savings_balance,
        "existing_mobile_loan": existing_mobile_loan,
        "existing_mobile_loan_application": existing_mobile_loan_application,
        "before_90_days": before_90_days,
        "days_before_90_days":days_before_90_days,
        "existing_loan": existing_loan

    })

@csrf_exempt
def list_onboarded_members(request):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    onboarded_members = []
    users = CustomUser.objects.filter(is_superuser=False)

    for user in users:
        onboarded_members.append(
            {
            "sacco_user_id": user.sacco_user_id,
            "name": user.name,
            "email": user.email,
            "phone": user.phone,
            "member_type": user.notes,
            "member_role": user.role,
            "region": user.region,
            "business_location": user.business_location,
            "is_active": user.is_active,
            }
        )
    return JsonResponse({"data": onboarded_members})

@csrf_exempt
def list_accounts_created(request):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    accounts_created = []
    # savingsAccounts = SavingsApplication.objects.all().order_by('-created_at')
    # loanAccounts = LoanApplication.objects.all().order_by('-created_at')

    savings_accounts = [
        {
            "member_id": savings.account_holder_id.sacco_user_id,
            "name": savings.account_holder_id.name,
            "product_name": savings.product_name,
            "amount": savings.monthly_remittance_amount,
            "type": "savings",
            "created_at": savings.created_at
        } 
        for savings in SavingsApplication.objects.all().order_by('-created_at')
    ]
    
    # loan_accounts = [
    #     {
    #         "member_id": loans.account_holder_id.sacco_user_id,
    #         "name": loans.account_holder_id.name,
    #         "product": loans.product_id,
    #         "amount": loans.amount,
    #         "type": "loan",
    #     } 
    #     for loans in LoanApplication.objects.all().order_by('-created_at')
    # ]

    accounts_created = savings_accounts
    # Log user activity for Member Details
    log_user_activity(auth_user, "Viewed Savings Accounts Created", request.path)
    return JsonResponse({"data": accounts_created})

@csrf_exempt
def list_loan_accounts_created(request):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    accounts_created = []
    
    loan_accounts = [
        {
            "member_id": loans.account_holder_id.sacco_user_id,
            "name": loans.account_holder_id.name,
            "product": loans.product_id,
            "amount": loans.amount,
            "status":loans.status,
            "type": "loan",
            "created_at": loans.created_at,
        } 
        for loans in LoanApplication.objects.all().order_by('-created_at')
    ]

    accounts_created = loan_accounts
    # Log user activity for Member Details
    log_user_activity(auth_user, "Viewed Loan Accounts Created", request.path)

    return JsonResponse({"data": accounts_created})
    
@csrf_exempt
def show_pending_members(request):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    headers = {
        'Authorization': f'Bearer {access_token}',
        'accept': 'application/json',
    }

    try:
        # pending_members = []
        # member_ids = list(CustomUser.objects.values_list('sacco_user_id', flat=True))

        # Get date range from query parameters
        from_date = request.GET.get('from_date')
        to_date = request.GET.get('to_date')

        # Parse and filter by the date range
        if from_date and to_date:
            from_date = datetime.strptime(from_date, "%Y-%m-%d")
            to_date = datetime.strptime(to_date, "%Y-%m-%d")
            # print(f"From Date: {from_date}, To Date: {to_date}")
            member_ids = list(
                CustomUser.objects.filter(
                    created_at__range=(from_date, to_date)
                ).values_list('sacco_user_id', flat=True)
            )
        else:
            member_ids = list(CustomUser.objects.values_list('sacco_user_id', flat=True))

        pending_members = []
        # print(f"Filtered Member IDs: {member_ids}")

        # Loop through each member and fetch their details
        for member_id in member_ids:
            member_details_url = f'https://api.kwara.com/members/{member_id}'

            try:
                member_details_response = requests.get(member_details_url, headers=headers)
                member_details_response.raise_for_status()
                member_details = member_details_response.json()

                # Check if 'data' is a dictionary and contains 'attributes' and 'state'
                if isinstance(member_details['data'], dict):
                    attributes = member_details['data'].get('attributes', {})
                    if attributes.get('state') == 'PENDING_APPROVAL':
                        pending_members.append(member_details['data'])
                        # print(f"Member with ID {member_id} appended")
                else:
                    print(f"Unexpected data structure for member {member_id}")

            except requests.RequestException as e:
                # print(f"Error fetching details for member {member_id}")
                # Continue to the next member if there's an error
                continue

        return JsonResponse({'data': pending_members}, status=200)

    except requests.RequestException as e:
        # print(f"Error in main members request: {e}")
        return JsonResponse({'error': str(e)}, status=500)
        
@csrf_exempt
def show_active_members(request):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    headers = {
        'Authorization': f'Bearer {access_token}',
        'accept': 'application/json',
    }

    try:
        # activated_members = []
        # member_ids = list(CustomUser.objects.values_list('sacco_user_id', flat=True))

        # Get date range from query parameters
        from_date = request.GET.get('from_date')
        to_date = request.GET.get('to_date')

        # Parse and filter by the date range
        if from_date and to_date:
            from_date = datetime.strptime(from_date, "%Y-%m-%d")
            to_date = datetime.strptime(to_date, "%Y-%m-%d")
            # print(f"From Date: {from_date}, To Date: {to_date}")
            member_ids = list(
                CustomUser.objects.filter(
                    created_at__range=(from_date, to_date)
                ).values_list('sacco_user_id', flat=True)
            )
        else:
            member_ids = list(CustomUser.objects.values_list('sacco_user_id', flat=True))

        activated_members = []
        # print(f"Filtered Member IDs: {member_ids}")

        # Loop through each member and fetch their details
        for member_id in member_ids:
            member_details_url = f'https://api.kwara.com/members/{member_id}'

            try:
                member_details_response = requests.get(member_details_url, headers=headers)
                member_details_response.raise_for_status()
                member_details = member_details_response.json()

                # Check if 'data' is a dictionary and contains 'attributes' and 'state'
                if isinstance(member_details['data'], dict):
                    attributes = member_details['data'].get('attributes', {})
                    if attributes.get('state') == 'ACTIVE':
                        activated_members.append(member_details['data'])
                        # print(f"Member with ID {member_id} appended")
                else:
                    print(f"Unexpected data structure for member {member_id}")

            except requests.RequestException as e:
                # print(f"Error fetching details for member {member_id}: {e}")
                # Continue to the next member if there's an error
                continue

        return JsonResponse({'data': activated_members}, status=200)

    except requests.RequestException as e:
        # print(f"Error in main members request: {e}")
        return JsonResponse({'error': str(e)}, status=500)

@csrf_exempt
def show_all_members(request):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")

    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    if request.method == "GET":
        users = CustomUser.objects.filter(source=CustomUser.Source.Kwara).values(
            'sacco_user_id', 'name', 'email', 'phone', 'created_at', 'kwara_active'
        )
        # print(list(users))
        return JsonResponse({"users": list(users)})

# def show_all_members(request):

#     token = request.headers.get("Authorization")
#     if not token:
#         return JsonResponse({"error": 'Permission denied'}, status=403)

#     auth_response = extract_user(token=token)

#     # Check if the token is invalid
#     if "error" in auth_response:
#         return JsonResponse({"error": auth_response["error"]}, status=401)
#     user_id = auth_response.get("user_id")
    
#     auth_user = CustomUser.objects.get(sacco_user_id=user_id)

#     if user_id != auth_user.role != 'Admin':
#         return JsonResponse({"error": 'permission denied'}, status=403)
    
#     if request.method == "GET":
#         users = CustomUser.objects.values(
#             'sacco_user_id', 'name', 'email', 'phone', 'created_at', 'kwara_active'
#         )
#         # print(list(users))
#         return JsonResponse({"users": list(users)})
# ss   
@csrf_exempt
def show_all_internet_banking_members(request):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")

    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    if request.method == "GET":
        users = CustomUser.objects.filter(source=CustomUser.Source.InternetBanking).values(
            'sacco_user_id', 'name', 'email', 'phone', 'created_at', 'kwara_active'
        )
        # print(list(users))
        return JsonResponse({"users": list(users)}) 

def get_fosa_account_numbers():
    """
    Fetches FOSA account numbers for all members using a single token.
    Includes member ID and name for display purposes.
    """
    # Fetch all member IDs and their names
    members = CustomUser.objects.values('sacco_user_id', 'name', 'fosa_account')  # Adjust 'name' to your actual field for member names
    fosa_accounts = []

    # Loop through members and fetch FOSA account numbers
    for member in members:
        member_id = member['sacco_user_id']
        member_name = member['name']
        fosa_account = member['fosa_account']
        # url = f"https://api.kwara.com/members/{member_id}/savings"

        try:
            if fosa_account:
                fosa_accounts.append({
                    'member_id': member_id,
                    'name': member_name,
                    'fosa_account_number': fosa_account
                })
                # print(f"member_id {fosa_account}")
        except requests.exceptions.RequestException as e:
            continue
    return fosa_accounts

@csrf_exempt
def show_all_members_fosa_accounts(request):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    """
    Django view to return all members' FOSA account details.
    """
    try:
        fosa_accounts = get_fosa_account_numbers()
        return JsonResponse({'fosa_accounts': fosa_accounts}, status=200)
    except ValueError as e:
        return JsonResponse({'error': str(e)}, status=500)


# @csrf_exempt
# def show_saving_product(request, savings_id):
#     # access_token = get_access_token()

#     url = f"https://api.kwara.com/savings_products/{savings_id}"
#     headers = {
#         'Authorization': f'Bearer {access_token}',
#         "accept": "application/json",
#         'content-type': 'application/json',
#     }
#     response = requests.get(url, headers=headers)
#     return JsonResponse(response.json())


@csrf_exempt
def show_savings(request, savings_id):
    # access_token = get_access_token()

    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")

    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    

    if request.method == 'GET':

        url = f"https://api.kwara.com/savings/{savings_id}?include=transactions"

        headers = {
            "accept": "application/json",
            'Authorization' : f'Bearer {access_token}',
        }
        try:
            response = requests.get(url, headers=headers)
            response.raise_for_status()  # Raise an error for bad status codes
            return JsonResponse(response.json(), status=response.status_code)
        except requests.RequestException as e:
            return JsonResponse({'error': str(e)}, status=500)
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)


@csrf_exempt
def show_saving_transactions(request, savings_id):

    # access_token = get_access_token()
    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")

    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    url = f"https://api.kwara.com/savings/{savings_id}/transactions"

    headers = {
        "accept": "application/json",
        "Authorization": f"Bearer {access_token}"
    }

    try:
        response = requests.get(url, headers=headers)
        response.raise_for_status()  # Raise an error for bad status codes
        
        return JsonResponse(response.json(), status=response.status_code)
    except requests.RequestException as e:
        return JsonResponse({'error': str(e)}, status=500)


@csrf_exempt
def show_member_savings(request, member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    user = CustomUser.objects.get(sacco_user_id=member_id)

    if request.method == 'GET':
        try:
            statuses = ['ACTIVE', 'PENDING_APPROVAL', 'APPROVED', 'ACTIVE_IN_ARREARS', 'DORMANT']  # Adjust based on actual savings states
            all_savings = []

            for state in statuses:
                url = f"https://api.kwara.com/members/{member_id}/savings?filter[state]={state}"
                headers = {
                    "accept": "application/json",
                    "Authorization": f"Bearer {access_token}"
                }

                response = requests.get(url, headers=headers)
                response.raise_for_status()  # Raise an error for bad status codes

                data = response.json().get('data', [])  # Extract savings data from 'data' key
                all_savings.extend(data)  # Append to all_savings list

                # api_response = response.json()  # The full API response
                # api_savings = api_response.get('data', [])  # Get the loan data list from the 'data' key

                # Step 2: Fetch loans from the database for this member
                # db_savings = SavingsApplication.objects.filter(account_holder_id=member_id)

                # Step 3: Get a set of product_ids from the API response
                # active_product_ids = {savings['attributes']['product_id'] for savings in api_savings}

                # # Step 4: Identify and delete loans in the database that are not in the API response
                # for savings in db_savings:
                #     if savings.product_id not in active_product_ids:
                #         savings.delete()  # Delete loans not in the API response

                # Log user activity for viewing savings
            log_user_activity(user, "Viewed Savings", request.path)

            # Step 5: Return the active loans from the API
            # return JsonResponse({"data": all_savings}, status=response.status_code)
            return JsonResponse(all_savings, status=response.status_code)
            # return JsonResponse(response.json(), status=response.status_code)
        except requests.RequestException as e:
            return JsonResponse({'error': str(e)}, status=500)
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)

@csrf_exempt
def show_member_active_savings(request, member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    user = CustomUser.objects.get(sacco_user_id=member_id)

    if request.method == 'GET':
        try:
            url = f"https://api.kwara.com/members/{member_id}/savings?filter[state]=ACTIVE"
            headers = {
                "accept": "application/json",
                "Authorization": f"Bearer {access_token}"
            }

            response = requests.get(url, headers=headers)
            response.raise_for_status()  # Raise an error for bad status codes

            api_response = response.json()  # The full API response
            api_savings = api_response.get('data', [])  # Get the savings data list from the 'data' key

            # If the user's role is "User", filter out savings with product_id="1039"
            if user.role == "User":
                filtered_savings = [
                    savings for savings in api_savings
                    if savings['attributes']['product_id'] != "1039"
                    if savings['attributes']['product_id'] != "1001"
                    if savings['attributes']['product_id'] != "1002"
                    if savings['attributes']['product_id'] != "6011"
                ]
                # Replace the 'data' key in the response with the filtered savings
                api_response['data'] = filtered_savings

            # # Step 2: Fetch savings from the database for this member
            # db_savings = SavingsApplication.objects.filter(account_holder_id=member_id)

            # Step 3: Get a set of product_ids from the API response
            active_product_ids = {savings['attributes']['product_id'] for savings in api_savings}

            # # Step 4: Identify and delete savings in the database that are not in the API response
            # for savings in db_savings:
            #     if savings.product_id not in active_product_ids:
            #         savings.delete()  # Delete savings not in the API response

            # Log user activity for viewing savings
            log_user_activity(user, "Viewed Savings", request.path)

            # Step 5: Return the active savings from the API
            return JsonResponse(api_response, status=response.status_code)
            # return JsonResponse(response.json(), status=response.status_code)
        except requests.RequestException as e:
            return JsonResponse({'error': str(e)}, status=500)
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)

@csrf_exempt
def show_member_pending_approval_savings(request, member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    user = CustomUser.objects.get(sacco_user_id=member_id)

    if request.method == 'GET':
        try:
            url = f"https://api.kwara.com/members/{member_id}/savings?filter[state]=PENDING_APPROVAL"
            headers = {
                "accept": "application/json",
                "Authorization": f"Bearer {access_token}"
            }

            response = requests.get(url, headers=headers)
            response.raise_for_status()  # Raise an error for bad status codes

            api_response = response.json()  # The full API response
            api_savings = api_response.get('data', [])  # Get the loan data list from the 'data' key

            # If the user's role is "User", filter out savings with product_id="1039"
            if user.role == "User":
                filtered_savings = [
                    savings for savings in api_savings
                    if savings['attributes']['product_id'] != "1039"
                    if savings['attributes']['product_id'] != "1001"
                    if savings['attributes']['product_id'] != "1002"
                    if savings['attributes']['product_id'] != "6011"
                ]
                # Replace the 'data' key in the response with the filtered savings
                api_response['data'] = filtered_savings

            # # Step 2: Fetch loans from the database for this member
            # db_savings = SavingsApplication.objects.filter(account_holder_id=member_id)

            # Step 3: Get a set of product_ids from the API response
            active_product_ids = {savings['attributes']['product_id'] for savings in api_savings}

            # # Step 4: Identify and delete loans in the database that are not in the API response
            # for savings in db_savings:
            #     if savings.product_id not in active_product_ids:
            #         savings.delete()  # Delete loans not in the API response

            # # Log user activity for viewing savings
            # log_user_activity(user, "Viewed Savings", request.path)

            # Step 5: Return the active loans from the API
            return JsonResponse(api_response, status=response.status_code)
            # return JsonResponse(response.json(), status=response.status_code)
        except requests.RequestException as e:
            return JsonResponse({'error': str(e)}, status=500)
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)

@csrf_exempt
def show_member_dormant_savings(request, member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    user = CustomUser.objects.get(sacco_user_id=member_id)

    if request.method == 'GET':
        try:
            url = f"https://api.kwara.com/members/{member_id}/savings?filter[state]=DORMANT"
            headers = {
                "accept": "application/json",
                "Authorization": f"Bearer {access_token}"
            }

            response = requests.get(url, headers=headers)
            response.raise_for_status()  # Raise an error for bad status codes

            api_response = response.json()  # The full API response
            api_savings = api_response.get('data', [])  # Get the loan data list from the 'data' key

            # If the user's role is "User", filter out savings with product_id="1039"
            if user.role == "User":
                filtered_savings = [
                    savings for savings in api_savings
                    if savings['attributes']['product_id'] != "1039"
                    if savings['attributes']['product_id'] != "1001"
                    if savings['attributes']['product_id'] != "1002"
                ]
                # Replace the 'data' key in the response with the filtered savings
                api_response['data'] = filtered_savings

            # # Step 2: Fetch loans from the database for this member
            # db_savings = SavingsApplication.objects.filter(account_holder_id=member_id)

            # Step 3: Get a set of product_ids from the API response
            active_product_ids = {savings['attributes']['product_id'] for savings in api_savings}

            # # Step 4: Identify and delete loans in the database that are not in the API response
            # for savings in db_savings:
            #     if savings.product_id not in active_product_ids:
            #         savings.delete()  # Delete loans not in the API response

            # # Log user activity for viewing savings
            # log_user_activity(user, "Viewed Savings", request.path)

            # Step 5: Return the active loans from the API
            return JsonResponse(api_response, status=response.status_code)
            # return JsonResponse(response.json(), status=response.status_code)
        except requests.RequestException as e:
            return JsonResponse({'error': str(e)}, status=500)
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)

@csrf_exempt
def list_member_loans_for_dashboard(request, member_id):

    token = request.headers.get("Authorization")
    memberr_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")

    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != memberr_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    try:
        # List of URLs with different loan states
        states = [
            "ACTIVE",
            "APPROVED",
            "PARTIAL_APPLICATION",
            "PENDING_APPROVAL",
            "ACTIVE_IN_ARREARS",
        ]
        base_url = f"https://api.kwara.com/members/{member_id}/loans?filter[state]="

        headers = {
            "accept": "application/json",
            "Authorization": f"Bearer {access_token}"
        }

        all_loans = []

        # Fetch data from each URL
        for state in states:
            url = base_url + state
            response = requests.get(url, headers=headers)

            if response.status_code == 200:
                data = response.json()
                loans = data.get('data', [])

                # Extract loan details and add to the list
                for loan in loans:
                    all_loans.append({
                        'loan_id': loan.get('id'),
                        'product_name': loan.get('attributes', {}).get('product_name'),
                        'amount': loan.get('attributes', {}).get('amount'),
                        'total_paid': loan.get('attributes', {}).get('total_paid'),
                        'total_due': loan.get('attributes', {}).get('total_due'),
                        'total_balance': loan.get('attributes', {}).get('total_balance'),
                        'state': loan.get('attributes', {}).get('state'),
                        'next_repayment_due_date': loan.get('attributes', {}).get('next_repayment_due_date'),
                    })
            else:
                return JsonResponse(
                    {'error': f"Failed to fetch loans for state {state}", 'details': response.json()},
                    status=response.status_code
                )

        return JsonResponse({'loans': all_loans}, status=200)

    except requests.RequestException as e:
        return JsonResponse({'error': str(e)}, status=500)

@csrf_exempt
def account_statements(request, member_id):

    token = request.headers.get("Authorization")
    memberr_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != memberr_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    start_date = request.GET.get('start_date')
    end_date = request.GET.get('end_date')
    user = CustomUser.objects.get(sacco_user_id=member_id)

    if request.method == 'GET':
        try:
            url = f"https://api.kwara.com/members/{member_id}/savings?include=transactions"
            headers = {
                "accept": "application/json",
                "Authorization": f"Bearer {access_token}"
            }

            response = requests.get(url, headers=headers)
            response.raise_for_status()
            data = response.json().get('data', [])

            # Filter savings accounts by updated_at date
            filtered_accounts = [
                account for account in data
                if start_date <= account['attributes']['created_at'][:10] <= end_date
            ]

            if not filtered_accounts:
                return JsonResponse({"error": "No data found within the specified date range"}, status=404)

            # Create an Excel workbook
            wb = Workbook()
            for account in filtered_accounts:
                product_name = account['attributes']['product_name']
                ws = wb.create_sheet(title=product_name)

                # Add savings account information
                ws.append(["Savings Account Details"])
                ws.append(["Account Name:", account['attributes']['name']])
                ws.append(["Product Name:", account['attributes']['product_name']])
                ws.append(["Balance:", account['attributes']['balance']])
                ws.append(["Available Balance:", account['attributes']['available_balance']])
                ws.append(["Accrued Interest:", account['attributes']['accrued_interest']])
                ws.append(["State:", account['attributes']['state']])

                # Format the updated_at date
                updated_at = datetime.strptime(account['attributes']['updated_at'], "%Y-%m-%dT%H:%M:%S.%f%z")
                formatted_updated_at = updated_at.strftime("%Y-%m-%d    %I:%M %p")
                ws.append(["Updated At:", formatted_updated_at])
                ws.append([])  # Add an empty row before transaction data

                # Add headers for transactions
                headers = ["Transaction ID", "Type", "Amount", "Balance", "Payment Method", "Notes", "Date"]
                for col_num, header in enumerate(headers, 1):
                    ws.cell(row=10, column=col_num, value=header)  # Start transactions after savings account info

                # Fetch and add transaction data
                transactions = account['relationships']['transactions']['data']
                transaction_details = response.json().get('included', [])
                row_num = 11  # Start adding transaction data from row 11

                for transaction in transactions:
                    transaction_info = next(
                        (item for item in transaction_details if item['id'] == transaction['id']), None
                    )
                    if transaction_info:
                        attributes = transaction_info['attributes']
                        ws.cell(row=row_num, column=1, value=transaction['id'])
                        ws.cell(row=row_num, column=2, value=attributes['type'])
                        ws.cell(row=row_num, column=3, value=attributes['amount'])
                        ws.cell(row=row_num, column=4, value=attributes['balance'])
                        ws.cell(row=row_num, column=5, value=attributes['payment_method'])
                        ws.cell(row=row_num, column=6, value=attributes.get('notes', ''))

                        # Format the created_at date
                        created_at = datetime.strptime(attributes['created_at'], "%Y-%m-%dT%H:%M:%S.%f%z")
                        formatted_created_at = created_at.strftime("%Y-%m-%d    %I:%M %p")
                        ws.cell(row=row_num, column=7, value=formatted_created_at)
                        row_num += 1

                # Adjust column widths
                for col_num in range(1, len(headers) + 1):
                    ws.column_dimensions[get_column_letter(col_num)].width = 20

            # Remove the default sheet created by openpyxl
            if 'Sheet' in wb.sheetnames:
                wb.remove(wb['Sheet'])

            # Save the workbook to an in-memory buffer
            buffer = io.BytesIO()
            wb.save(buffer)
            buffer.seek(0)

            # Return the file as a downloadable response
            response = HttpResponse(
                buffer, content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
            )
            response['Content-Disposition'] = f'attachment; filename=Account_Statement_{start_date}_to_{end_date}.xlsx'
            # Log user activity for viewing savings
            log_user_activity(user, f"Account Statement Downloaded", request.path)
            return response
        
        except requests.RequestException as e:
            return JsonResponse({'error': str(e)}, status=500)
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)
    
@csrf_exempt
def list_member_savings(request, member_id):

    token = request.headers.get("Authorization")
    memberr_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != memberr_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    user = CustomUser.objects.get(sacco_user_id=member_id)

    try:
        url = f"https://api.kwara.com/members/{member_id}/savings"
        headers = {
            "accept": "application/json",
            "Authorization": f"Bearer {access_token}"
        }

        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            data = response.json()
            savings = data.get('data', [])

            # Filter out specific savings based on user's role
            if user.role == "User":
                savings = [
                    saving for saving in savings
                    if saving.get('attributes', {}).get('product_id') not in ["1039", "1002", "1001"]
                ]

            savings_details = [
                {
                    'savings_id' : saving.get('id'),
                    'savings_name': saving.get('attributes', {}).get('product_name')
                }
                for saving in savings
            ]
            return JsonResponse({'savings': savings_details}, status=200)
        else:
            return JsonResponse(response.json(), status=response.status_code)

    except requests.RequestException as e:
        return JsonResponse({'error': str(e)}, status=500)
    
@csrf_exempt
def saving_transactions_by_id(request, saving_id, member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    user = CustomUser.objects.get(sacco_user_id=member_id)
    url = f"https://api.kwara.com/savings/{saving_id}?include=transactions"
    headers = {
        "accept": "application/json",
        "Authorization": f"Bearer {access_token}"
    }

    response = requests.get(url=url, headers=headers)
    if response.status_code == 200:

        data = response.json()
        transactions = data.get("included")
        # Log user activity for viewing Savings
        log_user_activity(user, f"Account Statement Accessed", request.path)
        return JsonResponse(transactions, safe=False)

    else:
        return JsonResponse(response.json(), status=response.status_code)

@csrf_exempt
def savings_transactions_by_admin(request, saving_id, member_id):

    token = request.headers.get("Authorization")
    memberr_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != memberr_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    user = CustomUser.objects.get(sacco_user_id=member_id)
    AdminUser = CustomUser.objects.get(sacco_user_id=memberr_id)
    sender_name = user.business if user.notes == 'Corporate Member' else user.name
    url = f"https://api.kwara.com/savings/{saving_id}?include=transactions"
    headers = {
        "accept": "application/json",
        "Authorization": f"Bearer {access_token}"
    }

    response = requests.get(url=url, headers=headers)
    if response.status_code == 200:

        data = response.json()
        transactions = data.get("included")
        # Log user activity for viewing Savings
        log_user_activity(AdminUser, f"{sender_name} - {member_id} Account Statement Accessed", request.path)
        return JsonResponse(transactions, safe=False)

    else:
        return JsonResponse(response.json(), status=response.status_code)


@csrf_exempt
def loan_statements(request, member_id):

    token = request.headers.get("Authorization")
    memberr_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != memberr_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    start_date = request.GET.get('start_date')
    end_date = request.GET.get('end_date')

    user = CustomUser.objects.get(sacco_user_id=member_id)

    if request.method == 'GET':
        try:
            url = f"https://api.kwara.com/members/{member_id}/loans?filter[state]=ACTIVE&include=transactions"
            headers = {
                "accept": "application/json",
                "Authorization": f"Bearer {access_token}"
            }

            response = requests.get(url, headers=headers)
            response.raise_for_status()
            data = response.json().get('data', [])

            # Filter loan accounts by updated_at date
            filtered_accounts = [
                account for account in data
                if start_date <= account['attributes']['created_at'][:10] <= end_date
            ]

            if not filtered_accounts:
                return JsonResponse({"error": "No data found within the specified date range"}, status=404)

            # Create an Excel workbook
            wb = Workbook()
            for account in filtered_accounts:
                product_name = account['attributes']['product_name']
                ws = wb.create_sheet(title=product_name)

                # Add loan account information
                ws.append(["Loan Account Details"])
                # ws.append(["Account Name:", account['attributes']['name']])
                ws.append(["Product Name:", account['attributes']['product_name']])
                ws.append(["Amount:", account['attributes']['amount']])
                ws.append(["Total Due:", account['attributes']['total_due']])
                ws.append(["Total Paid:", account['attributes']['total_paid']])
                ws.append(["Total Balance:", account['attributes']['total_balance']])
                ws.append(["Accrued Interest:", account['attributes']['accrued_interest']])

                # Format the updated_at date
                next_repayment_due_date = datetime.strptime(account['attributes']['next_repayment_due_date'], "%Y-%m-%dT%H:%M:%S.%f%z")
                formatted_next_repayment_due_date = next_repayment_due_date.strftime("%Y-%m-%d    %I:%M %p")
                ws.append(["Next Repayment Due Date:", formatted_next_repayment_due_date])

                ws.append(["State:", account['attributes']['state']])
                ws.append(["Fosa Deposit Account:", account['attributes']['fosa_deposit_account']['product_name']])

                # Format the updated_at date
                updated_at = datetime.strptime(account['attributes']['updated_at'], "%Y-%m-%dT%H:%M:%S.%f%z")
                formatted_updated_at = updated_at.strftime("%Y-%m-%d    %I:%M %p")
                ws.append(["Updated At:", formatted_updated_at])

                ws.append([])  # Add an empty row before transaction data
                ws.append([])  # Add an empty row before transaction data

                # Add headers for transactions
                headers = ["Transaction ID", "Type", "Repayment Amount", "Loan Balance", "Payment Method", "Notes", "Date"]
                for col_num, header in enumerate(headers, 1):
                    ws.cell(row=13, column=col_num, value=header)  # Start transactions after loan account info

                # Fetch and add transaction data
                transactions = account['relationships']['transactions']['data']
                transaction_details = response.json().get('included', [])
                row_num = 14  # Start adding transaction data from row 11

                for transaction in transactions:
                    transaction_info = next(
                        (item for item in transaction_details if item['id'] == transaction['id']), None
                    )
                    if transaction_info:
                        attributes = transaction_info['attributes']
                        ws.cell(row=row_num, column=1, value=transaction['id'])
                        ws.cell(row=row_num, column=2, value=attributes['type'])
                        ws.cell(row=row_num, column=3, value=attributes['amount'])
                        ws.cell(row=row_num, column=4, value=attributes['balance'])
                        ws.cell(row=row_num, column=5, value=attributes['payment_method'])
                        ws.cell(row=row_num, column=6, value=attributes.get('notes', ''))

                        # Format the created_at date
                        created_at = datetime.strptime(attributes['created_at'], "%Y-%m-%dT%H:%M:%S.%f%z")
                        formatted_created_at = created_at.strftime("%Y-%m-%d    %I:%M %p")
                        ws.cell(row=row_num, column=7, value=formatted_created_at)

                        row_num += 1

                # Adjust column widths
                for col_num in range(1, len(headers) + 1):
                    ws.column_dimensions[get_column_letter(col_num)].width = 26

            # Remove the default sheet created by openpyxl
            if 'Sheet' in wb.sheetnames:
                wb.remove(wb['Sheet'])

            # Save the workbook to an in-memory buffer
            buffer = io.BytesIO()
            wb.save(buffer)
            buffer.seek(0)

            # Return the file as a downloadable response
            response = HttpResponse(
                buffer, content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
            )
            response['Content-Disposition'] = f'attachment; filename=Loan_Statement_{start_date}_to_{end_date}.xlsx'
            
            # Log user activity for viewing loans
            log_user_activity(user, f"Loan Statement Downloaded", request.path)
            return response

        except requests.RequestException as e:
            return JsonResponse({'error': str(e)}, status=500)
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)


# @csrf_exempt
# def list_member_loans(request, member_id):
#     try:
#         url = f"https://api.kwara.com/members/{member_id}/loans"
#         headers = {
#             "accept": "application/json",
#             "Authorization": f"Bearer {access_token}"
#         }

#         response = requests.get(url, headers=headers)
#         if response.status_code == 200:
#             data = response.json()
#             loans = data.get('data', [])
            
#             # Extract loan_id and product_name
#             loan_details = [
#                 {
#                     'loan_id': loan.get('id'),
#                     'product_name': loan.get('attributes', {}).get('product_name')
#                 }
#                 for loan in loans
#             ]
#             return JsonResponse({'loans': loan_details}, status=200)
#         else:
#             return JsonResponse(response.json(), status=response.status_code)

#     except requests.RequestException as e:
#         return JsonResponse({'error': str(e)}, status=500)
# ss

@csrf_exempt
def list_member_loans(request, member_id):

    token = request.headers.get("Authorization")
    memberr_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != memberr_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    try:
        # List of URLs with different loan states
        states = [
            "ACTIVE",
            "APPROVED",
            "PARTIAL_APPLICATION",
            "PENDING_APPROVAL",
            "ACTIVE_IN_ARREARS",
        ]
        base_url = f"https://api.kwara.com/members/{member_id}/loans?filter[state]="
        
        headers = {
            "accept": "application/json",
            "Authorization": f"Bearer {access_token}"
        }

        all_loans = []

        # Fetch data from each URL
        for state in states:
            url = base_url + state
            response = requests.get(url, headers=headers)

            if response.status_code == 200:
                data = response.json()
                loans = data.get('data', [])
                
                # Extract loan details and add to the list
                for loan in loans:
                    all_loans.append({
                        'loan_id': loan.get('id'),
                        'product_name': loan.get('attributes', {}).get('product_name')
                    })
            else:
                return JsonResponse(
                    {'error': f"Failed to fetch loans for state {state}", 'details': response.json()}, 
                    status=response.status_code
                )

        return JsonResponse({'loans': all_loans}, status=200)

    except requests.RequestException as e:
        return JsonResponse({'error': str(e)}, status=500)
    
def list_member_loans_for_m_loan(member_id):
    try:
        # List of URLs with different loan states
        states = [
            "ACTIVE",
            "APPROVED",
            "PARTIAL_APPLICATION",
            "PENDING_APPROVAL",
            "ACTIVE_IN_ARREARS",
        ]
        base_url = f"https://api.kwara.com/members/{member_id}/loans?filter[state]="
        
        headers = {
            "accept": "application/json",
            "Authorization": f"Bearer {access_token}"
        }

        all_loans = []

        # Fetch data from each URL
        for state in states:
            url = base_url + state
            response = requests.get(url, headers=headers)

            if response.status_code == 200:
                data = response.json()
                loans = data.get('data', [])
                
                # Extract loan details and add to the list
                for loan in loans:
                    all_loans.append({
                        'loan_id': loan.get('id'),
                        'product_name': loan.get('attributes', {}).get('product_name')
                    })
            else:
                return JsonResponse(
                    {'error': f"Failed to fetch loans for state {state}", 'details': response.json()}, 
                    status=response.status_code
                )

        return JsonResponse({'loans': all_loans}, status=200)

    except requests.RequestException as e:
        return JsonResponse({'error': str(e)}, status=500)  
    
@csrf_exempt
def loan_transactions_by_id(request, loan_id, member_id):

    token = request.headers.get("Authorization")
    memberr_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != memberr_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    user = CustomUser.objects.get(sacco_user_id=member_id)
    url = f"https://api.kwara.com/loans/{loan_id}/transactions"
    headers = {
        "accept": "application/json",
        "Authorization": f"Bearer {access_token}"
    }

    response = requests.get(url=url, headers=headers)
    # Log user activity for viewing loans
    log_user_activity(user, f"Loan Statement Accessed", request.path)
    return JsonResponse(response.json())

@csrf_exempt
def loan_transactions_by_admin(request, loan_id, member_id):

    token = request.headers.get("Authorization")
    memberr_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != memberr_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    user = CustomUser.objects.get(sacco_user_id=member_id)
    AdminUser = CustomUser.objects.get(sacco_user_id=memberr_id)
    sender_name = user.business if user.notes == 'Corporate Member' else user.name
    url = f"https://api.kwara.com/loans/{loan_id}/transactions"
    headers = {
        "accept": "application/json",
        "Authorization": f"Bearer {access_token}"
    }

    response = requests.get(url=url, headers=headers)
    # Log user activity for viewing loans
    log_user_activity(AdminUser, f"{sender_name} - {member_id} Loan Statement Accessed", request.path)
    return JsonResponse(response.json())

@csrf_exempt
def list_all_payment_requests(request):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")

    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if  auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    start_date = request.GET.get('start_date')
    end_date = request.GET.get('end_date')
    transaction_type = request.GET.get('type')  # 'deposit' or 'withdrawal'

    payments_to_paybill = [
        {
            'amount': payment.amount,
            'transaction_member': CustomUser.objects.get(phone=f"+{payment.phone_number}").name if CustomUser.objects.filter(phone=f"+{payment.phone_number}").exists() else payment.phone_number,
            'transaction_member_id': payment.member_sacco_id if payment.member_sacco_id else "",
            'phone_number': payment.phone_number,
            'account_reference': payment.account_reference,
            'date': payment.created_at.strftime('%Y-%m-%d'),
            'request_response': payment.response_description,
            'type': 'deposit',
            'callback_response': MpesaTransaction.objects.filter(checkout_request_id=payment.checkout_request_id).first().result_description if MpesaTransaction.objects.filter(checkout_request_id=payment.checkout_request_id).exists() else 'No response',
            'mpesa_reference': MpesaTransaction.objects.filter(checkout_request_id=payment.checkout_request_id).first().mpesa_receipt_number if MpesaTransaction.objects.filter(checkout_request_id=payment.checkout_request_id).exists() else 'No M-PESA Reference',
            'kwara_tracking_reference': '',
        }
        for payment in Payment.objects.all().order_by('-created_at')
    ]

    withdraw_requests = [
        {
            'member': CustomUser.objects.get(sacco_user_id=w_request.member_sacco_id).fosa_account or "FOSA",
            'transaction_member': CustomUser.objects.get(sacco_user_id=w_request.member_sacco_id).name,
            'transaction_member_id': w_request.member_sacco_id,
            'amount': w_request.amount,
            'account_reference': w_request.account_no if w_request.account_no else CustomUser.objects.get(sacco_user_id=w_request.member_sacco_id).phone,
            'date': w_request.request_time.strftime('%Y-%m-%d'),
            'request_response': w_request.request_response,
            'type': 'withdrawal',
            'callback_response': MpesaB2CCallback.objects.filter(originator_conversation_id=w_request.conversation_id).first().result_desc if MpesaB2CCallback.objects.filter(originator_conversation_id=w_request.conversation_id).exists() else 'No response',
            'mpesa_reference': MpesaB2CCallback.objects.filter(originator_conversation_id=w_request.conversation_id).first().transaction_id if MpesaB2CCallback.objects.filter(originator_conversation_id=w_request.conversation_id).exists() else 'No M-PESA Reference',
            'kwara_tracking_reference': w_request.conversation_id,
        }
        for w_request in WithdrawRequest.objects.filter(payment_method="mpesa").order_by('-request_time')
    ]

    all_transactions = payments_to_paybill + withdraw_requests

    # print(all_transactions)

    # Apply filters
    if start_date and end_date:
        start_date = datetime.strptime(start_date, "%Y-%m-%d")
        end_date = datetime.strptime(end_date, "%Y-%m-%d")
        all_transactions = [
            t for t in all_transactions if start_date <= datetime.strptime(t['date'], "%Y-%m-%d") <= end_date
        ]

    if transaction_type and transaction_type in ["deposit", "withdrawal"]:
        all_transactions = [t for t in all_transactions if t["type"] == transaction_type]

    return JsonResponse({"data": all_transactions}, safe=False)

@csrf_exempt
def list_all_internet_banking_transactions(request):
    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)

    user_id = auth_response.get("user_id")
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if auth_user.role != 'Admin':
        return JsonResponse({"error": 'Permission denied'}, status=403)

    try:
        start_date = request.GET.get('start_date')
        end_date = request.GET.get('end_date')

        transactions = [
            {
                'created': payment.created_at,
                'transaction_id': payment.transaction_id,
                'description': payment.description,
                'account_no': payment.account_no,
                'account_name': payment.account_name,
                'amount': payment.amount,
                'member_id': payment.user.sacco_user_id,
                'member_name': (
                    payment.user.chama_name if payment.user.notes == "Chama Member"
                    else payment.user.name if payment.user.notes in ["Corporate Member", "Individual Member"]
                    else ""
                ),
                'transaction_type': payment.transaction_type,
                'status': payment.status,
                'callback_response': '',
                'mpesa_reference': '',
                'type': '',

            }
            for payment in TransactionLog.objects.all()
        ]

        deposits = [
            {
                'created': deposit.created_at,
                'transaction_id': deposit.checkout_request_id,
                'description': f'Deposit from {deposit.phone_number}',
                'account_no': deposit.account_reference,
                'account_name': deposit.account_name,
                'amount': deposit.amount,
                'member_id': deposit.member_sacco_id if deposit.member_sacco_id else deposit.account_reference,
                'member_name': CustomUser.objects.get(sacco_user_id=deposit.member_sacco_id).name if deposit.member_sacco_id else  deposit.account_reference,
                'transaction_type': 'deposit',
                'status': "SUCCESSFUL" if MpesaTransaction.objects.filter(checkout_request_id=deposit.checkout_request_id).exists() else 'FAILED',
                'callback_response': MpesaTransaction.objects.filter(checkout_request_id=deposit.checkout_request_id).first().result_description if MpesaTransaction.objects.filter(checkout_request_id=deposit.checkout_request_id).exists() else '',
                'mpesa_reference': MpesaTransaction.objects.filter(checkout_request_id=deposit.checkout_request_id).first().mpesa_receipt_number if MpesaTransaction.objects.filter(checkout_request_id=deposit.checkout_request_id).exists() else '',
                'type': 'deposit',
            }
            for deposit in Payment.objects.all()
        ]

        withdrawals = [
            {
                'created': withdrawal.request_time,
                'transaction_id': withdrawal.conversation_id,
                'description': f"Withdrawal { ' to '+ withdrawal.account_no if withdrawal.account_no else ""}",
                'account_no': withdrawal.account_no,
                'account_name': withdrawal.account_no,
                'amount': withdrawal.amount,
                'member_id': withdrawal.member_sacco_id,
                'member_name': CustomUser.objects.get(sacco_user_id=withdrawal.member_sacco_id).name if withdrawal.member_sacco_id else  "",
                'transaction_type': 'withdrawal',
                'status': "SUCCESSFUL" if MpesaB2CCallback.objects.filter(originator_conversation_id=withdrawal.conversation_id).exists() else 'FAILED',
                'callback_response': MpesaB2CCallback.objects.filter(originator_conversation_id=withdrawal.conversation_id).first().result_desc if MpesaB2CCallback.objects.filter(originator_conversation_id=withdrawal.conversation_id).exists() else '',
                'mpesa_reference': MpesaB2CCallback.objects.filter(originator_conversation_id=withdrawal.conversation_id).first().transaction_id if MpesaB2CCallback.objects.filter(originator_conversation_id=withdrawal.conversation_id).exists() else '',
                'type': 'withdrawal',
            }
            for withdrawal in WithdrawRequest.objects.all()
        ]

        all_transactions = transactions + deposits + withdrawals

        # **Sort all transactions by 'created' (newest first)**
        all_transactions = sorted(all_transactions, key=lambda t: t['created'], reverse=True)

        # Apply date filtering if both start_date and end_date are provided
        if start_date and end_date:
            try:
                start_date = datetime.strptime(start_date, "%Y-%m-%d")
                end_date = datetime.strptime(end_date, "%Y-%m-%d")

                all_transactions = [
                    t for t in all_transactions if start_date <= t['created'].date() <= end_date
                ]
            except ValueError:
                return JsonResponse({"error": "Invalid date format. Use YYYY-MM-DD."}, status=400)

        return JsonResponse({"data": all_transactions}, safe=False)

    except Exception as e:
        return JsonResponse({"error": str(e)}, status=500)
    
@csrf_exempt
def withdrawals_above_100000(request):
    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)

    user_id = auth_response.get("user_id")
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if auth_user.role != 'Admin':
        return JsonResponse({"error": 'Permission denied'}, status=403)

    try:
        start_date = request.GET.get('start_date')
        end_date = request.GET.get('end_date')


        callback_exists = MpesaB2CCallback.objects.filter(
            originator_conversation_id=OuterRef('conversation_id')
            )
        withdraw_requests = WithdrawRequest.objects.annotate(
                has_callback=Exists(callback_exists)
            ).filter(
                has_callback=True,
                amount__gte=100000
            )
 
        withdrawals = [
            {
                'created': withdrawal.request_time,
                'transaction_id': withdrawal.conversation_id,
                'transaction_member': CustomUser.objects.get(sacco_user_id=withdrawal.member_sacco_id).name,
                'transaction_member_id': withdrawal.member_sacco_id,
                'description': f"Withdrawal { ' to '+ withdrawal.account_no if withdrawal.account_no else ""}",
                'account_no': withdrawal.account_no,
                'amount': withdrawal.amount,
                'member_id': withdrawal.member_sacco_id,
                'member_name': CustomUser.objects.get(sacco_user_id=withdrawal.member_sacco_id).name if withdrawal.member_sacco_id else  "",
                'transaction_type': 'withdrawal',
                'status': "SUCCESSFUL" if MpesaB2CCallback.objects.filter(originator_conversation_id=withdrawal.conversation_id).exists() else 'FAILED',
                'callback_response': MpesaB2CCallback.objects.filter(originator_conversation_id=withdrawal.conversation_id).first().result_desc if MpesaB2CCallback.objects.filter(originator_conversation_id=withdrawal.conversation_id).exists() else '',
                'mpesa_reference': MpesaB2CCallback.objects.filter(originator_conversation_id=withdrawal.conversation_id).first().transaction_id if MpesaB2CCallback.objects.filter(originator_conversation_id=withdrawal.conversation_id).exists() else '',
            }
            for withdrawal in withdraw_requests
        ]

    
        # withdrawals = [
        #     {
        #         'created': withdrawal.request_time,
        #         'transaction_id': withdrawal.conversation_id,
        #         'transaction_member': CustomUser.objects.get(sacco_user_id=withdrawal.member_sacco_id).name,
        #         'transaction_member_id': withdrawal.member_sacco_id,
        #         'description': f"Withdrawal { ' to '+ withdrawal.account_no if withdrawal.account_no else ""}",
        #         'account_no': withdrawal.account_no,
        #         'amount': withdrawal.amount,
        #         'member_id': withdrawal.member_sacco_id,
        #         'member_name': CustomUser.objects.get(sacco_user_id=withdrawal.member_sacco_id).name if withdrawal.member_sacco_id else  "",
        #         'transaction_type': 'withdrawal',
        #         'status': "SUCCESSFUL" if MpesaB2CCallback.objects.filter(originator_conversation_id=withdrawal.conversation_id).exists() else 'FAILED',
        #         'callback_response': MpesaB2CCallback.objects.filter(originator_conversation_id=withdrawal.conversation_id).first().result_desc if MpesaB2CCallback.objects.filter(originator_conversation_id=withdrawal.conversation_id).exists() else '',
        #         'mpesa_reference': MpesaB2CCallback.objects.filter(originator_conversation_id=withdrawal.conversation_id).first().transaction_id if MpesaB2CCallback.objects.filter(originator_conversation_id=withdrawal.conversation_id).exists() else '',
        #     }
        #     for withdrawal in WithdrawRequest.objects.filter(amount__gte=100000)
        # ]

        all_transactions = withdrawals
        # transactions + deposits + withdrawals

        # **Sort all transactions by 'created' (newest first)**
        all_transactions = sorted(all_transactions, key=lambda t: t['created'], reverse=True)

        # Apply date filtering if both start_date and end_date are provided
        if start_date and end_date:
            try:
                start_date = datetime.strptime(start_date, "%Y-%m-%d")
                end_date = datetime.strptime(end_date, "%Y-%m-%d")

                all_transactions = [
                    t for t in all_transactions if start_date <= t['created'].date() <= end_date
                ]
            except ValueError:
                return JsonResponse({"error": "Invalid date format. Use YYYY-MM-DD."}, status=400)

        return JsonResponse({"data": all_transactions}, safe=False)

    except Exception as e:
        return JsonResponse({"error": str(e)}, status=500)  

@csrf_exempt
def stats_for_supervisor_dashboard(request,sacco_user_id):
        
    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != sacco_user_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    # deposits = sum(deposit.amount for deposit in Payment.objects.all())
    valid_checkout_ids = MpesaTransaction.objects.values_list('checkout_request_id', flat=True)
    deposits = sum(deposit.amount for deposit in Payment.objects.filter(checkout_request_id__in=valid_checkout_ids))
    withdrawals = sum(withdrawal.amount for withdrawal in WithdrawRequest.objects.all())
    members_from_core_banking = CustomUser.objects.filter(source=CustomUser.Source.Kwara).count()
    members_from_internet_banking = CustomUser.objects.filter(source=CustomUser.Source.InternetBanking).count()
    loan_applications = LoanApplication.objects.all().count()
    loans_appraised = sum(loan.amount for loan in LoanApplication.objects.filter(status=LoanApplication.Status.Appraised))

    return JsonResponse({
        "total_deposits": deposits, 
        "total_withdrawals": withdrawals, 
        "members_from_core_banking": members_from_core_banking, 
        "members_from_internet_banking": members_from_internet_banking,
        "loan_applications": loan_applications,
        "loans_appraised": loans_appraised,
        })


@csrf_exempt
def show_member_loan_repayment(request, member_id):
    # access_token = get_access_token()

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    user = CustomUser.objects.get(sacco_user_id=member_id)

    try:
        url = f"https://api.kwara.com/members/{member_id}/loans?filter[state]=ACTIVE"
        headers = {
            "accept": "application/json",
            "Authorization": f"Bearer {access_token}"
        }

        response = requests.get(url, headers=headers)
        response.raise_for_status()  # Raise an error for bad status codes
        # Log user activity for viewing loan repayment
        log_user_activity(user, "Viewed Loan Repayment", request.path)
        return JsonResponse(response.json(), status=response.status_code)
    except requests.RequestException as e:
        return JsonResponse({'error': str(e)}, status=500)

# @csrf_exempt
# def show_member_closed_loan(request, member_id):
#     # access_token = get_access_token()

#     try:
#         url = f"https://api.kwara.com/members/{member_id}/loans?filter[state]=CLOSED"
#         headers = {
#             "accept": "application/json",
#             "Authorization": f"Bearer {access_token}"
#         }

#         response = requests.get(url, headers=headers)
#         response.raise_for_status()  # Raise an error for bad status codes
#         return JsonResponse(response.json(), status=response.status_code)
#     except requests.RequestException as e:
#         return JsonResponse({'error': str(e)}, status=500)

@csrf_exempt
def show_member_approved_loan(request, member_id):
    # access_token = get_access_token()
    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)


    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
            return JsonResponse({"error": 'permission denied'}, status=403)

    try:
        url = f"https://api.kwara.com/members/{member_id}/loans?filter[state]=APPROVED"
        headers = {
            "accept": "application/json",
            "Authorization": f"Bearer {access_token}"
        }

        response = requests.get(url, headers=headers)
        response.raise_for_status()  # Raise an error for bad status codes
        return JsonResponse(response.json(), status=response.status_code)
    except requests.RequestException as e:
        return JsonResponse({'error': str(e)}, status=500)

@csrf_exempt
def show_member_loan_pending_approval(request, member_id):
    # access_token = get_access_token()
    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)


    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
            return JsonResponse({"error": 'permission denied'}, status=403)

    try:
        url = f"https://api.kwara.com/members/{member_id}/loans?filter[state]=PENDING_APPROVAL"
        headers = {
            "accept": "application/json",
            "Authorization": f"Bearer {access_token}"
        }

        response = requests.get(url, headers=headers)
        response.raise_for_status()  # Raise an error for bad status codes
        return JsonResponse(response.json(), status=response.status_code)
    except requests.RequestException as e:
        return JsonResponse({'error': str(e)}, status=500)

@csrf_exempt
def show_member_loan_partial_application(request, member_id):
    # access_token = get_access_token()
    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)


    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    try:
        url = f"https://api.kwara.com/members/{member_id}/loans?filter[state]=PARTIAL_APPLICATION"
        headers = {
            "accept": "application/json",
            "Authorization": f"Bearer {access_token}"
        }

        response = requests.get(url, headers=headers)
        response.raise_for_status()  # Raise an error for bad status codes
        return JsonResponse(response.json(), status=response.status_code)
    except requests.RequestException as e:
        return JsonResponse({'error': str(e)}, status=500)
    
@csrf_exempt
def show_member_loans(request, member_id):
    # access_token = get_access_token()
    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    user = CustomUser.objects.get(sacco_user_id=member_id)

    try:
        url = f"https://api.kwara.com/members/{member_id}/loans?filter[state]=ACTIVE"
        headers = {
            "accept": "application/json",
            "Authorization": f"Bearer {access_token}"
        }

        response = requests.get(url, headers=headers)
        response.raise_for_status()

        # Log user activity for viewing loans
        log_user_activity(user, "Viewed Loans", request.path)
        return JsonResponse(response.json(), status=response.status_code)
    except requests.RequestException as e:
        return JsonResponse({'error': str(e)}, status=500)

@csrf_exempt
def show_memberr_loans(request, member_id):
    # access_token = get_access_token()
    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    user = CustomUser.objects.get(sacco_user_id=member_id)

    try:
        url = f"https://api.kwara.com/members/{member_id}/loans?filter[state]=ACTIVE"
        headers = {
            "accept": "application/json",
            "Authorization": f"Bearer {access_token}"
        }

        response = requests.get(url, headers=headers)
        response.raise_for_status()

        return JsonResponse(response.json(), status=response.status_code)
    except requests.RequestException as e:
        return JsonResponse({'error': str(e)}, status=500)

@csrf_exempt
def check_existing_loan_product(request, member_id, productName):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    try:
        statuses = ['APPROVED', 'PENDING_APPROVAL', 'PARTIAL_APPLICATION', 'ACTIVE', 'ACTIVE_IN_ARREARS']
        loans = []
        for state in statuses:
            url = f"https://api.kwara.com/members/{member_id}/loans?filter[state]={state}"
            headers = {
                "accept": "application/json",
                "Authorization": f"Bearer {access_token}"
            }
            response = requests.get(url, headers=headers)
            response.raise_for_status()
            data = response.json().get("data", [])

            # # ✅ Check if there are any ACTIVE_IN_ARREARS loans
            # if state == "ACTIVE_IN_ARREARS" and data:
            #     return JsonResponse({"exist": True}, status=200)
            
            loans.extend(data)

        # Check if the product_name exists in the aggregated loan data
        for loan in loans:
            if loan.get("attributes", {}).get("product_name") == productName:
                return JsonResponse({"exists": True}, status=200)
        
        return JsonResponse({"exists": False}, status=200)
    except requests.RequestException as e:
        return JsonResponse({'error': str(e)}, status=500)

  
@csrf_exempt
def show_guarantor_requests(request,member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    member = CustomUser.objects.get(sacco_user_id=member_id)
    loans_pending_my_guarantee = []
    all_loans= Guarantor.objects.filter(guarantor_member_id=member.sacco_user_id).order_by('-created_at')
    for loan in all_loans:
        loans_pending_my_guarantee.append({
           "id": loan.id,
           "approved": loan.approved,
           "amount": loan.loan_application.amount,
           "rejected": loan.rejected,
           "product_id": loan.loan_application.product_id,
           "loan_owner": loan.loan_application.account_holder_id.sacco_user_id,
           "loan_owner_name": loan.loan_application.account_holder_id.name,
           "loan_owner_id": loan.loan_application.account_holder_id.sacco_user_id,
           "loan_owner_business": loan.loan_application.account_holder_id.business,
           "member_type": loan.loan_application.account_holder_id.notes,
           "loan_owner_phone": loan.loan_application.account_holder_id.phone,
           "created_at": loan.created_at,
           "updated_at": loan.updated_at,
        })
    return JsonResponse({"data":loans_pending_my_guarantee})

@csrf_exempt
def show_my_loan_guarantor_requests(request,member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    # member = CustomUser.objects.get(sacco_user_id=member_id)
    my_loan_guarantors = []
    all_guarantors = Guarantor.objects.all().order_by('-created_at')
    # loan_application.account_holder_id.sacco_user_id=member_id
    for guarantor in all_guarantors:
        # print(f"guarantor id {guarantor.id}")
        if (guarantor.loan_application.account_holder_id.sacco_user_id == member_id):
            my_loan_guarantors.append({
                'guarantor_id': guarantor.id,
                "rejected": guarantor.rejected,
                "product_id" : guarantor.loan_application.product_id,
                "amount" : guarantor.loan_application.amount,
                "approved": guarantor.approved,
                "guarantor_id": guarantor.guarantor_member_id,
                "guarantor_member_id": guarantor.guarantor_member_id,
                "guarantor_name": guarantor.guarantor_name,
                "guarantor_phone": guarantor.guarantor_phone,
                "created_at": guarantor.created_at,
                "updated_at": guarantor.updated_at,
            })

    return JsonResponse({"data": my_loan_guarantors})

@csrf_exempt
def change_guarantee_status(request, guarantee_id):
    try:
        data = json.loads(request.body)
        user_id = data.get('saccoMemberId')
        user = CustomUser.objects.get(sacco_user_id=user_id)
        product_name = data.get('productName')

        token = request.headers.get("Authorization")
        if not token:
            return JsonResponse({"error": 'Permission denied'}, status=403)

        auth_response = extract_user(token=token)

        # Check if the token is invalid
        if "error" in auth_response:
            return JsonResponse({"error": auth_response["error"]}, status=401)
        userr_id = auth_response.get("user_id")
        
        auth_user = CustomUser.objects.get(sacco_user_id=userr_id)

        if userr_id != user_id and auth_user.role != 'Admin':
            return JsonResponse({"error": 'permission denied'}, status=403)

        # Ensure both saccoMemberId and guarantee_id are valid
        if not user_id or not guarantee_id:
            # print("Invalid member or guarantee ID")
            return JsonResponse({'error': 'Invalid member or guarantee ID'}, status=400)

        try:
            member = Guarantor.objects.get(id=guarantee_id)
            loan_application = member.loan_application
            account_holder = loan_application.account_holder_id
            # name = account_holder.name
            sender_name = account_holder.business if account_holder.notes == 'Corporate Member' else account_holder.name
            phone = account_holder.phone
        except CustomUser.DoesNotExist:
            # print("Member not found")
            return JsonResponse({'error': 'Member not found'}, status=404)

        guarantee = Guarantor.objects.get(id=guarantee_id)
        guarantee.approved = True
        guarantee.save()

        number = phone.lstrip("+")
        helper_send_sms(phone=number, message=f"{guarantee.guarantor_name} has accepted to guarantee your {product_name}.", department="Loans & Credit")
        helper_send_sms(phone='254720861566', message=f"{guarantee.guarantor_name} has accepted to guarantee {product_name} for {sender_name}.", department="Loans & Credit")
        helper_send_sms(phone='254721662453', message=f"{guarantee.guarantor_name} has accepted to guarantee {product_name} for {sender_name}.", department="Loans & Credit")
        helper_send_sms(phone='254722281318', message=f"{guarantee.guarantor_name} has accepted to guarantee {product_name} for {sender_name}.", department="Loans & Credit")
        helper_send_sms(phone='254727336746', message=f"{guarantee.guarantor_name} has accepted to guarantee {product_name} for {sender_name}.", department="Loans & Credit")
        helper_send_sms(phone='254790094839', message=f"{guarantee.guarantor_name} has accepted to guarantee {product_name} for {sender_name}.", department="Business Development")
        send_mail(
            "Kenya Bankers Internet Banking Loan Guarantee",
            f"Kenya Bankers Internet Banking Loan Guarantee",
            settings.DEFAULT_FROM_EMAIL,
            ["retail@kenyabankers.coop"],  # Make sure user has an email field
            fail_silently=False,
            html_message=f'<p>{guarantee.guarantor_name} has accepted to guarantee {product_name} for {sender_name}.</p>'
        )
        log_user_activity(user, f"Approved Guarantor for {sender_name} on {product_name}", request.path)
        return JsonResponse({'success': 'guarantee approved successfully'})
    except Guarantor.DoesNotExist:
        return JsonResponse({'error': 'Guarantor not found'}, status=404)
    except Exception as e:
        return JsonResponse({'error': f'An error occurred: {str(e)}'}, status=500)

@csrf_exempt
def reject_guarantee_status(request, guarantee_id):
    try:
        data = json.loads(request.body)
        user_id = data.get('saccoMemberId')
        user = CustomUser.objects.get(sacco_user_id=user_id)
        product_name = data.get('productName')
        rejectionComment = data.get('rejectionComment')

        token = request.headers.get("Authorization")
        if not token:
            return JsonResponse({"error": 'Permission denied'}, status=403)

        auth_response = extract_user(token=token)

        # Check if the token is invalid
        if "error" in auth_response:
            return JsonResponse({"error": auth_response["error"]}, status=401)
        userr_id = auth_response.get("user_id")
        
        auth_user = CustomUser.objects.get(sacco_user_id=userr_id)

        if userr_id != user_id and auth_user.role != 'Admin':
            return JsonResponse({"error": 'permission denied'}, status=403)

        # Ensure both saccoMemberId and guarantee_id are valid
        if not user_id or not guarantee_id:
            # print("Invalid member or guarantee ID")
            return JsonResponse({'error': 'Invalid member or guarantee ID'}, status=400)

        try:
            member = Guarantor.objects.get(id=guarantee_id)
            loan_application = member.loan_application
            account_holder = loan_application.account_holder_id
            # name = account_holder.name
            sender_name = account_holder.business if account_holder.notes == 'Corporate Member' else account_holder.name
            phone = account_holder.phone
        except CustomUser.DoesNotExist:
            # print("Member not found")
            return JsonResponse({'error': 'Member not found'}, status=404)

        guarantee = Guarantor.objects.get(id=guarantee_id)
        guarantee.rejection_comment = rejectionComment
        guarantee.rejected = True
        guarantee.save()

        number = phone.lstrip("+")
        helper_send_sms(phone=number, message=f"{guarantee.guarantor_name} has rejected to guarantee your {product_name}.", department="Loans & Credit")
        helper_send_sms(phone='254720861566', message=f"{guarantee.guarantor_name} has rejected to guarantee {product_name} for {sender_name}.", department="Loans & Credit")
        helper_send_sms(phone='254721662453', message=f"{guarantee.guarantor_name} has rejected to guarantee {product_name} for {sender_name}.", department="Loans & Credit")
        helper_send_sms(phone='254722281318', message=f"{guarantee.guarantor_name} has rejected to guarantee {product_name} for {sender_name}.", department="Loans & Credit")
        helper_send_sms(phone='254727336746', message=f"{guarantee.guarantor_name} has rejected to guarantee {product_name} for {sender_name}.", department="Loans & Credit")
        helper_send_sms(phone='254790094839', message=f"{guarantee.guarantor_name} has rejected to guarantee {product_name} for {sender_name}.", department="Business Development")
        send_mail(
            "Kenya Bankers Internet Banking Loan Guarantee",
            f"Kenya Bankers Internet Banking Loan Guarantee",
            settings.DEFAULT_FROM_EMAIL,
            ["retail@kenyabankers.coop"],  # Make sure user has an email field
            fail_silently=False,
            html_message=f'<p>{guarantee.guarantor_name} has rejected to guarantee {product_name} for {sender_name}.</p>'
        )
        log_user_activity(user, f"Rejected Guarantor for {sender_name} on {product_name}", request.path)
        return JsonResponse({'success': 'guarantee approved successfully'})
    except Guarantor.DoesNotExist:
        return JsonResponse({'error': 'Guarantor not found'}, status=404)
    except Exception as e:
        return JsonResponse({'error': f'An error occurred: {str(e)}'}, status=500)
    
@csrf_exempt
def list_loan_details_to_update_securities(request, sacco_member_id, loan_id):

    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    try:
        requesting_user = CustomUser.objects.get(sacco_user_id=sacco_member_id)
    except CustomUser.DoesNotExist:
        return JsonResponse({"error": f"User with sacco_user_id {sacco_member_id} not found"}, status=404)

    isAdmin = requesting_user.role == "Admin"

    if request.method == 'GET':
        data = []
        loan = LoanApplication.objects.filter(pk=loan_id).first()
        loan_data = {
                "id": loan.id,
                "account_holder_id": loan.account_holder_id.sacco_user_id,
                "amount": loan.amount,
                "status": loan.status,
                "product_id": loan.product_id,
                "repayment_installments": loan.repayment_installments,
                "repayment_period": loan.repayment_period,
                "repayment_period_unit": loan.repayment_period_unit,
                "anticipated_disbursement_date": loan.anticipated_disbursement_date,
                "first_repayment_date": loan.first_repayment_date,
                "disbursement_mode": loan.disbursement_mode,
                "repayment_mode": loan.repayment_mode,
                "processing_fee": loan.processing_fee,
                "processing_fee_reference": loan.processing_fee_reference,
                "created_at": loan.created_at,
                "user": {
                    "idNumber": loan.idNumber,
                    "name": loan.account_holder_id.name,
                    "email": loan.email,
                    "gender": loan.gender,
                    "phone": loan.phone,
                    "date_of_birth": loan.dateOfBirth,
                    "kra_pin": loan.kra_pin,
                    "marital_status": loan.marital_status,
                    "physical_address": loan.physical_address,
                    "postal_address": loan.postal_address,
                },
                "guarantors": list(loan.guarantors.values(
                    "guarantor_member_id", "guarantor_type", "guarantor_name", "guarantor_phone", "approved", "confirming_id"
                )),
                "securities": list(loan.securities.values(
                    "security_type", "description", "value", "reference_number"
                )),
            }
        data.append(loan_data)

        return JsonResponse(data, safe=False)
    else:
        return JsonResponse({"error": "Invalid request method"}, status=405)
    
@csrf_exempt
def update_loan_securities(request, sacco_member_id, loan_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != sacco_member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    user = CustomUser.objects.get(sacco_user_id=sacco_member_id)
    sender_name = user.business if user.notes == 'Corporate Member' else user.name
    s_phone = user.phone
    sender_phone = s_phone.lstrip('+')
    # Attempt to parse JSON data from 'json_data' field within request.POST for form data
    try:
        data = json.loads(request.POST.get('json_data', '{}'))
        product_name = data.get('product_name', 'Unknown Product')  # Get product_name
    except json.JSONDecodeError:
        return JsonResponse({'error': 'Invalid JSON data'}, status=status.HTTP_400_BAD_REQUEST)

    loan_application = LoanApplication.objects.get(pk=loan_id)
    new_guarantors_ids = []

    if loan_application:

        # delete all securities and guarantors
        Security.objects.filter(loan_application=loan_application).delete()
        # Guarantor.objects.filter(loan_application=loan_application).delete()
        
        try:
            guarantors = data.get('guarantors', [])
            for guarantor in guarantors:
                new_guarantors_ids.append(guarantor['member_id'])
                if all(k in guarantor for k in ('type', 'name', 'member_id', 'phone')):
                    existing_guarantor = Guarantor.objects.filter(
                        guarantor_member_id=guarantor['member_id'],
                        approved=False,
                        rejected=False
                    ).first()

                    already_guarantor_for_this_loan = Guarantor.objects.filter(guarantor_member_id=guarantor['member_id'],loan_application=loan_application).exists()

                    if not already_guarantor_for_this_loan:
                        Guarantor.objects.create(
                            product_name=product_name,
                            sender_name=sender_name,
                            loan_application=loan_application,
                            guarantor_type=guarantor['type'],
                            guarantor_name=guarantor['name'],
                            guarantor_member_id=guarantor['member_id'],
                            guarantor_phone=guarantor['phone'],
                        )
                    # print(guarantor.id)
                    if not existing_guarantor:
                        # If there's no pending status for this member, send SMS immediately
                        # pass
                        helper_send_guarantor_sms(
                            phone=guarantor['phone'],
                            message=f"{sender_name} has selected you as a loan guarantor.\nReply with:\n1. To approve \n2. To reject"
                        )
                        helper_send_sms(phone='254720861566', message=f"{guarantor['name']} has been selected to guarantee {product_name} for {sender_name}.", department="Loans & Credit")
                        helper_send_sms(phone='254721662453', message=f"{guarantor['name']} has been selected to guarantee {product_name} for {sender_name}.", department="Loans & Credit")
                        helper_send_sms(phone='254722281318', message=f"{guarantor['name']} has been selected to guarantee {product_name} for {sender_name}.", department="Loans & Credit")
                        helper_send_sms(phone='254727336746', message=f"{guarantor['name']} has been selected to guarantee {product_name} for {sender_name}.", department="Loans & Credit")
                        helper_send_sms(phone='254790094839', message=f"{guarantor['name']} has been selected to guarantee {product_name} for {sender_name}.", department="Business Development")
                        send_mail(
                            "Kenya Bankers Internet Banking Loan Guarantee",
                            f"Kenya Bankers Internet Banking Loan Guarantee",
                            settings.DEFAULT_FROM_EMAIL,
                            ["retail@kenyabankers.coop"],  # Make sure user has an email field
                            fail_silently=False,
                            html_message=f'<p>{guarantor['name']} has been selected to guarantee {product_name} for {sender_name}.</p>'
                        )
                    else:
                        # pass
                        helper_send_sms(phone=guarantor['phone'], message=f"You have received a new guarantor request from {sender_name}. \nLog into KBS Internet Banking to approve or reject pending requests.", department="Loans & Credit")
                else:
                    return JsonResponse({'error': 'Invalid guarantor data. All fields are required.'}, status=status.HTTP_400_BAD_REQUEST)

            Guarantor.objects.filter(loan_application=loan_application).exclude(guarantor_member_id__in=new_guarantors_ids).delete()

            # Save securities
            security_types = {
                'titleDeed': 'Title Deed',
                'cashCollateral': 'Cash Collateral',
                'nseShares': 'NSE Shares',
                'otherSecurity': 'Other'
            }

            for key, display_name in security_types.items():
                security_data = data.get(key)
                if security_data:
                    reference_number = security_data.get('reference_number') if display_name in ['Title Deed', 'NSE Shares'] else None
                    description = security_data.get('description')
                    value = security_data.get('value')
                    if description and value:  # Check if both fields are present
                        Security.objects.create(
                            loan_application=loan_application,
                            security_type=display_name,
                            reference_number=reference_number,
                            description=description,
                            value=value
                        )
                    else:
                        return JsonResponse({'error': f'Invalid data for security type: {display_name}. Both description and value are required.'}, status=status.HTTP_400_BAD_REQUEST)

            # Handle document uploads
            document_data = {
                doc: request.FILES.get(doc) 
                for doc in ['payslip', 'bank_statements', 'mpesa_statements', 'utility_bill', 'cash_flow_analysis']
            }
            if any(document_data.values()):  # Check if any documents were uploaded
                LoanOriginationDocuments.objects.create(
                    loan_application=loan_application,
                    **document_data
                )

            # Update status and rejection comment
            loan_application.status = LoanApplication.Status.PendingAppraisal
            loan_application.rejection_comment = "Loan Securities Updated"
            loan_application.save()

            masked_sacco_user_id = str(sacco_member_id)[0] + "x" * (len(str(sacco_member_id)) - 1)
            # Log user activity for viewing loans
            log_user_activity(user, f"{product_name} securities updated", request.path)
            helper_send_sms(phone=s_phone, message=f"Dear {sender_name} - {masked_sacco_user_id}, you have successfully updated loan securities for your {product_name} loan application.", department="Loans & Credit")
            helper_send_sms(phone='254720861566', message=f"{sender_name} - {masked_sacco_user_id} has successfully updated loan securities for {product_name} loan application.", department="Loans & Credit")
            helper_send_sms(phone='254721662453', message=f"{sender_name} - {masked_sacco_user_id} has successfully updated loan securities for {product_name} loan application.", department="Loans & Credit")
            helper_send_sms(phone='254722281318', message=f"{sender_name} - {masked_sacco_user_id} has successfully updated loan securities for {product_name} loan application.", department="Loans & Credit")
            helper_send_sms(phone='254727336746', message=f"{sender_name} - {masked_sacco_user_id} has successfully updated loan securities for {product_name} loan application.", department="Loans & Credit")
            helper_send_sms(phone='254790094839', message=f"{sender_name} - {masked_sacco_user_id} has successfully updated loan securities for {product_name} loan application.", department="Business Development")
            send_mail(
                "Kenya Bankers Internet Banking Loan Securities Update",
                f"Kenya Bankers Internet Banking Loan Securities Update",
                settings.DEFAULT_FROM_EMAIL,
                ["retail@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{sender_name} - {masked_sacco_user_id} has successfully updated loan securities for {product_name}, loan application.</p>'
            )
            return JsonResponse({"success": 'Loan securities updated successfully'}, status=200)
        except Exception as e:
            print(f"Error during loan submission {e}")
            return JsonResponse({'error': f'Error during submition: {str(e)}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    else:
        return JsonResponse("Error updating securities", status=status.HTTP_400_BAD_REQUEST)

@csrf_exempt
def show_member_arrears_loans(request, member_id):
    # access_token = get_access_token()
    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    try:
        url = f"https://api.kwara.com/members/{member_id}/loans?filter[state]=ACTIVE_IN_ARREARS"
        headers = {
            "accept": "application/json",
            "Authorization": f"Bearer {access_token}"
        }

        response = requests.get(url, headers=headers)
        response.raise_for_status()  # Raise an error for bad status codes
        return JsonResponse(response.json(), status=response.status_code)
    except requests.RequestException as e:
        return JsonResponse({'error': str(e)}, status=500)


@api_view(['POST'])
@csrf_exempt
def create_savings_application(request, member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    serializer = SavingsApplicationSerializer(data=request.data)
    # access_token = get_access_token()
    user = CustomUser.objects.get(sacco_user_id=member_id)
    phone = user.phone
    sender_name = user.business if user.notes == 'Corporate Member' else user.name

    if serializer.is_valid():

        # Get the account holder based on the member_id
        account_holder = get_object_or_404(CustomUser, sacco_user_id=member_id)

        # Check if the savings account already exists for the member with the same product_id
        if SavingsApplication.objects.filter(account_holder_id=account_holder, product_id=request.data['product_id'], created_at__date=now().date()).exists():
            return Response({'error': 'Savings account already exists for this product.'}, status=status.HTTP_400_BAD_REQUEST)

        # savings_application = serializer.save()

        # Send the savings application to the external API
        url = f"https://api.kwara.com/members/{member_id}/savings"
        payload = {
            "data": {
                "attributes": {
                    "account_holder_id": request.data['account_holder_id'],
                    "product_id": request.data['product_id'],
                    "name": request.data['product_name'],
                    "monthly_remittance_amount": request.data['monthly_remittance_amount']
                }
            }
        }
        headers = {
            "accept": "application/json",
            "Authorization": f"Bearer {access_token}"
        }
        try:
            response = requests.post(url, json=payload, headers=headers)
            # response.raise_for_status()
            if response.status_code == 201:
                # Save the savings application data
                saving = serializer.save(account_holder_id=account_holder)

                masked_sacco_user_id = str(member_id)[0] + "x" * (len(str(member_id)) - 1)

                # Log user activity for creating savings
                log_user_activity(user, f"Submitted - {saving.product_name}", request.path)
                helper_send_sms(phone=phone, message=f"Dear {sender_name} - {masked_sacco_user_id}, you have successfully submitted a {saving.product_name}. It is pending approval.", department="Customer Service")
                helper_send_sms(phone='254722391827', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a {saving.product_name}. It is pending approval. Do your KYC and approve", department="Customer Service")
                helper_send_sms(phone='254700531408', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a {saving.product_name}. It is pending approval. Do your KYC and approve", department="Customer Service")
                send_mail(
                    "Kenya Bankers Internet Banking Savings Application",
                    f"Kenya Bankers Internet Banking Savings Application",
                    settings.DEFAULT_FROM_EMAIL,
                    ["closure@kenyabankers.coop"],  # Make sure user has an email field
                    fail_silently=False,
                    html_message=f'<p>{sender_name} - {masked_sacco_user_id} has successfully submitted a {saving.product_name}. It is pending approval. Do your KYC and approve</p>'
                )
                send_mail(
                    "Kenya Bankers Internet Banking Savings Application",
                    f"Kenya Bankers Internet Banking Savings Application",
                    settings.DEFAULT_FROM_EMAIL,
                    ["help@kenyabankers.coop"],  # Make sure user has an email field
                    fail_silently=False,
                    html_message=f'<p>{sender_name} - {masked_sacco_user_id} has successfully submitted a {saving.product_name}. It is pending approval. Do your KYC and approve</p>'
                )
                return Response(response.json(), status=response.status_code)
            else:
                return JsonResponse(response.json(), status=response.status_code)

        except requests.RequestException as e:
            return Response({'error': str(e)}, status=response.status_code)
    else:
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@api_view(['POST'])
@csrf_exempt
def create_barizi_savings(request, member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    serializer = SavingsApplicationSerializer(data=request.data)
    # access_token = get_access_token()
    user = CustomUser.objects.get(sacco_user_id=member_id)
    phone = user.phone
    sender_name = user.business if user.notes == 'Corporate Member' else user.name

    if serializer.is_valid():

        # Get the account holder based on the member_id
        account_holder = get_object_or_404(CustomUser, sacco_user_id=member_id)

        # Check if the savings account already exists for the member with the same product_id
        if SavingsApplication.objects.filter(account_holder_id=account_holder, product_id=request.data['product_id'], created_at__date=now().date()).exists():
            return Response({'error': 'Savings account already exists for this product.'}, status=status.HTTP_400_BAD_REQUEST)

        # Send the savings application to the external API
        url = f"https://api.kwara.com/members/{member_id}/savings"
        payload = {
            "data": {
                "attributes": {
                    "account_holder_id": request.data['account_holder_id'],
                    "product_id": request.data['product_id'],
                    "name": request.data['product_name'],
                    "monthly_remittance_amount": request.data['monthly_remittance_amount']
                }
            }
        }
        headers = {
            "accept": "application/json",
            "Authorization": f"Bearer {access_token}"
        }
        try:
            response = requests.post(url, json=payload, headers=headers)
            # response.raise_for_status()
            if response.status_code == 201:
                # Save the savings application data
                saving = serializer.save(account_holder_id=account_holder)

                masked_sacco_user_id = str(member_id)[0] + "x" * (len(str(member_id)) - 1)

                # Log user activity for creating savings
                log_user_activity(user, f"Created Barizi Account", request.path)
                helper_send_sms(phone=phone, message=f"Dear {sender_name} - {masked_sacco_user_id}, you have successfully submitted a {saving.product_name}. It is pending approval.", department="Customer Service")
                helper_send_sms(phone='254722391827', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a {saving.product_name}. It is pending approval. Do your KYC and approve", department="Customer Service")
                helper_send_sms(phone='254700531408', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a {saving.product_name}. It is pending approval. Do your KYC and approve", department="Customer Service")
                send_mail(
                    "Kenya Bankers Internet Banking Barizi Savings Application",
                    f"Kenya Bankers Internet Banking Barizi Savings Application",
                    settings.DEFAULT_FROM_EMAIL,
                    ["help@kenyabankers.coop"],  # Make sure user has an email field
                    fail_silently=False,
                    html_message=f'<p>{sender_name} - {masked_sacco_user_id} has successfully submitted a {saving.product_name}. It is pending approval. Do your KYC and approve</p>'
                )
                send_mail(
                    "Kenya Bankers Internet Banking Barizi Savings Application",
                    f"Kenya Bankers Internet Banking Barizi Savings Application",
                    settings.DEFAULT_FROM_EMAIL,
                    ["closure@kenyabankers.coop"],  # Make sure user has an email field
                    fail_silently=False,
                    html_message=f'<p>{sender_name} - {masked_sacco_user_id} has successfully submitted a {saving.product_name}. It is pending approval. Do your KYC and approve</p>'
                )
                return Response(response.json(), status=response.status_code)
            else:
                return JsonResponse(response.json(), status=response.status_code)

        except requests.RequestException as e:
            return Response({'error': str(e)}, status=response.status_code)
    else:
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)



@api_view(['GET'])
@csrf_exempt
def show_savings_details(request, member_id, savings_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    # access_token = get_access_token()
    user = CustomUser.objects.get(sacco_user_id=member_id)

    url = f"https://api.kwara.com/members/{member_id}/savings/{savings_id}?include=product"
    headers = {
        "accept": "application/json",
        "Authorization": f"Bearer {access_token}"
    }
    try:
        response = requests.get(url, headers=headers)
        response.raise_for_status()

        # Log user activity for viewing savings
        log_user_activity(user, f"Viewed Savings Details for {savings_id} ", request.path)
        return Response(response.json(), status=response.status_code)
    except requests.RequestException as e:
        return Response({'error': str(e)}, status=response.status_code)


# @api_view(['POST'])
# @csrf_exempt
# def create_loan_application(request, member_id):
#     data = json.loads(request.body)
#     serializer = LoanApplicationSerializer(data=request.data)
#     # serializer = LoanApplicationSerializer(data=data)
#     # access_token = get_access_token()

#     if serializer.is_valid():

#         # Get the account holder based on the member_id
#         account_holder = get_object_or_404(CustomUser, sacco_user_id=member_id)

#         # Check if the savings account already exists for the member with the same product_id
#         if LoanApplication.objects.filter(account_holder_id=account_holder, product_id=request.data['product_id']).exists():
#             return Response({'error': 'Loan account already exists for this product.'}, status=status.HTTP_400_BAD_REQUEST)

#         # Send the loan application to the external API
#         url = f"https://api.kwara.com/members/{member_id}/loans"
#         payload = {
#             "data": {
#                 "attributes": {
#                     "account_holder_id": request.data['account_holder_id'],
#                     "product_id": request.data['product_id'],
#                     "amount": request.data['amount'],
#                     "repayment_installments": request.data['repayment_installments'],
#                     "repayment_period": request.data['repayment_period'],
#                     "repayment_period_unit": request.data['repayment_period_unit'],
#                     "anticipated_disbursement_date": request.data['anticipated_disbursement_date'],
#                     "first_repayment_date": request.data['first_repayment_date'],
#                     "disbursement_mode": request.data['disbursement_mode'],
#                     "disbursement_bank_details": {
#                         "bank":request.data['bank'],
#                         "bank_branch":request.data['bank_branch'],
#                         "account_number":request.data['account_number']
#                     },
#                 }
#             }
#         }
#         headers = {
#             "accept": "application/json",
#             "content-type": "application/json",
#             "Authorization": f"Bearer {access_token}"
#         }
#         try:
#             response = requests.post(url, json=payload, headers=headers)
#             # response.raise_for_status()
#             if response.status_code == 201 :
#                 # If the external API call is successful, save the loan application data locally
#                 loan_application = serializer.save(account_holder_id=account_holder)
#                 response_data = response.json()
#                 # Save guarantors if provided in the request
#                 if 'guarantors' in data:
#                     guarantors = data['guarantors']  # assuming guarantors are sent as JSON in the request body
#                     for guarantor in guarantors:
#                         Guarantor.objects.create(
#                             loan_application=loan_application,
#                             guarantor_name=guarantor['name'],
#                             guarantor_member_id=guarantor['member_id'],
#                             guarantor_phone=guarantor['phone']
#                         )

#                 # Check if the state is PENDING_APPROVAL or ACTIVE
#                 loan_state = response_data['data']['attributes']['state']
#                 if loan_state == 'ACTIVE' or loan_state == "PENDING_APPROVAL":
#                     disbursement_mode = request.data['disbursement_mode']
#                     # Create a WithdrawRequest if disbursement_mode is mpesa or bank
#                     if disbursement_mode == "mpesa":
#                         response = WithdrawRequest.loan_mpesa_withdraw_request(data=data)
#                         return response
#                     if disbursement_mode == "bank":
#                         response = WithdrawRequest.loan_swift_withdraw_request(data=data)
#                         return response
#                     else:
#                         WithdrawRequest.objects.create(
#                             member_sacco_id = member_id,
#                             amount = data.get("amount"),
#                             payment_method = "fosa",
#                             request_response = "disbursed to fosa"

#                         )

#                 return Response(response.json(), status=response.status_code)
#             else:
#                 return JsonResponse(response.json(), status=response.status_code)

#         except requests.RequestException as e:
#             return Response({'error': str(e)}, status=response.status_code)
#     else:
#         return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@api_view(['POST'])
@csrf_exempt
def create_loan_application(request, member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    user = CustomUser.objects.get(sacco_user_id=member_id)
    sender_name = user.business if user.notes == 'Corporate Member' else user.name
    s_phone = user.phone
    sender_phone = s_phone.lstrip('+')
    # Attempt to parse JSON data from 'json_data' field within request.POST for form data
    try:
        data = json.loads(request.POST.get('json_data', '{}'))
        product_name = data.get('product_name', 'Unknown Product')  # Get product_name
    except json.JSONDecodeError:
        return Response({'error': 'Invalid JSON data'}, status=status.HTTP_400_BAD_REQUEST)
    
    serializer = LoanApplicationSerializer(data=request.data)
    if serializer.is_valid():
        # Get the account holder based on the member_id
        account_holder = get_object_or_404(CustomUser, sacco_user_id=member_id)
        # Check if the savings account already exists for the member with the same product_id

        if LoanApplication.objects.filter(account_holder_id=account_holder, product_id=request.data['product_id'], created_at__date=now().date()).exists():
            return Response({'error': 'Loan account already exists for this product.'}, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            # Set default values for nullable fields if they are missing
            validated_data = serializer.validated_data
            validated_data['repayment_installments'] = validated_data.get('repayment_installments', 0)
            validated_data['repayment_period'] = validated_data.get('repayment_period', 0)

            loan_application = serializer.save(account_holder_id=account_holder)
            # response_data = response.json()
            # Save guarantors
            # guarantors = data.get('guarantors', [])
            # for guarantor in guarantors:                
            #     if all(k in guarantor for k in ('type', 'name', 'member_id', 'phone')):
            #         Guarantor.objects.create(
            #             loan_application=loan_application,
            #             guarantor_type=guarantor['type'],
            #             guarantor_name=guarantor['name'],
            #             guarantor_member_id=guarantor['member_id'],
            #             guarantor_phone=guarantor['phone'],
            #         )
            #         helper_send_sms(phone=guarantor['phone'], message=f"{sender_name} has selected you as a loan guarantor. Log in to KBS Internet Banking to Approve")
            #     else:
            #         return Response({'error': 'Invalid guarantor data. All fields are required.'}, status=status.HTTP_400_BAD_REQUEST)

            guarantors = data.get('guarantors', [])
            for guarantor in guarantors:
                if all(k in guarantor for k in ('type', 'name', 'member_id', 'phone')):
                    existing_guarantor = Guarantor.objects.filter(
                        guarantor_member_id=guarantor['member_id'],
                        approved=False,
                        rejected=False
                    ).first()
                    Guarantor.objects.create(
                        product_name=product_name,
                        sender_name=sender_name,
                        loan_application=loan_application,
                        guarantor_type=guarantor['type'],
                        guarantor_name=guarantor['name'],
                        guarantor_member_id=guarantor['member_id'],
                        guarantor_phone=guarantor['phone'],
                    )
                    # print(guarantor.id)
                    if not existing_guarantor:
                        # If there's no pending status for this member, send SMS immediately
                        helper_send_guarantor_sms(
                            phone=guarantor['phone'],
                            message=f"{sender_name} has selected you as a loan guarantor.\nReply with:\n1. To approve \n2. To reject"
                            # message=f"{sender_name} has selected you as a loan guarantor. Log in to KBS Internet Banking to Approve. Reply with 1 to approve or 2 to reject"
                        )
                        helper_send_sms(phone='254720861566', message=f"{guarantor['name']} has been selected to guarantee {product_name} for {sender_name}.", department="Loans & Credit")
                        helper_send_sms(phone='254721662453', message=f"{guarantor['name']} has been selected to guarantee {product_name} for {sender_name}.", department="Loans & Credit")
                        helper_send_sms(phone='254722281318', message=f"{guarantor['name']} has been selected to guarantee {product_name} for {sender_name}.", department="Loans & Credit")
                        helper_send_sms(phone='254727336746', message=f"{guarantor['name']} has been selected to guarantee {product_name} for {sender_name}.", department="Loans & Credit")
                        helper_send_sms(phone='254790094839', message=f"{guarantor['name']} has been selected to guarantee {product_name} for {sender_name}.", department="Business Development")
                        send_mail(
                            "Kenya Bankers Internet Banking Loan Guarantee",
                            f"Kenya Bankers Internet Banking Loan Guarantee",
                            settings.DEFAULT_FROM_EMAIL,
                            ["retail@kenyabankers.coop"],  # Make sure user has an email field
                            fail_silently=False,
                            html_message=f'<p>{guarantor['name']} has been selected to guarantee {product_name} for {sender_name}.</p>'
                        )
                    else:
                        # If there's a pending status, we'll wait for the signal to send SMS
                        helper_send_sms(phone=guarantor['phone'], message=f"You have received a new guarantor request from {sender_name}. \nLog into KBS Internet Banking to approve or reject pending requests.", department="Loans & Credit")
                        # print(f"Waiting for other guarantor decisions for {guarantor['member_id']} to send SMS.")
                    # helper_send_guarantor_sms(phone=guarantor['phone'], message=f"{sender_name} has selected you as a loan guarantor. Log in to KBS Internet Banking to Approve. Reply with 1 to approve or 2 to reject")
                else:
                    return Response({'error': 'Invalid guarantor data. All fields are required.'}, status=status.HTTP_400_BAD_REQUEST)

            # Save securities
            security_types = {
                'titleDeed': 'Title Deed',
                'cashCollateral': 'Cash Collateral',
                'nseShares': 'NSE Shares',
                'otherSecurity': 'Other'
            }

            for key, display_name in security_types.items():
                security_data = data.get(key)
                if security_data:
                    reference_number = security_data.get('reference_number') if display_name in ['Title Deed', 'NSE Shares'] else None
                    description = security_data.get('description')
                    value = security_data.get('value')
                    if description and value:  # Check if both fields are present
                        Security.objects.create(
                            loan_application=loan_application,
                            security_type=display_name,
                            reference_number=reference_number,
                            description=description,
                            value=value
                        )
                    else:
                        return Response({'error': f'Invalid data for security type: {display_name}. Both description and value are required.'}, status=status.HTTP_400_BAD_REQUEST)

            # # Handle document uploads
            # document_data = {
            #     doc: request.FILES.get(doc) 
            #     for doc in ['passport_photo', 'signature', 'payslip', 'bank_statements', 'mpesa_statements', 'utility_bill', 'cash_flow_analysis', 'repayment_document']
            # }
            # if any(document_data.values()):  # Check if any documents were uploaded
            #     LoanOriginationDocuments.objects.create(
            #         loan_application=loan_application,
            #         **document_data
            #     )
            # First, extract single file fields (non-M2M)
            single_file_fields = ['passport_photo', 'signature', 'payslip', 'utility_bill', 'repayment_document']
            single_files = {
                field: request.FILES.get(field) for field in single_file_fields
                if request.FILES.get(field)
            }

            # Create the LoanOriginationDocuments instance without the M2M fields yet
            loan_docs = LoanOriginationDocuments.objects.create(
                loan_application=loan_application,
                **single_files
            )

            # Now handle the M2M multi-file fields
            m2m_fields = {
                'bank_statements': request.FILES.getlist('bank_statements'),
                'mpesa_statements': request.FILES.getlist('mpesa_statements'),
                'cash_flow_analysis': request.FILES.getlist('cash_flow_analysis'),
            }

            # For each M2M field, create Document instances and add to the loan_docs instance
            for field_name, files in m2m_fields.items():
                for file in files:
                    doc = Document.objects.create(file=file, loan_application=loan_application)
                    getattr(loan_docs, field_name).add(doc)

            masked_sacco_user_id = str(member_id)[0] + "x" * (len(str(member_id)) - 1)
            # Log user activity for viewing loans
            log_user_activity(user, f"{product_name} Submitted", request.path)
            helper_send_sms(phone=s_phone, message=f"Dear {sender_name} - {masked_sacco_user_id}, you have successfully submitted {product_name} application form. It is pending approval.", department="Loans & Credit")
            helper_send_sms(phone='254720861566', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a {product_name} application form. It is pending approval. Do your KYC and approve", department="Loans & Credit")
            helper_send_sms(phone='254721662453', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a {product_name} application form. It is pending approval. Do your KYC and approve", department="Loans & Credit")
            helper_send_sms(phone='254722281318', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a {product_name} application form. It is pending approval. Do your KYC and approve", department="Loans & Credit")
            helper_send_sms(phone='254727336746', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a {product_name} application form. It is pending approval. Do your KYC and approve", department="Loans & Credit")
            helper_send_sms(phone='254790094839', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a {product_name} application form. It is pending approval. Do your KYC and approve", department="Business Development")
            send_mail(
                "Kenya Bankers Internet Banking Loan Application",
                f"Kenya Bankers Internet Banking Loan Application",
                settings.DEFAULT_FROM_EMAIL,
                ["retail@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{sender_name} - {masked_sacco_user_id} has successfully submitted a {product_name} application form. It is pending approval. Do your KYC and approve</p>'
            )
            return Response({"success": 'Loan Origination created successfully'}, status=200)
        except requests.RequestException as e:
            return Response({'error': f'Error during loan submittion: {str(e)}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    else:
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
@receiver(post_save, sender=Guarantor)
def send_sms_on_status_change(sender, instance, **kwargs):
    if instance.approved or instance.rejected:
        # Check for other pending guarantors
        pending_guarantors = Guarantor.objects.filter(
            guarantor_member_id=instance.guarantor_member_id,
            approved=False,
            rejected=False
        ).exclude(id=instance.id)

        if not pending_guarantors.exists():
            # Fetch the guarantor instance again
            guarantor = Guarantor.objects.filter(
                guarantor_member_id=instance.guarantor_member_id,
                loan_application=instance.loan_application
            ).first()

            if guarantor and not guarantor.approved and not guarantor.rejected:  # Validate the guarantor
                guarantor_phone = guarantor.guarantor_phone.lstrip("+")
                helper_send_guarantor_sms(
                    phone=guarantor_phone,
                    message=f"{guarantor.sender_name} has selected you as a loan guarantor. Log in to KBS Internet Banking to Approve. Reply with 1 to approve or 2 to reject")

    
@csrf_exempt
def approve_and_update_loan_application(request, member_id, loan_id):

    token = request.headers.get("Authorization")
    memberr_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    user = CustomUser.objects.get(sacco_user_id=member_id)
    Auth_User = CustomUser.objects.get(sacco_user_id=memberr_id)

    if request.method == 'POST':
        loan_application = LoanApplication.objects.get(id=loan_id)
        sender_name = loan_application.business if loan_application.account_holder_id.notes == 'Corporate Member' else loan_application.full_name
        Dreceiver = loan_application.phone
        receiver = Dreceiver.lstrip("+")

        # Parse the JSON data sent in the request body
        data = json.loads(request.body)
        # Extract product_name from the request
        product_name = data.get('product_name', 'Unknown Product')  # Use a fallback if not provided
        
        # Update the LoanApplication model fields with form data
        loan_application.product_id = data.get('product_id')
        loan_application.amount = data.get('amount')
        loan_application.repayment_mode = data.get('repayment_mode')
        loan_application.loan_purpose = data.get('loan_purpose')
        loan_application.repayment_installments = data.get('repayment_installments')
        loan_application.repayment_period = data.get('repayment_period')
        loan_application.repayment_period_unit = data.get('repayment_period_unit')
        loan_application.anticipated_disbursement_date = data.get('anticipated_disbursement_date')
        loan_application.first_repayment_date = data.get('first_repayment_date')
        loan_application.save()


        # API request payload
        url = f"https://api.kwara.com/members/{member_id}/loans"
        # url = f"https://api.kwara.com/members/{member_id}/loans"
        payload = {
            "data": {
                "attributes": {
                    "account_holder_id": member_id,
                    "product_id": loan_application.product_id,
                    "amount": float(loan_application.amount),
                    "repayment_installments": loan_application.repayment_installments,
                    "repayment_period": loan_application.repayment_period,
                    "repayment_period_unit": loan_application.repayment_period_unit,
                    "anticipated_disbursement_date": str(loan_application.anticipated_disbursement_date),
                    "first_repayment_date": str(loan_application.first_repayment_date),
                    "disbursement_mode": loan_application.disbursement_mode,
                    "disbursement_bank_details": {
                        "bank": "Kenya Bankers",
                        "bank_branch": "Kenya Bankers",
                        "account_number": "FOSA"
                    },
                    # "disbursement_bank_details": {
                    #     "bank": loan_application.bank,
                    #     "bank_branch": loan_application.bank_branch,
                    #     "account_number": loan_application.account_number
                    # },
                }
            }
        }
    
        headers = {
            "accept": "application/json",
            "content-type": "application/json",
            "Authorization": f"Bearer {access_token}"
            # "Authorization": f"Bearer {access_token}"
        }
        
        try:
            # Send loan application to Kwara
            response = requests.post(url, json=payload, headers=headers)
            
            if response.status_code == 201:  # Loan successfully created in the external API
                # Update the loan status to "Appraised"
                loan_application.status = LoanApplication.Status.Appraised
                loan_application.save()  # Save the updated status in the database
                # print( f"loan status {loan_application.status}")
                masked_sacco_user_id = str(member_id)[0] + "x" * (len(str(member_id)) - 1)
                
                # Log user activity for viewing loans
                log_user_activity(Auth_User, f"{product_name} Appraised for {member_id} - {sender_name}", request.path)
                helper_send_sms(phone=receiver, message=f"Dear {sender_name}, your {product_name} has been appraised", department="Loans & Credit")
                helper_send_sms(phone='254720861566', message=f"{sender_name} - {masked_sacco_user_id}, {product_name} has been appraised", department="Loans & Credit")
                helper_send_sms(phone='254721662453', message=f"{sender_name} - {masked_sacco_user_id}, {product_name} has been appraised", department="Loans & Credit")
                helper_send_sms(phone='254722281318', message=f"{sender_name} - {masked_sacco_user_id}, {product_name} has been appraised", department="Loans & Credit")
                helper_send_sms(phone='254727336746', message=f"{sender_name} - {masked_sacco_user_id}, {product_name} has been appraised", department="Loans & Credit")
                helper_send_sms(phone='254790094839', message=f"{sender_name} - {masked_sacco_user_id}, {product_name} has been appraised", department="Business Development")
                send_mail(
                    "Kenya Bankers Internet Banking Loan Appraisal",
                    f"Kenya Bankers Internet Banking Loan Appraisal",
                    settings.DEFAULT_FROM_EMAIL,
                    ["retail@kenyabankers.coop"],  # Make sure user has an email field
                    fail_silently=False,
                    html_message=f'<p>{sender_name} - {masked_sacco_user_id}, {product_name} has been appraised</p>'
                )
                return JsonResponse({"success": "Loan application sent to Kwara and status updated to 'Appraised'."}, status=response.status_code)
            else:
                return JsonResponse(response.json(), status=response.status_code)
        
        except requests.RequestException as e:
            return JsonResponse({"error": str(e)}, status=500)
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)
    
@csrf_exempt
def reject_loan_application(request, member_id, loan_id):

    token = request.headers.get("Authorization")
    # memberr_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    # if user_id != member_id and auth_user.role != 'Admin':
    #     return JsonResponse({"error": 'permission denied'}, status=403)
    if auth_user.role != "Admin":
        return JsonResponse({"error": "Permission denied"}, status=403)
    
    # user = CustomUser.objects.get(sacco_user_id=member_id)
    # Auth_User = CustomUser.objects.get(sacco_user_id=memberr_id)
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            loan_application = LoanApplication.objects.get(id=loan_id)
            loan_application.status= LoanApplication.Status.Rejected
            loan_application.rejection_comment = data.get("rejection_reason")
            loan_application.save()
            Dreceiver = loan_application.phone
            receiver = Dreceiver.lstrip("+")
            user = loan_application.account_holder_id
            product_id = loan_application.product_id
            product_name = PRODUCTS.get(str(product_id), "Unknown Product")
            sender_name = user.business if user.notes == 'Corporate Member' else user.name
            masked_sacco_user_id = str(member_id)[0] + "x" * (len(str(member_id)) - 1)
            log_user_activity(auth_user, f"Rejected {product_name} application for user {member_id} - {sender_name}", request.path)
            helper_send_sms(phone=receiver, message=f"Dear {sender_name}, your {product_name} application has been rejected. Reason: {data.get('rejection_reason')}", department="Loans & Credit")
            helper_send_sms(phone='254720861566', message=f"{sender_name} - {masked_sacco_user_id}, {product_name} application has been rejected. Reason: {data.get('rejection_reason')}", department="Loans & Credit")
            helper_send_sms(phone='254721662453', message=f"{sender_name} - {masked_sacco_user_id}, {product_name} application has been rejected. Reason: {data.get('rejection_reason')}", department="Loans & Credit")
            helper_send_sms(phone='254722281318', message=f"{sender_name} - {masked_sacco_user_id}, {product_name} application has been rejected. Reason: {data.get('rejection_reason')}", department="Loans & Credit")
            helper_send_sms(phone='254727336746', message=f"{sender_name} - {masked_sacco_user_id}, {product_name} application has been rejected. Reason: {data.get('rejection_reason')}", department="Loans & Credit")
            helper_send_sms(phone='254790094839', message=f"{sender_name} - {masked_sacco_user_id}, {product_name} application has been rejected. Reason: {data.get('rejection_reason')}", department="Business Development")
            send_mail(
                "Kenya Bankers Internet Banking Loan Rejection",
                f"Kenya Bankers Internet Banking Loan Rejection",
                settings.DEFAULT_FROM_EMAIL,
                ["retail@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{sender_name} - {masked_sacco_user_id}, {product_name} application has been rejected. Reason: {data.get('rejection_reason')}</p>'
            )
            return JsonResponse({"success": 'loan aplication rejected successfully'}, status=201)
        except Exception as e:
            return JsonResponse({"error": 'could not reject loan application'},status=405)
        
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)
    
@csrf_exempt
def list_loan_applications(request):
       
    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    # loan_applications = LoanApplication.objects.all()
    if request.method == 'GET':
        loan_applications = LoanApplication.objects.all().values('account_holder_id', 'amount', 'product_id', 'status', 'id', 'created_at', 'employment_status', 'full_name', 'rejection_comment').order_by('-created_at')
        return JsonResponse(list(loan_applications), safe=False)

@csrf_exempt
def list_loan_applications_for_download(request, sacco_member_id):

    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    try:
        # Get the requesting user
        requesting_user = CustomUser.objects.get(sacco_user_id=sacco_member_id)
    except CustomUser.DoesNotExist:
        return JsonResponse({"error": f"User with sacco_user_id {sacco_member_id} not found"}, status=404)

    isAdmin = requesting_user.role == "Admin"

    if request.method == 'GET':
        # Fetch loan applications based on the user's role
        if isAdmin:
            loan_applications = LoanApplication.objects.select_related('account_holder_id').prefetch_related(
                'guarantors', 'securities', 'LoanOriginationDocuments'
            ).all().order_by('-created_at')
        else:
            loan_applications = LoanApplication.objects.select_related('account_holder_id').prefetch_related(
                'guarantors', 'securities', 'LoanOriginationDocuments'
            ).filter(account_holder_id=requesting_user).order_by('-created_at')

        # Serialize data
        data = []
        for loan in loan_applications:
            document_data = []
            for doc in loan.LoanOriginationDocuments.all():
                document_data.append({
                    'passport_photo': request.build_absolute_uri(doc.passport_photo.url) if doc.passport_photo else None,
                    'signature': request.build_absolute_uri(doc.signature.url) if doc.signature else None,
                    'payslip': request.build_absolute_uri(doc.payslip.url) if doc.payslip else None,
                    'bank_statements': [request.build_absolute_uri(f.file.url) for f in doc.bank_statements.all()] or None,
                    'mpesa_statements': [request.build_absolute_uri(f.file.url) for f in doc.mpesa_statements.all()] or None,
                    'utility_bill': request.build_absolute_uri(doc.utility_bill.url) if doc.utility_bill else None,
                    'cash_flow_analysis': [request.build_absolute_uri(f.file.url) for f in doc.cash_flow_analysis.all()] or None,
                    'repayment_document': request.build_absolute_uri(doc.repayment_document.url) if doc.repayment_document else None,
                })
            loan_data = {
                "id": loan.id,
                "account_holder_id": loan.account_holder_id.sacco_user_id,
                "amount": loan.amount,
                "status": loan.status,
                "product_id": loan.product_id,
                "repayment_installments": loan.repayment_installments,
                "repayment_period": loan.repayment_period,
                "repayment_period_unit": loan.repayment_period_unit,
                "anticipated_disbursement_date": loan.anticipated_disbursement_date,
                "first_repayment_date": loan.first_repayment_date,
                "disbursement_mode": loan.disbursement_mode,
                "repayment_mode": loan.repayment_mode,
                "processing_fee": loan.processing_fee,
                "processing_fee_reference": loan.processing_fee_reference,
                "created_at": loan.created_at,
                "rejection_comment": loan.rejection_comment,
                "user": {
                    "idNumber": loan.idNumber,
                    "name": loan.account_holder_id.name,
                    "email": loan.email,
                    "gender": loan.gender,
                    "phone": loan.phone,
                    "date_of_birth": loan.dateOfBirth,
                    "kra_pin": loan.kra_pin,
                    "marital_status": loan.marital_status,
                    "physical_address": loan.physical_address,
                    "postal_address": loan.postal_address,
                },
                "employment": {
                    "status": loan.employment_status,
                    "employer": loan.employer,
                    "staff_no": loan.staff_id,
                    "work_email": loan.work_email,
                    "work_phone": loan.telephone,
                    "postal_address": loan.work_postal_address,
                    "position": loan.position,
                    "terms_of_service": loan.terms_of_service,
                    "date_of_employment": loan.dateOfEmployement,
                },
                "business": {
                    'business': loan.business,
                    'email': loan.business_email,
                    'address': loan.business_address,
                    'location': loan.business_location,
                    'type': loan.business_activity,
                    'ownership': loan.business_ownership,
                },
                "guarantors": list(loan.guarantors.values(
                    "guarantor_member_id", "guarantor_type", "guarantor_name", "guarantor_phone", "approved", "confirming_id"
                )),
                "securities": list(loan.securities.values(
                    "security_type", "description", "value"
                )),
                "documents": document_data,
                # "documents": [
                #     {
                #         "passport_photo": request.build_absolute_uri(doc.passport_photo.url) if doc.passport_photo else None,
                #         "signature": request.build_absolute_uri(doc.signature.url) if doc.signature else None,
                #         "payslip": request.build_absolute_uri(doc.payslip.url) if doc.payslip else None,
                #         "bank_statements": request.build_absolute_uri(doc.bank_statements.url) if doc.bank_statements else None,
                #         "mpesa_statements": request.build_absolute_uri(doc.mpesa_statements.url) if doc.mpesa_statements else None,
                #         "utility_bill": request.build_absolute_uri(doc.utility_bill.url) if doc.utility_bill else None,
                #         "cash_flow_analysis": request.build_absolute_uri(doc.cash_flow_analysis.url) if doc.cash_flow_analysis else None,
                #         "repayment_document": request.build_absolute_uri(doc.repayment_document.url) if doc.repayment_document else None,
                #     } for doc in loan.LoanOriginationDocuments.all()
                # ],
            }
            data.append(loan_data)

        return JsonResponse(data, safe=False)
    else:
        return JsonResponse({"error": "Invalid request method"}, status=405)

@csrf_exempt
def view_loan_application(request,loan_id):

    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    if request.method == 'GET':
        try:
            loan = LoanApplication.objects.get(id=loan_id)
            # Fetch the guarantors related to this loan
            guarantors = loan.guarantors.all()  # related_name='guarantors' from the Guarantor model
            # Create a list of guarantor details to send to the frontend
            guarantor_data = [
                {
                    'type': guarantor.guarantor_type,
                    'name': guarantor.guarantor_name,
                    'member_id': guarantor.guarantor_member_id,
                    'phone': guarantor.guarantor_phone,
                    'confirming_id' : guarantor.confirming_id,
                    'status': "Approved" if guarantor.approved else "Pending Approval"
                }
                for guarantor in guarantors
            ]

            # Fetch the securities related to this loan
            securities = loan.securities.all()  # related_name='securities' from the Security model
            # Create a list of security details to send to the frontend
            security_data = [
                {
                    'type': security.security_type,
                    'reference_number': security.reference_number,
                    'description': security.description,
                    'value': str(security.value),  # Convert Decimal to string for JSON serialization
                }
                for security in securities
            ]

            # Fetch loan origination documents related to this loan
            documents = loan.LoanOriginationDocuments.all().first()  # Assuming only one set of documents per loan
            # document_data = {
            #     'passport_photo': documents.passport_photo.url if documents.passport_photo else None,
            #     'signature': documents.signature.url if documents.signature else None,
            #     'payslip': documents.payslip.url if documents.payslip else None,
            #     # 'bank_statements': documents.bank_statements.url if documents.bank_statements else None,
            #     'bank_statements': [request.build_absolute_uri(doc.file.url) for doc in documents.bank_statements.all()],
            #     'mpesa_statements': documents.mpesa_statements.url if documents.mpesa_statements else None,
            #     'utility_bill': documents.utility_bill.url if documents.utility_bill else None,
            #     'cash_flow_analysis': documents.cash_flow_analysis.url if documents.cash_flow_analysis else None,
            #     'repayment_document': documents.repayment_document.url if documents.repayment_document else None,
            # } if documents else {}
            document_data = {}

            bank_statements = []
            if hasattr(documents, 'bank_statements') and hasattr(documents.bank_statements, 'all'):
                bank_statements = [request.build_absolute_uri(doc.file.url) for doc in documents.bank_statements.all()]
            if not bank_statements and hasattr(documents, 'bank_statements') and hasattr(documents.bank_statements, 'url'):
                bank_statements = [request.build_absolute_uri(documents.bank_statements.url)]
            mpesa_statements = []
            if hasattr(documents, 'mpesa_statements') and hasattr(documents.mpesa_statements, 'all'):
                mpesa_statements = [request.build_absolute_uri(doc.file.url) for doc in documents.mpesa_statements.all()]
            if not mpesa_statements and hasattr(documents, 'mpesa_statements') and hasattr(documents.mpesa_statements, 'url'):
                mpesa_statements = [request.build_absolute_uri(documents.mpesa_statements.url)]
            cash_flow_analysis = []
            if hasattr(documents, 'cash_flow_analysis') and hasattr(documents.cash_flow_analysis, 'all'):
                cash_flow_analysis = [request.build_absolute_uri(doc.file.url) for doc in documents.cash_flow_analysis.all()]
            if not cash_flow_analysis and hasattr(documents, 'cash_flow_analysis') and hasattr(documents.cash_flow_analysis, 'url'):
                cash_flow_analysis = [request.build_absolute_uri(documents.cash_flow_analysis.url)]
            
            if documents:
                document_data = {
                    'passport_photo': documents.passport_photo.url if documents.passport_photo else None,
                    'signature': documents.signature.url if documents.signature else None,
                    'payslip': documents.payslip.url if documents.payslip else None,
                    'bank_statements': bank_statements or None,
                    # 'bank_statements': [request.build_absolute_uri(doc.file.url) for doc in documents.bank_statements.all()] or None,
                    'mpesa_statements': mpesa_statements or None,
                    # 'mpesa_statements': [request.build_absolute_uri(doc.file.url) for doc in documents.mpesa_statements.all()] or None,
                    'utility_bill': documents.utility_bill.url if documents.utility_bill else None,
                    'cash_flow_analysis': cash_flow_analysis or None,
                    # 'cash_flow_analysis': [request.build_absolute_uri(doc.file.url) for doc in documents.cash_flow_analysis.all()] or None,
                    'repayment_document':  documents.repayment_document.url if documents.repayment_document else None,
                }

            loan_data = {
                'account_holder_id': loan.account_holder_id.sacco_user_id,
                'member_type': loan.account_holder_id.notes,
                'account_holder_name': loan.account_holder_id.name,
                'account_holder_company': loan.account_holder_id.business,
                'product_id': loan.product_id,
                'amount': str(loan.amount),  # Convert Decimal to string for JSON serialization
                'repayment_installments': loan.repayment_installments,
                'repayment_period': loan.repayment_period,
                'repayment_period_unit': loan.repayment_period_unit,
                'anticipated_disbursement_date': loan.anticipated_disbursement_date,
                'first_repayment_date': loan.first_repayment_date,
                'disbursement_mode': loan.disbursement_mode,
                'repayment_mode': loan.repayment_mode,
                'id_number': loan.idNumber,
                'date_of_birth': loan.dateOfBirth,
                'gender': loan.gender,
                'physical_address': loan.physical_address,
                'postal_address': loan.postal_address,
                'marital_status': loan.marital_status,
                'phone': loan.phone,
                'kra_pin': loan.kra_pin,
                'employment_status': loan.employment_status,
                'employer': loan.employer,
                'staff_id': loan.staff_id,
                'work_email': loan.work_email,
                'email': loan.email,
                'work_postal_address': loan.work_postal_address,
                'position': loan.position,
                'terms_of_service': loan.terms_of_service,
                'business': loan.business,
                'telephone': loan.telephone,
                'dateOfEmployement': loan.dateOfEmployement,
                'business_email': loan.business_email,
                'business_address': loan.business_address,
                'business_location': loan.business_location,
                'business_activity': loan.business_activity,
                'business_ownership': loan.business_ownership,
                'loan_purpose': loan.loan_purpose,
                'sacco_loan_to_be_cleared': loan.sacco_loan_to_be_cleared,
                # 'bank': loan.bank,
                'processing_fee': loan.processing_fee,
                'processing_fee_reference': loan.processing_fee_reference,
                # 'bank_branch': loan.bank_branch,
                # 'account_number': loan.account_number,
                'created_at': loan.created_at.isoformat() if loan.created_at else None,  # ISO format for datetime
                'status': loan.status,
                'guarantors': guarantor_data,  # Include guarantor data in the response
                'securities': security_data,  # Include security data in the response
                'documents': document_data,  # Include loan origination documents
                'doc_data': [
                    {
                        "passport_photo": request.build_absolute_uri(doc.passport_photo.url) if doc.passport_photo else None,
                        "signature": request.build_absolute_uri(doc.signature.url) if doc.signature else None,
                        "payslip": request.build_absolute_uri(doc.payslip.url) if doc.payslip else None,
                        # "bank_statements": request.build_absolute_uri(doc.bank_statements.url) if doc.bank_statements else None,
                        # "mpesa_statements": request.build_absolute_uri(doc.mpesa_statements.url) if doc.mpesa_statements else None,
                        'bank_statements': [request.build_absolute_uri(file.file.url) for file in doc.bank_statements.all()] or None,
                        'mpesa_statements': [request.build_absolute_uri(file.file.url) for file in doc.mpesa_statements.all()] or None,
                        "utility_bill": request.build_absolute_uri(doc.utility_bill.url) if doc.utility_bill else None,
                        # "cash_flow_analysis": request.build_absolute_uri(doc.cash_flow_analysis.url) if doc.cash_flow_analysis else None,
                        'cash_flow_analysis': [request.build_absolute_uri(file.file.url) for file in doc.cash_flow_analysis.all()] or None,
                        "repayment_document": request.build_absolute_uri(doc.repayment_document.url) if doc.repayment_document else None,
                    } for doc in loan.LoanOriginationDocuments.all()
                ]
            }
            return JsonResponse(loan_data, safe=False)
        except LoanApplication.DoesNotExist:
            return JsonResponse({'error': 'Loan not found'}, status=404)


@api_view(['GET'])
@csrf_exempt
def show_loan_details(request, member_id, loan_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    user = CustomUser.objects.get(sacco_user_id=member_id)

    url = f"https://api.kwara.com/members/{member_id}/loans/{loan_id}?include=product"
    headers = {
        "accept": "application/json",
        "Authorization": f"Bearer {access_token}"
    }
    try:
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        # Log user activity for viewing loans
        log_user_activity(user, f"Viewed Loan Details for {loan_id} ", request.path)
        return Response(response.json(), status=response.status_code)
    except requests.RequestException as e:
        return Response({'error': str(e)}, status=response.status_code)

@api_view(['GET'])
@csrf_exempt
def show_loan_schedule(request, member_id, loan_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    url = f"https://api.kwara.com/members/{member_id}/loans/{loan_id}/schedules"
    headers = {
        "accept": "application/json",
        "Authorization": f"Bearer {access_token}"
    }
    try:
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        return Response(response.json(), status=response.status_code)
    except requests.RequestException as e:
        return Response({'error': str(e)}, status=response.status_code)

@csrf_exempt
def show_loan_transactions(request, loan_id):

    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")

    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    url = f"https://api.kwara.com/loans/{loan_id}/transactions"

    headers = {
        "accept": "application/json",
        "Authorization": f"Bearer {access_token}"
    }

    try:
        response = requests.get(url, headers=headers)
        response.raise_for_status()  # Raise an error for bad status codes
        return JsonResponse(response.json(), status=response.status_code)
    except requests.RequestException as e:
        return JsonResponse({'error': str(e)}, status=500)

@csrf_exempt
def loan_eligibility_by_products(request, member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    # access_token = get_access_token()
    user = CustomUser.objects.get(sacco_user_id=member_id)

    url = f"https://api.kwara.com/members/{member_id}/loan_eligibility?include=product"

    headers = {
        "accept": "application/json",
        "Authorization": f"Bearer {access_token}"
    }

    response = requests.get(url, headers=headers)
    # Log user activity for viewing loan eligibility
    log_user_activity(user, "Viewed Loan Eligibility", request.path)

    return JsonResponse(response.json())


@csrf_exempt
def show_member_savings_and_loans(request, member_id):
    
    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)

    if request.method == 'GET':
        try:
            savings_url = f"https://api.kwara.com/members/{member_id}/savings"
            loans_url = f"https://api.kwara.com/members/{member_id}/loans"
            headers = {
                "accept": "application/json",
                "Authorization": f"Bearer {access_token}"
            }

            # Fetch savings data
            savings_response = requests.get(savings_url, headers=headers)
            savings_response.raise_for_status()
            savings_data = savings_response.json().get("data", [])

            # Fetch loans data
            loans_response = requests.get(loans_url, headers=headers)
            loans_response.raise_for_status()
            loans_data = loans_response.json().get("data", [])

            # Extract the savings and loan IDs with the most recent updated_at
            most_recent_savings = max(savings_data, key=lambda x: x["attributes"]["updated_at"], default=None)
            most_recent_loan = max(loans_data, key=lambda x: x["attributes"]["updated_at"], default=None)

            # Extract only the savings_id and loan_id of the most recent entries
            recent_savings_id = most_recent_savings["id"] if most_recent_savings else None
            recent_loan_id = most_recent_loan["id"] if most_recent_loan else None

            # Return the combined response
            return JsonResponse({
                "savings_id": recent_savings_id,
                "loan_id": recent_loan_id,
                "savings_data": savings_data,
                "loans_data": loans_data
            }, status=200)
        except requests.RequestException as e:
            return JsonResponse({'error': str(e)}, status=500)
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)
    
# Risk Claim Views
class SpouseClaimView(APIView):
    permission_classes = [IsAuthenticated]
    def post(self, request, *args, **kwargs):
        user = request.user  # Get the authenticated user
        sender_name = user.business if user.notes == 'Corporate Member' else user.name
        member_name = request.data.get('member_name', 'Member')  # Extract member_name from the request data
        serializer = SpouseClaimSerializer(data=request.data)
        if serializer.is_valid():
            masked_sacco_user_id = str(user.sacco_user_id)[0] + "x" * (len(str(user.sacco_user_id)) - 1)
            serializer.save(sacco_user=user)  # Associate the claim with the user
            log_user_activity(user, f"Spouse Risk Claim submitted", request.path)
            helper_send_sms(phone='254720974594', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve", department="Finance")
            helper_send_sms(phone='254720371813', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve", department="Finance")
            send_mail(
                "Kenya Bankers Internet Banking Risk Claim",
                f"Kenya Bankers Internet Banking Risk Claim",
                settings.DEFAULT_FROM_EMAIL,
                ["help@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve</p>'
            )
            send_mail(
                "Kenya Bankers Internet Banking Risk Claim",
                f"Kenya Bankers Internet Banking Risk Claim",
                settings.DEFAULT_FROM_EMAIL,
                ["closure@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve</p>'
            )
            return Response({"message": "Spouse claim submitted successfully!"}, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
class PrincipalClaimView(APIView):
    permission_classes = [IsAuthenticated]
    def post(self, request, *args, **kwargs):
        user = request.user  # Get the authenticated user
        sender_name = user.business if user.notes == 'Corporate Member' else user.name
        member_name = request.data.get('member_name', 'Member')  # Extract member_name from the request data
        serializer = PrincipalClaimSerializer(data=request.data)
        if serializer.is_valid():
            masked_sacco_user_id = str(user.sacco_user_id)[0] + "x" * (len(str(user.sacco_user_id)) - 1)
            serializer.save(sacco_user=user)  # Associate the claim with the user
            log_user_activity(user, f"Principal Risk Claim submitted", request.path)
            helper_send_sms(phone='254720974594', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve", department="Finance")
            helper_send_sms(phone='254720371813', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve", department="Finance")
            send_mail(
                "Kenya Bankers Internet Banking Risk Claim",
                f"Kenya Bankers Internet Banking Risk Claim",
                settings.DEFAULT_FROM_EMAIL,
                ["help@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve</p>'
            )
            send_mail(
                "Kenya Bankers Internet Banking Risk Claim",
                f"Kenya Bankers Internet Banking Risk Claim",
                settings.DEFAULT_FROM_EMAIL,
                ["closure@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve</p>'
            )
            return Response({"message": "Principal claim submitted successfully!"}, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
class ParentClaimView(APIView):
    permission_classes = [IsAuthenticated]
    def post(self, request, *args, **kwargs):
        user = request.user  # Get the authenticated user
        sender_name = user.business if user.notes == 'Corporate Member' else user.name
        member_name = request.data.get('member_name', 'Member')  # Extract member_name from the request data
        serializer = ParentClaimSerializer(data=request.data)
        if serializer.is_valid():
            masked_sacco_user_id = str(user.sacco_user_id)[0] + "x" * (len(str(user.sacco_user_id)) - 1)
            serializer.save(sacco_user=user)  # Associate the claim with the user
            log_user_activity(user, f"Parent Risk Claim submitted", request.path)
            helper_send_sms(phone='254720974594', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve", department="Finance")
            helper_send_sms(phone='254720371813', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve", department="Finance")
            send_mail(
                "Kenya Bankers Internet Banking Risk Claim",
                f"Kenya Bankers Internet Banking Risk Claim",
                settings.DEFAULT_FROM_EMAIL,
                ["help@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve</p>'
            )
            send_mail(
                "Kenya Bankers Internet Banking Risk Claim",
                f"Kenya Bankers Internet Banking Risk Claim",
                settings.DEFAULT_FROM_EMAIL,
                ["closure@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve</p>'
            )
            return Response({"message": "Parent claim submitted successfully!"}, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
class ParentInLawClaimView(APIView):
    permission_classes = [IsAuthenticated]
    def post(self, request, *args, **kwargs):
        user = request.user  # Get the authenticated user
        sender_name = user.business if user.notes == 'Corporate Member' else user.name
        member_name = request.data.get('member_name', 'Member')  # Extract member_name from the request data
        serializer = ParentInLawClaimSerializer(data=request.data)
        if serializer.is_valid():
            masked_sacco_user_id = str(user.sacco_user_id)[0] + "x" * (len(str(user.sacco_user_id)) - 1)
            serializer.save(sacco_user=user)  # Associate the claim with the user
            log_user_activity(user, f"Parent In Law Risk Claim submitted", request.path)
            helper_send_sms(phone='254720974594', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve", department="Finance")
            helper_send_sms(phone='254720371813', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve", department="Finance")
            send_mail(
                "Kenya Bankers Internet Banking Risk Claim",
                f"Kenya Bankers Internet Banking Risk Claim",
                settings.DEFAULT_FROM_EMAIL,
                ["help@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve</p>'
            )
            send_mail(
                "Kenya Bankers Internet Banking Risk Claim",
                f"Kenya Bankers Internet Banking Risk Claim",
                settings.DEFAULT_FROM_EMAIL,
                ["closure@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve</p>'
            )
            return Response({"message": "ParentInLaw claim submitted successfully!"}, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
class DependantClaimView(APIView):
    permission_classes = [IsAuthenticated]
    def post(self, request, *args, **kwargs):
        user = request.user  # Get the authenticated user
        sender_name = user.business if user.notes == 'Corporate Member' else user.name
        member_name = request.data.get('member_name', 'Member')  # Extract member_name from the request data
        serializer = DependantClaimSerializer(data=request.data)
        if serializer.is_valid():
            masked_sacco_user_id = str(user.sacco_user_id)[0] + "x" * (len(str(user.sacco_user_id)) - 1)
            serializer.save(sacco_user=user)  # Associate the claim with the user
            log_user_activity(user, f"Dependant Risk Claim submitted", request.path)
            helper_send_sms(phone='254720974594', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve", department="Finance")
            helper_send_sms(phone='254720371813', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve", department="Finance")
            send_mail(
                "Kenya Bankers Internet Banking Risk Claim",
                f"Kenya Bankers Internet Banking Risk Claim",
                settings.DEFAULT_FROM_EMAIL,
                ["help@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve</p>'
            )
            send_mail(
                "Kenya Bankers Internet Banking Risk Claim",
                f"Kenya Bankers Internet Banking Risk Claim",
                settings.DEFAULT_FROM_EMAIL,
                ["closure@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve</p>'
            )
            return Response({"message": "Dependant claim submitted successfully!"}, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class InpatientClaimView(APIView):
    permission_classes = [IsAuthenticated]
    def post(self, request, *args, **kwargs):
        user = request.user  # Get the authenticated user
        sender_name = user.business if user.notes == 'Corporate Member' else user.name
        member_name = request.data.get('member_name', 'Member')  # Extract member_name from the request data
        serializer = InpatientClaimSerializer(data=request.data)
        if serializer.is_valid():
            masked_sacco_user_id = str(user.sacco_user_id)[0] + "x" * (len(str(user.sacco_user_id)) - 1)
            serializer.save(sacco_user=user)  # Associate the claim with the user
            log_user_activity(user, f"Inpatient Risk Claim submitted", request.path)
            helper_send_sms(phone='254720974594', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve", department="Finance")
            helper_send_sms(phone='254720371813', message=f"{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve", department="Finance")
            send_mail(
                "Kenya Bankers Internet Banking Risk Claim",
                f"Kenya Bankers Internet Banking Risk Claim",
                settings.DEFAULT_FROM_EMAIL,
                ["help@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve</p>'
            )
            send_mail(
                "Kenya Bankers Internet Banking Risk Claim",
                f"Kenya Bankers Internet Banking Risk Claim",
                settings.DEFAULT_FROM_EMAIL,
                ["closure@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{sender_name} - {masked_sacco_user_id} has successfully submitted a Risk Claim on behalf of {member_name}. It is pending approval. Do your KYC and approve</p>'
            )
            return Response({"message": "Inpatient claim submitted successfully!"}, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class RiskClaimListView(APIView):
    permission_classes = [IsAuthenticated]
    def get(self, request, *args, **kwargs):
        user = request.user
        is_admin = user.role == 'Admin'
        if is_admin:
            # Fetch all the claims from the respective models
            spouse_claims = SpouseClaim.objects.all()
            principal_claims = PrincipalClaim.objects.all()
            parent_claims = ParentClaim.objects.all()
            parent_in_law_claims = ParentInLawClaim.objects.all()
            dependant_claims = DependantClaim.objects.all()
            inpatient_claims = InpatientClaim.objects.all()
        else:
            # Non-admins see only their claims
            spouse_claims = SpouseClaim.objects.filter(sacco_user=user)
            principal_claims = PrincipalClaim.objects.filter(sacco_user=user)
            parent_claims = ParentClaim.objects.filter(sacco_user=user)
            parent_in_law_claims = ParentInLawClaim.objects.filter(sacco_user=user)
            dependant_claims = DependantClaim.objects.filter(sacco_user=user)
            inpatient_claims = InpatientClaim.objects.filter(sacco_user=user)

        # Serialize the claims using their respective serializers
        spouse_claim_serializer = SpouseClaimSerializer(spouse_claims, many=True)
        principal_claim_serializer = PrincipalClaimSerializer(principal_claims, many=True)
        parent_claim_serializer = ParentClaimSerializer(parent_claims, many=True)
        parent_in_law_claim_serializer = ParentInLawClaimSerializer(parent_in_law_claims, many=True)
        dependant_claim_serializer = DependantClaimSerializer(dependant_claims, many=True)
        inpatient_claim_serializer = InpatientClaimSerializer(inpatient_claims, many=True)

        # Combine all the serialized claims into one response
        all_claims = {
            "spouse_claims": spouse_claim_serializer.data,
            "principal_claims": principal_claim_serializer.data,
            "parent_claims": parent_claim_serializer.data,
            "parent_in_law_claims": parent_in_law_claim_serializer.data,
            "dependant_claims": dependant_claim_serializer.data,
            "inpatient_claims": inpatient_claim_serializer.data,
        }

        return Response(all_claims, status=status.HTTP_200_OK)

@csrf_exempt
@api_view(['GET'])
def fetch_risk(request, member_number):
    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    try:
        # Check if the member_number already exists
        if PrincipalClaim.objects.filter(member_Number=member_number).exists():
            return Response(
                {'error': 'This principal member claim already exists.'},
                status=status.HTTP_400_BAD_REQUEST
            )
        return Response({'message': 'Member number does not exist.'}, status=status.HTTP_200_OK)
    except Exception as e:
        return Response(
            {'error': str(e)},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR
        )

@csrf_exempt
@api_view(['GET'])
def fetch_In_patient_risk(request, member_number):

    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    try:
        # Check if the member_number already exists in InpatientClaim
        claim = InpatientClaim.objects.filter(member_Number=member_number).first()
        if claim:
            # print(f"Found claim: {claim.member_Number}, status: {claim.status}")
            # Check if the claim status is not 'disbursed'
            if claim.status == 'Disbursed':
                return Response(
                    {'error': 'This claim already exists and is pending disbursement.'},
                    status=status.HTTP_400_BAD_REQUEST
                )
        return Response({'message': 'Member number does not exist.'}, status=status.HTTP_200_OK)
    except Exception as e:
        return Response(
            {'error': str(e)},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR
        )
    
class SpouseRiskClaimDetailView(APIView):
    permission_classes = [IsAuthenticated]
    def get(self, request, risk_id, *args, **kwargs):
        try:
            # Fetch the claim object or return a 404 error if not found
            claim = get_object_or_404(SpouseClaim, id=risk_id)
            # Serialize the claim data
            serializer = SpouseClaimSerializer(claim)      
            # Return the serialized data
            return Response({ "success": True, "data": serializer.data }, status=status.HTTP_200_OK)
        except Exception as e: return Response({ "success": False, "error": str(e) }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class DependantRiskClaimDetailView(APIView):
    permission_classes = [IsAuthenticated]
    def get(self, request, risk_id, *args, **kwargs):
        try:
            # Fetch the claim object or return a 404 error if not found
            claim = get_object_or_404(DependantClaim, id=risk_id)
            
            # Serialize the claim data
            serializer = DependantClaimSerializer(claim)
            
            # Return the serialized data
            return Response({ "success": True, "data": serializer.data }, status=status.HTTP_200_OK)
        except Exception as e: return Response({ "success": False, "error": str(e) }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class ParentInLawRiskClaimDetailView(APIView):
    permission_classes = [IsAuthenticated]
    def get(self, request, risk_id, *args, **kwargs):
        try:
            # Fetch the claim object or return a 404 error if not found
            claim = get_object_or_404(ParentInLawClaim, id=risk_id)
            
            # Serialize the claim data
            serializer = ParentInLawClaimSerializer(claim)
            
            # Return the serialized data
            return Response({ "success": True, "data": serializer.data }, status=status.HTTP_200_OK)
        except Exception as e: return Response({ "success": False, "error": str(e) }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class ParentRiskClaimDetailView(APIView):
    permission_classes = [IsAuthenticated]
    def get(self, request, risk_id, *args, **kwargs):
        try:
            # Fetch the claim object or return a 404 error if not found
            claim = get_object_or_404(ParentClaim, id=risk_id)
            serializer = ParentClaimSerializer(claim)    
            # Return the serialized data
            return Response({ "success": True, "data": serializer.data }, status=status.HTTP_200_OK)
        except Exception as e: return Response({ "success": False, "error": str(e) }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class PrincipalRiskClaimDetailView(APIView):
    permission_classes = [IsAuthenticated]
    def get(self, request, risk_id, *args, **kwargs):
        try:
            # Fetch the claim object or return a 404 error if not found
            claim = get_object_or_404(PrincipalClaim, id=risk_id)
            serializer = PrincipalClaimSerializer(claim)            
            # Return the serialized data
            return Response({ "success": True, "data": serializer.data }, status=status.HTTP_200_OK)
        except Exception as e: return Response({ "success": False, "error": str(e) }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class InpatientRiskClaimDetailView(APIView):
    permission_classes = [IsAuthenticated]
    def get(self, request, risk_id, *args, **kwargs):
        try:
            # Fetch the claim object or return a 404 error if not found
            claim = get_object_or_404(InpatientClaim, id=risk_id)
            serializer = InpatientClaimSerializer(claim)            
            # Return the serialized data
            return Response({ "success": True, "data": serializer.data }, status=status.HTTP_200_OK)
        except Exception as e: return Response({ "success": False, "error": str(e) }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

# Mapping claim types to model names
CLAIM_MODEL_MAPPING = {
    'spouse': 'SpouseClaim',
    'principal': 'PrincipalClaim',
    'parent': 'ParentClaim',
    'parentInLaw': 'ParentInLawClaim',
    'dependant': 'DependantClaim',
    'inpatient': 'InpatientClaim',
}

@api_view(['PATCH'])
def update_risk_claim(request, claim_id, member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    claim_type = request.data.get('type')  # Expecting 'type' in the request payload
    if not claim_type or claim_type not in CLAIM_MODEL_MAPPING:
        return Response({"error": "Invalid or missing claim type"}, status=status.HTTP_400_BAD_REQUEST)

    model_name = CLAIM_MODEL_MAPPING[claim_type]
    user = CustomUser.objects.get(sacco_user_id=member_id)
    try:
        # Dynamically get the model class
        ClaimModel = apps.get_model(app_label='api', model_name=model_name)
        claim = ClaimModel.objects.get(id=claim_id)
        Dstatus = request.data.get('status', claim.status)
        Dnote = request.data.get('note', claim.note)
        Dname = claim.sacco_user.business if claim.sacco_user.notes == 'Corporate Member' else claim.sacco_user.name
        Dphone = claim.sacco_user.phone
        receiver = Dphone.lstrip("+")
        Drisk = claim.member_name

        # Update fields
        claim.status = request.data.get('status', claim.status)
        claim.note = request.data.get('note', claim.note)
        claim.save()

        log_user_activity(user, f"{Dname} Risk Claim {Dstatus}", request.path)
        # Send SMS based on the presence of a note
        if not Dnote:  # If note is empty or None
            helper_send_sms(phone=receiver, message=f"Dear {Dname}, your Risk Claim on behalf of {Drisk} has been {Dstatus}", department="Finance")
            helper_send_sms(phone='254720974594', message=f"{Dname} Risk Claim on behalf of {Drisk} has been {Dstatus}", department="Finance")
            helper_send_sms(phone='254720371813', message=f"{Dname} Risk Claim on behalf of {Drisk} has been {Dstatus}", department="Finance")
            send_mail(
                "Kenya Bankers Internet Banking Risk Claim",
                f"Kenya Bankers Internet Banking Risk Claim",
                settings.DEFAULT_FROM_EMAIL,
                ["help@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{Dname} Risk Claim on behalf of {Drisk} has been {Dstatus}</p>'
            )
            send_mail(
                "Kenya Bankers Internet Banking Risk Claim",
                f"Kenya Bankers Internet Banking Risk Claim",
                settings.DEFAULT_FROM_EMAIL,
                ["closure@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{Dname} Risk Claim on behalf of {Drisk} has been {Dstatus}</p>'
            )
        else:  # If note is present
            helper_send_sms(phone=receiver, message=f"Dear {Dname}, your Risk Claim on behalf of {Drisk} has been {Dstatus}. {Dnote}", department="Finance")
            helper_send_sms(phone='254720974594', message=f"{Dname} Risk Claim on behalf of {Drisk} has been {Dstatus}. {Dnote}", department="Finance")
            helper_send_sms(phone='254720371813', message=f"{Dname} Risk Claim on behalf of {Drisk} has been {Dstatus}. {Dnote}", department="Finance")
            send_mail(
                "Kenya Bankers Internet Banking Risk Claim",
                f"Kenya Bankers Internet Banking Risk Claim",
                settings.DEFAULT_FROM_EMAIL,
                ["help@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{Dname} Risk Claim on behalf of {Drisk} has been {Dstatus}. {Dnote}</p>'
            )
            send_mail(
                "Kenya Bankers Internet Banking Risk Claim",
                f"Kenya Bankers Internet Banking Risk Claim",
                settings.DEFAULT_FROM_EMAIL,
                ["closure@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{Dname} Risk Claim on behalf of {Drisk} has been {Dstatus}. {Dnote}</p>'
            )
        return Response({"message": "Status updated successfully"}, status=status.HTTP_200_OK)
    except ClaimModel.DoesNotExist:
        return Response({"error": "Claim not found"}, status=status.HTTP_404_NOT_FOUND)
    except Exception as e:
        return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)

# @csrf_exempt
# def change_member_state(request, member_id):

#     # access_token = get_access_token()

#     url = "https://api.kwara.com/members/4688NLMT/state"

#     payload = { "data": { "attributes": { "event": "approve" } } }
#     headers = {
#         "accept": "application/json",
#         "content-type": "application/json",
#         "Authorization": f"Bearer {access_token}"
#     }

#     response = requests.put(url, json=payload, headers=headers)

#     print(response.text)

def update_members_active_state_fosa():
    print("thread function called")
    try:
        ids = CustomUser.objects.filter(kwara_active=False,source=CustomUser.Source.InternetBanking).values_list('sacco_user_id', flat=True)

        print(f"ids {ids}")

        # os.remove(temp_file_path)  # Delete the temp file after extraction

        # Prepare for batching
        batch_size = 100  # Adjust based on API limits or performance considerations
        batched_ids = [ids[i:i + batch_size] for i in range(0, len(ids), batch_size)]

        # Fetch token and initialize response list
        token_info = get_kwara__access_token()

        # print(f"token info {token_info}")
        member_details = []

        for batch in batched_ids:
            # Refresh token if close to expiry
            current_time = int(time.time())
            if current_time > token_info['expires_at'] - 120:  # Refresh 2 minutes before expiry
                try:
                    print("Refreshing token...")
                    token_info = get_kwara__access_token()
                except Exception as e:
                    return JsonResponse({"status": "error", "message": f"Token refresh failed: {e}"}, status=500)

            # Fetch members in the batch
            for member_id in batch:
                url = f'https://api.kwara.com/members/{member_id}'
                headers = {
                    "Authorization": f"Bearer {token_info['access_token']}",
                    "accept": "application/json",
                }

                try:
                    response = requests.get(url, headers=headers)
                    response.raise_for_status()
                    member = response.json().get("data", {}).get("attributes", {})

                    if member:
                        kwara_status = member.get("state")

                        user = CustomUser.objects.get(sacco_user_id=member_id)

                        if user:
                            user.kwara_active = True if kwara_status == "ACTIVE" else False
                            user.save()

                        # Add to response list
                        member_details.append({
                            "member_id": member_id,
                        })

                except requests.HTTPError as http_err:
                    # print(f"HTTP error for ID {member_id}: {http_err}")
                    member_details.append({"member_id": member_id, "error": str(http_err)})
                except Exception as e:
                    print(f"Unexpected error for ID {member_id}: {e}")
                    member_details.append({"member_id": member_id, "error": str(e)})

        return JsonResponse({"status": "success", "members": member_details})

    except Exception as e:
        print(f"Thread crashed {e}")
        return JsonResponse({"status": "error", "message": str(e)}, status=500)
# def update_members_active_state_fosa():
#     """
#     Extract members from excel sheet
#     """
#     try:
#         # Extract IDs from the Excel file
#         # workbook = load_workbook(temp_file_path)
#         # sheet = workbook.active

#         # members = CustomUser.objects.filter(kwara_status=False)
#         ids = CustomUser.objects.filter(kwara_active=False).values_list('sacco_user_id', flat=True)

#         # os.remove(temp_file_path)  # Delete the temp file after extraction

#         # Prepare for batching
#         batch_size = 100  # Adjust based on API limits or performance considerations
#         batched_ids = [ids[i:i + batch_size] for i in range(0, len(ids), batch_size)]

#         # Fetch token and initialize response list
#         token_info = get_kwara__access_token()
#         member_details = []

#         for batch in batched_ids:
#             # Refresh token if close to expiry
#             current_time = int(time.time())
#             if current_time > token_info['expires_at'] - 120:  # Refresh 2 minutes before expiry
#                 try:
#                     print("Refreshing token...")
#                     token_info = get_kwara__access_token()
#                 except Exception as e:
#                     return JsonResponse({"status": "error", "message": f"Token refresh failed: {e}"}, status=500)

#             # Fetch members in the batch
#             for member_id in batch:
#                 # if CustomUser.objects.filter(sacco_user_id=member_id).exists():
#                 #     print(f"Skipping user ID {member_id}")
#                 #     continue  # Skip this ID and proceed to the next one
#                 # print(f"Processing ID: {member_id}")
#                 url = f'https://api.kwara.com/members/{member_id}'
#                 headers = {
#                     "Authorization": f"Bearer {token_info['access_token']}",
#                     "accept": "application/json",
#                 }

#                 try:
#                     response = requests.get(url, headers=headers)
#                     response.raise_for_status()
#                     member = response.json().get("data", {}).get("attributes", {})

#                     if member:
#                         # Extract member details
#                         # first_name = member.get("first_name", "")
#                         # middle_name = member.get("middle_name", "")
#                         kwara_status = member.get("state") 

#                         user = CustomUser.objects.get(sacco_user_id=member_id)

#                         if user:
#                             user.kwara_active = True if kwara_status == "ACTIVE" else False
#                             user.save()
#                         # last_name = member.get("last_name", "")
#                         # name = f"{first_name} {middle_name} {last_name}".strip()
#                         # date_of_birth = member.get("date_of_birth", "")
#                         # phone = member.get("phone_number", "")
#                         # email = member.get("email") or "email@example.com"
#                         # notes = "Individual Member"
#                         # role = "User"
#                         # sacco_user_id = member_id
#                         # default_password = "12Kagb@#"

#                         # Save or update user in the database
#                         # user, created = CustomUser.objects.get_or_create(
#                         #     phone=phone,
#                         #     defaults={
#                         #         "name": name,
#                         #         "date_of_birth": date_of_birth,
#                         #         "email": email,
#                         #         "notes": notes,
#                         #         "role": role,
#                         #         "sacco_user_id": sacco_user_id,
#                         #         "kwara_active": True if kwara_status == "ACTIVE" else False
#                         #     },
#                         # )
#                         # if not created:
#                         #     user.name = name
#                         #     user.date_of_birth = date_of_birth
#                         #     user.email = email
#                         #     user.sacco_user_id = sacco_user_id
#                         #     user.notes = notes
#                         #     user.role = role
#                         #     user.kwara_active = True if kwara_status == "ACTIVE" else False
#                         # user.set_password(default_password)
#                         # user.save()

#                         # Add to response list
#                         member_details.append({
#                             "member_id": member_id,
#                             # "name": name,
#                             # "phone": phone,
#                             # "email": email,
#                         })

#                 except requests.HTTPError as http_err:
#                     # print(f"HTTP error for ID {member_id}: {http_err}")
#                     member_details.append({"member_id": member_id, "error": str(http_err)})
#                 except Exception as e:
#                     # print(f"Unexpected error for ID {member_id}: {e}")
#                     member_details.append({"member_id": member_id, "error": str(e)})

#         return JsonResponse({"status": "success", "members": member_details})

#     except Exception as e:
#         return JsonResponse({"status": "error", "message": str(e)}, status=500)
#  ss   
def update_members_fosa_accounts():
    # print("This function has been called")
    try:
        # Extract IDs from the Excel file
        # workbook = load_workbook(temp_file_path)
        # sheet = workbook.active

        # members = CustomUser.objects.filter(kwara_status=False)
        ids = CustomUser.objects.filter(fosa_account__isnull=True,source=CustomUser.Source.InternetBanking).values_list('sacco_user_id', flat=True)
        # print(f"ids: {ids.count()}")

        # os.remove(temp_file_path)  # Delete the temp file after extraction

        # Prepare for batching
        batch_size = 100  # Adjust based on API limits or performance considerations
        batched_ids = [ids[i:i + batch_size] for i in range(0, len(ids), batch_size)]

        # Fetch token and initialize response list
        token_info = get_kwara__access_token()
        member_details = []

        for batch in batched_ids:
            # Refresh token if close to expiry
            current_time = int(time.time())
            if current_time > token_info['expires_at'] - 120:  # Refresh 2 minutes before expiry
                try:
                    print("Refreshing token...")
                    token_info = get_kwara__access_token()
                except Exception as e:
                    return JsonResponse({"status": "error", "message": f"Token refresh failed: {e}"}, status=500)

            # Fetch members in the batch
            for member_id in batch:
                # if CustomUser.objects.filter(sacco_user_id=member_id).exists():
                #     print(f"Skipping user ID {member_id}")
                #     continue  # Skip this ID and proceed to the next one
                # print(f"Processing ID: {member_id}")

                user = CustomUser.objects.get(sacco_user_id=member_id)

                url = f"https://api.kwara.com/members/{member_id}/savings"
                headers = {
                    'Authorization': f'Bearer {access_token}',
                    'accept': 'application/json',
                }
                try:
                    response = requests.get(url, headers=headers)
                    response.raise_for_status()
                    savings_data = response.json().get('data', [])

                    fosa_savings = next(
                    (s for s in savings_data if s.get('attributes', {}).get('product_name') == "FOSA Current" or s.get('attributes', {}).get('product_id') == "6006"),
                    None
                    )

                    staff_savings = next(
                        (s for s in savings_data if s.get('attributes', {}).get('product_name') == "Staff Account" or s.get('attributes', {}).get('product_id') == "6008"),
                        None
                    )
                    # Determine account_number based on availability
                    if fosa_savings and staff_savings:
                        # If both exist, prioritize Staff Account
                        # account_number = staff_savings['id']
                        # staff_account = staff_savings['id']
                        user.fosa_account = staff_savings['id']
                        user.save()
                    elif fosa_savings:
                        # Only FOSA exists
                        account_number = fosa_savings['id']
                        user.fosa_account = fosa_savings['id']
                        user.save()
                    elif staff_savings:
                        # Only Staff Account exists
                        # account_number = staff_savings['id']
                        # staff_account = staff_savings['id']
                        user.fosa_account = staff_savings['id']
                        user.save()
                        # Add to response list
                        member_details.append({
                            "member_id": member_id,
                        })

                except requests.HTTPError as http_err:
                    # print(f"HTTP error for ID {member_id}: {http_err}")
                    member_details.append({"member_id": member_id, "error": str(http_err)})
                except Exception as e:
                    # print(f"Unexpected error for ID {member_id}: {e}")
                    member_details.append({"member_id": member_id, "error": str(e)})

        return JsonResponse({"status": "success", "members": member_details})

    except Exception as e:
        return JsonResponse({"status": "error", "message": str(e)}, status=500)
@csrf_exempt
def refresh_members_status_fosa(request):

    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    """Handles saving fosa and kwara status for members in database"""

    thread = threading.Thread(target=update_members_active_state_fosa)
    thread.start()
    return JsonResponse({"status": "success", "message": "Processing started in background"})

@csrf_exempt
def refresh_members_fosa_accounts(request):

    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    """Handles saving fosa and kwara status for members in database"""

    thread = threading.Thread(target=update_members_fosa_accounts)
    thread.start()
    return JsonResponse({"status": "success", "message": "Processing started in background"})

# @csrf_exempt
# def verify_individual(request):

#     # access_token = get_access_token()
#     # type="national"
#     identity_number = 38174925
    
#     # Endpoint URL for the identity verification
#     url = f"https://api.metropol.co.ke:1234/api/v1/identity/verify"
    
#     # Generate the timestamp (example format: 20140708175839987843)
#     timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S%f")

#     # Generate the API hash (api_secret + timestamp)
#     # hash_input = api_secret + timestamp
#     # api_hash = hashlib.sha256(hash_input.encode()).hexdigest()

#     # Headers for the request
#     headers = {
#         "X-METROPOL-REST-API-KEY": "DKKEIE3CKGPAIRJVN495JFJAJ",
#         "X-METROPOL-REST-API-HASH": "6b4412c63b19cd86e9939c43d115x961ef4357698da42f984287e6d0029c5671",
#         "X-METROPOL-REST-API-TIMESTAMP": timestamp,
#         "Content-Type": "application/json"
#     }

#     # Payload data for the request
#     data = {
#         "report_type": 1,  # Identity Verification Report Type
#         "identity_number": identity_number,
#         "identity_type": "001"  # E.g. '001' for national ID
#     }

#     try:
#         # Make the POST request
#         response = requests.post(url, headers=headers, json=data)

#         # Check if the request was successful
#         if response.status_code == 200:
#             return response.json()  # Return the API response as JSON
#         else:
#             return {"error": f"Request failed with status code {response.status_code}", "details": response.text}
    
#     except requests.RequestException as e:
#         # Handle any request errors
#         return {"error": str(e)}

@csrf_exempt
def lipa_na_mpesa(request):
    try:

        # data = json.loads(request.body)
        # business_shortCode = 888880
        # phone = data.get('phone')
        # amount = data.get('amount')
        # description = data.get('description')
        # code = data.get('code')
        # acct_number = data.get('acct_number')

        business_shortCode = "888880"
        phone = "254724265242"
        amount = "100"
        description = "Customer PayBill Online"
        code = business_shortCode
        acct_number = "37231995236"


        formatted_time = get_timestamp()
        decoded_password = generate_password()
        access_token = generate_access_token()

        api_url = "https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest"

        headers = {
            'Authorization': f'Bearer {access_token}',
            'Content-Type': 'application/json'
        }

        mpesa_request = {
            "BusinessShortCode": "174379",
            "Password": decoded_password,
            "Timestamp": formatted_time,
            "TransactionType": "CustomerPayBillOnline",
            "Amount": amount,
            "PartyA": phone,
            "PartyB": "174379",
            "PhoneNumber": phone,
            "CallBackURL": "https://mydomain.com/path",
            "AccountReference": acct_number,
            "TransactionDesc": description,
        }


        response = requests.request("POST", api_url, headers=headers, json=mpesa_request)
        response_data = response.json()
        if response.status_code == 200:
            return JsonResponse(response_data, status=200)
        else:
            return JsonResponse(response_data, status=response.status_code)
    except requests.exceptions.RequestException as e:
        return JsonResponse({'error': str(e)}, status=500)


# @csrf_exempt
# def extract_members(request):
#     # access_token = get_access_token()
#     if request.method == 'GET':
#         url = 'https://api.kwara.com/members'
#         headers = {
#             'Authorization': f'Bearer {access_token}',
#             'accept': 'application/json',
#         }

#         try:
#             response = requests.get(url, headers=headers)
#             response.raise_for_status()  # Raise an error for bad status codes
#         except requests.RequestException as e:
#             print(f"RequestException: {e}")
#             return JsonResponse({'error': str(e)}, status=500)

#         try:
#             members_data = response.json().get('data', [])
#             for member in members_data:
#                 attributes = member.get('attributes', {})
#                 first_name = attributes.get('first_name', '')
#                 middle_name = attributes.get('middle_name', '')
#                 last_name = attributes.get('last_name', '')

#                 # Combine names into one field
#                 name = f"{first_name} {middle_name} {last_name}".strip()
#                 date_of_birth = attributes.get('date_of_birth', '')
#                 phone = attributes.get('phone_number', '')
#                 email = attributes.get('email', '')
#                 sacco_user_id = member['id']

#                 if not phone:
#                     print(f"Skipping member with sacco_user_id={sacco_user_id} due to missing phone number.")
#                     continue

#                 if not email:
#                     print(f"Skipping member with sacco_user_id={sacco_user_id} due to missing email.")
#                     continue

#                 if not date_of_birth:
#                     print(f"Skipping member with sacco_user_id={sacco_user_id} due to missing date_of_birth.")
#                     continue

#                 if not name:
#                     print(f"Skipping member with sacco_user_id={sacco_user_id} due to missing date_of_birth.")
#                     continue

#                 default_password = "12345"

#                 # Check if the user with the given phone already exists
#                 try:
#                     user = CustomUser.objects.get(phone=phone)
#                     user.name = name
#                     user.date_of_birth = date_of_birth
#                     user.email = email
#                     user.sacco_user_id = sacco_user_id
#                     user.set_password(default_password)
#                     user.save()
#                 except CustomUser.DoesNotExist:
#                     CustomUser.objects.create(
#                         name=name,
#                         date_of_birth=date_of_birth,
#                         phone=phone,
#                         email=email,
#                         sacco_user_id=sacco_user_id
#                     )
#                     user.set_password(default_password)
#                     user.save()
#             return JsonResponse(response.json(), status=response.status_code)
#         except Exception as e:
#             print(f"Exception: {e}")
#             return JsonResponse({'error': str(e)}, status=500)
#     else:
#         return JsonResponse({'error': 'Invalid request method'}, status=405)

@csrf_exempt
def extract_single_member(request, member_id):

    token = request.headers.get("Authorization")
    memberr_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != memberr_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    sacco_user_id = member_id  # Set the specific sacco_user_id here
    # access_token = get_P_access_token()
    # access_token = get_access_token()

    if request.method == 'GET':
        url = f'https://api.kwara.com/members/{member_id}'
        headers = {
            'Authorization': f'Bearer {access_token}',
            'accept': 'application/json',
        }

        try:
            response = requests.get(url, headers=headers)
            response.raise_for_status()  # Raise an error for bad status codes
        except requests.RequestException as e:
            # print(f"RequestException: {e}")
            return JsonResponse({'error': str(e)}, status=500)

        try:
            member = response.json().get('data', {}).get('attributes', {})
            if not member:
                return JsonResponse({'error': 'Member not found'}, status=404)

            # Process member data
            first_name = member.get('first_name', '')
            middle_name = member.get('middle_name', '')
            last_name = member.get('last_name', '')
            name = f"{first_name} {middle_name} {last_name}".strip()
            date_of_birth = member.get('date_of_birth', '')
            phone = member.get('phone_number', '')
            email = member.get('email', '')
            kwara_status = member.get("state")
            notes = "Individual Member"
            # role = "Admin"

            default_password = "12Kgba@#"

            # Check if the user already exists
            if CustomUser.objects.filter(phone=phone).exists():
                return JsonResponse({"message": "User already exists"}, status=200)
            
            user = CustomUser.objects.create(
                name=name,
                date_of_birth=date_of_birth,
                phone=phone,
                email=email,
                notes = notes,
                kwara_active = True if kwara_status == "ACTIVE" else False,
                source = "Kwara",
                # role = role,
                sacco_user_id=sacco_user_id
            )
            user.set_password(default_password)
            user.save()

            user = CustomUser.objects.get(sacco_user_id=member_id)
            AdminUser = CustomUser.objects.get(sacco_user_id=memberr_id)
            sender_name = user.business if user.notes == 'Corporate Member' else user.name

            # Log user activity for viewing savings
            log_user_activity(AdminUser, f"{sender_name} - {member_id} Details Extracted", request.path)

            return JsonResponse(member, status=response.status_code)
        except Exception as e:
            # print(f"Exception: {e}")
            return JsonResponse({'error': str(e)}, status=500)
    else:
        return JsonResponse({'error': 'Invalid request method'}, status=405)

# @csrf_exempt
def get_kwara__access_token():
    """
    Fetches an access token from Kwara's API and calculates its expiry time.
    """
    client_id = "hW5DhVcUHSb06W45ERIqdXX6D6C9CElC1KXbgkDWomQ"
    client_secret = "3tEroB79viucZc5sg6Fjqf6TpOevyXY_BQg-IaYxxpE"
    url = 'https://api.kwara.com/oauth/token'
    payload = {
        'grant_type': 'client_credentials',
        'client_id': client_id,
        'client_secret': client_secret,
    }

    response = requests.post(url, data=payload)
    if response.status_code == 200:
        token_data = response.json()
        return {
            'access_token': token_data.get('access_token'),
            'expires_at': int(time.time()) + token_data.get('expires_in'),
        }
    else:
        raise ValueError(f"Failed to fetch access token, status code: {response.status_code}")
    
# def process_file_in_background(temp_file_path):
#     """
#     Extract members from excel sheet
#     """
#     try:
#         # Extract IDs from the Excel file
#         workbook = load_workbook(temp_file_path)
#         sheet = workbook.active
#         ids = [
#             row[0]
#             for row in sheet.iter_rows(
#                 min_row=6, max_row=sheet.max_row, min_col=1, max_col=1, values_only=True
#             )
#             if row[0]  # Skip empty cells
#         ]
#         os.remove(temp_file_path)  # Delete the temp file after extraction

#         # Prepare for batching
#         batch_size = 100  # Adjust based on API limits or performance considerations
#         batched_ids = [ids[i:i + batch_size] for i in range(0, len(ids), batch_size)]

#         # Fetch token and initialize response list
#         token_info = get_kwara__access_token()
#         member_details = []

#         for batch in batched_ids:
#             # Refresh token if close to expiry
#             current_time = int(time.time())
#             if current_time > token_info['expires_at'] - 120:  # Refresh 2 minutes before expiry
#                 try:
#                     print("Refreshing token...")
#                     token_info = get_kwara__access_token()
#                 except Exception as e:
#                     return JsonResponse({"status": "error", "message": f"Token refresh failed: {e}"}, status=500)

#             # Fetch members in the batch
#             for member_id in batch:
#                 if CustomUser.objects.filter(sacco_user_id=member_id).exists():
#                     print(f"Skipping user ID {member_id}")
#                     continue  # Skip this ID and proceed to the next one
#                 print(f"Processing ID: {member_id}")
#                 url = f'https://api.kwara.com/members/{member_id}'
#                 headers = {
#                     "Authorization": f"Bearer {token_info['access_token']}",
#                     "accept": "application/json",
#                 }

#                 try:
#                     response = requests.get(url, headers=headers)
#                     response.raise_for_status()
#                     member = response.json().get("data", {}).get("attributes", {})

#                     if member:
#                         # Extract member details
#                         first_name = member.get("first_name", "")
#                         middle_name = member.get("middle_name", "")
#                         last_name = member.get("last_name", "")
#                         name = f"{first_name} {middle_name} {last_name}".strip()
#                         date_of_birth = member.get("date_of_birth", "")
#                         phone = member.get("phone_number", "")
#                         email = member.get("email") or ""
#                         kwara_status = member.get("state") 
#                         notes = "Individual Member"
#                         role = "User"
#                         sacco_user_id = member_id
#                         default_password = "12Kagb@#"

#                         # Save or update user in the database
#                         user, created = CustomUser.objects.get_or_create(
#                             phone=phone,
#                             defaults={
#                                 "name": name,
#                                 "date_of_birth": date_of_birth,
#                                 "email": email,
#                                 "notes": notes,
#                                 "role": role,
#                                 "sacco_user_id": sacco_user_id,
#                                 "kwara_active": True if kwara_status == "ACTIVE" else False,
#                             },
#                         )
#                         if not created:
#                             user.name = name
#                             user.date_of_birth = date_of_birth
#                             user.email = email
#                             user.sacco_user_id = sacco_user_id
#                             user.notes = notes
#                             user.role = role
#                             user.kwara_active = True if kwara_status == "ACTIVE" else False
#                         user.set_password(default_password)
#                         user.save()

#                         # Add to response list
#                         member_details.append({
#                             "member_id": member_id,
#                             "name": name,
#                             "phone": phone,
#                             "email": email,
#                         })

#                 except requests.HTTPError as http_err:
#                     print(f"HTTP error for ID {member_id}: {http_err}")
#                     member_details.append({"member_id": member_id, "error": str(http_err)})
#                 except Exception as e:
#                     print(f"Unexpected error for ID {member_id}: {e}")
#                     member_details.append({"member_id": member_id, "error": str(e)})

#         return JsonResponse({"status": "success", "members": member_details})

#     except Exception as e:
#         return JsonResponse({"status": "error", "message": str(e)}, status=500)

# def process_file_in_background_kwara(temp_file_path):
#     """
#     Extracts member details from the Excel sheet and creates users in the database.
#     """
#     try:
#         # Load the Excel workbook and sheet
#         workbook = load_workbook(temp_file_path)
#         sheet = workbook.active
        
#         # Extract member details from each row
#         members = []
#         for row in sheet.iter_rows(min_row=6, values_only=True):  # Start from row 6
#             member_id = row[0]
#             name = row[1]
#             phone = row[2]
#             id_number = row[3]
#             kwara_status = row[4]

#             if not member_id:  # Ensure mandatory fields are present
#                 continue

#             # Dynamically build the filter condition
#             query = Q(sacco_user_id=member_id)
#             if phone:  # Only check phone if it's not None
#                 query |= Q(phone=phone)

#             # Check if user already exists
#             if CustomUser.objects.filter(query).exists():
#                 print(f"Skipping existing user ID: {member_id}, Phone: {phone}")
#                 continue

#             # Prepare default password
#             default_password = "12Kagb@#"

#             try:
#                 # Create the user
#                 user = CustomUser(
#                     sacco_user_id=member_id,
#                     name=name,
#                     phone=phone,
#                     id_number=id_number,
#                     kwara_active=True if kwara_status == "ACTIVE" else False,
#                 )
#                 user.set_password(default_password)
#                 print(f"saved user {member_id}")
#                 user.save()

#                 members.append({"member_id": member_id, "name": name, "phone": phone})
#             except Exception as e:
#                 print(f"Skipping user due to error: {e}")

#         # Remove temp file after processing
#         os.remove(temp_file_path)

#         print(f"Successfully processed {len(members)} new users.")
#     except Exception as e:
#         print(f"Error processing file: {e}")

@csrf_exempt
def extract_kwara_members_excel(request):
    """
    Handles the uploaded file, extracts IDs, fetches member details, and saves to the database.
    """

    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    AdminUser = CustomUser.objects.get(sacco_user_id=member_id)
    
    if request.method != "POST" or not request.FILES.get("file"):
        return JsonResponse({"status": "error", "message": "Invalid request"}, status=400)

    uploaded_file = request.FILES["file"]

    # Save the file temporarily
    temp_file_path = os.path.join(settings.MEDIA_ROOT, uploaded_file.name)
    with open(temp_file_path, "wb") as f:
        for chunk in uploaded_file.chunks():
            f.write(chunk)

    # Run the process in a separate thread
    thread = threading.Thread(target=process_file_in_background_with_excel_from_kwara, args=(temp_file_path,))
    print("Background thread started...")
    thread.start()

    # Log user activity for viewing savings
    log_user_activity(AdminUser, "Members Excel extracted", request.path)
    return JsonResponse({"status": "success", "message": "Processing started in the background"})

def chunk_list(lst, chunk_size):
    """Yield successive chunks from a list."""
    for i in range(0, len(lst), chunk_size):
        yield lst[i:i + chunk_size]

# def process_file_in_background(temp_file_path):
#     """
#     Process an Excel sheet to extract and save users while avoiding SQL limitations.
#     Logs users skipped due to UNIQUE constraint violations.
#     """
#     try:
#         print("🚀 Starting Excel file processing...")
#         workbook = load_workbook(temp_file_path)
#         sheet = workbook.active

#         all_member_ids = set()
#         new_users = []
#         skipped_users = []  # Store users skipped due to errors

#         for row in sheet.iter_rows(min_row=2, values_only=True):
#             member_id = row[4]
#             if not member_id:
#                 continue
#             all_member_ids.add(member_id)

#             new_users.append({
#                 "sacco_user_id": member_id,
#                 "date_of_birth": str(row[3]),
#                 "name": row[5],
#                 "phone": row[6],
#                 "email": row[7],
#                 # "kwara_active": row[8] == "Active",
#                 "kwara_active":True if row[8] == "Active" else False,
#                 "physical_address": row[9],
#                 "employer": row[10],
#                 "notes": "Individual Member",
#             })
#         print(f"✅ Total unique member IDs extracted: {len(all_member_ids)}")

#         # Fetch existing users in chunks
#         existing_ids = set()
#         chunk_size = 500
#         for chunk in chunk_list(list(all_member_ids), chunk_size):
#             existing_ids.update(
#                 CustomUser.objects.filter(sacco_user_id__in=chunk).values_list("sacco_user_id", flat=True)
#             )

#         missing_users = all_member_ids - existing_ids  # Users not found in DB
#         print(f"🛑 Existing users found: {len(existing_ids)}")
#         print(f"🆕 New users to create: {len(missing_users)}")

#         # Track skipped users
#         for user_id in existing_ids:
#             print(f"⚠️ Skipping existing user ID: {user_id}")
#             skipped_users.append(user_id)
            
#         new_users = [user for user in new_users if user["sacco_user_id"] in missing_users]

#         saved_users = 0
#         for user_data in new_users:
#             try:
#                 user = CustomUser(**user_data)
#                 user.set_password("12Kagb@#")  # Set default password
#                 user.save()
#                 print(f"Saved user with name {user.name}")
#                 saved_users += 1
#             except IntegrityError as e:
#                 skipped_users.append(f"Skipped user {user_data['sacco_user_id']} - {e}")
#             except Exception as e:
#                 skipped_users.append(f"Error with user {user_data['sacco_user_id']} - {e}")

#         # Log skipped users to a file
#         skipped_users_file = "skipped_users.txt"
#         with open(skipped_users_file, "w") as file:
#             for line in skipped_users:
#                 file.write(line + "\n")

#         os.remove(temp_file_path)
#         print(f"Successfully processed {saved_users} new users. Skipped {len(skipped_users)} users.")

#     except Exception as e:
#         print(f"Error processing file: {e}")

# def process_file_in_background_with_excel_from_kwara(temp_file_path):
#     """
#     Extracts member details from the Excel sheet, prints all member_ids, 
#     and checks which members were not saved in the database.
#     """

#     close_old_connections()
#     try:
#         print("Processing file in background...")

#         # Load the Excel workbook and sheet
#         workbook = load_workbook(temp_file_path)
#         sheet = workbook.active

#         # Extract member IDs from each row
#         all_member_ids = set()  # Store all member_ids from Excel
#         new_users = []  # Store new users for creation
#         skipped_users = []  # Store already existing users
        
#         for row in sheet.iter_rows(min_row=6, values_only=True):  # Start from row 6
#             member_id = row[0]  # First column contains the member ID
#             phone_number = row[2]  # First column contains the member ID

#             if not member_id:  # Ensure member_id is present
#                 continue

#             all_member_ids.add(member_id)  # Collect member_id

#             # Check if user exists
#             if CustomUser.objects.filter(sacco_user_id=member_id).exists():
#                 skipped_users.append(f"Skipping existing user ID: {member_id}")
#                 print(f"Skipping existing user ID: {member_id}")
#                 continue

#             # Check if phone number already exists in DB
#             if CustomUser.objects.filter(phone=phone_number).exists():
#                 print(f"⚠️ Skipping user {member_id} - Phone number already exists: {phone_number}")
#                 skipped_users.append(f"⚠️ Skipping user {member_id} - Phone number already exists: {phone_number}")
#                 continue

#             print("New users to be saved:", new_users)

#             # Collect user data for creation
#             new_users.append({
#                 "sacco_user_id": member_id,
#                 "notes": "Individual Member",
#                 "name": row[1],
#                 "phone": row[2],
#                 "id_number": row[3],
#                 "kwara_active": True if row[4] == "ACTIVE" else False,
#                 "source" : "Kwara",
#             })

#         # Print all member IDs from Excel
#         # print("\nAll Member IDs from Excel:")
#         # print(all_member_ids)

#         # Find missing users
#         existing_ids = set(CustomUser.objects.filter(sacco_user_id__in=all_member_ids).values_list('sacco_user_id', flat=True))
#         missing_users = all_member_ids - existing_ids  # Users not found in DB

#         # Print missing users
#         print("\nUsers not saved in the database:")
#         print(missing_users)

#         # Save new users
#         with transaction.atomic():
#             for user_data in new_users:
#                 try:
#                     user = CustomUser(**user_data)
#                     user.set_password("12Kagb@#")  # Set default password
#                     print(f"Saved user: {user.sacco_user_id}")
#                     user.save() 
#                 except IntegrityError as e:
#                     print(f"Error saving user {user_data['sacco_user_id']}: {e}")
#                     skipped_users.append(f"Skipped user {user_data['sacco_user_id']}: {e}")
#                 except Exception as e:
#                     skipped_users.append(f"Error with user {user_data['sacco_user_id']}: {e}")

#         # Log skipped users to a file
#         skipped_users_file = "skipped_users.txt"
#         with open(skipped_users_file, "w", encoding="utf-8") as file:
#             for line in skipped_users:
#                 file.write(line + "\n")

#         # Remove temp file after processing
#         os.remove(temp_file_path)
#         # print(f"Successfully processed {len(new_users)} new users.")

#     except Exception as e:
#         print(f"Error processing file: {e}")
# nn

def process_file_in_background_with_excel_from_kwara(filepath):
    wb = load_workbook(filepath)
    sheet = wb.active
    
    new_users = []
    skipped_users = []  # Store users skipped due to errors during saving

    for row in sheet.iter_rows(min_row=6, values_only=True):  # Start from row 6
        member_id = str(row[0]).strip() if row[0] else None  # ID
        name = row[1].strip() if row[1] else None  # Name
        phone_number = str(row[2]).strip() if row[2] else None  # Phone (No normalization)
        national_id = str(row[3]).strip() if row[3] else None  # National ID
        status = row[4].strip() if row[4] else "INACTIVE"  # Status (default to INACTIVE)

        # Check if user already exists and skip them (but do NOT add to skipped_users.txt)
        if CustomUser.objects.filter(sacco_user_id=member_id).exists():
            # skipped_users.append(f"Skipping existing user ID: {member_id}")
            print(f"Skipping existing user ID: {member_id}")
            continue

        user = CustomUser(
            sacco_user_id=member_id,
            name=name,
            phone=phone_number,
            id_number=national_id,
            kwara_active=True if status == "ACTIVE" else False,
            source="Kwara",
        )

        # Save each user inside a separate transaction
        try:
            with transaction.atomic():  # Wrap each save operation in a separate transaction
                user.save()
                new_users.append(user)  # Only add successful saves
        except IntegrityError as e:
            skipped_users.append(f"{user.sacco_user_id} - {user.name} - {user.phone} - {user.id_number} - {e}")
            print(f"❌ Error saving user {user.sacco_user_id}: {e}")

    print(f"✅ Successfully added {len(new_users)} new users.")

    # Save skipped users to a file
    if skipped_users:
        skipped_file_path = os.path.join(os.path.dirname(filepath), "skipped_users.txt")
        with open(skipped_file_path, "w", encoding="utf-8") as f:
            f.write("Skipped Users (Errors During Save)\n")
            f.write("====================================\n")
            for user in skipped_users:
                f.write(user + "\n")
        print(f"📄 Skipped users saved to: {skipped_file_path}")
    else:
        print("✅ No users were skipped due to save errors. All users were saved successfully.")

# def chunked_queryset(iterable, chunk_size=500):
#     """Yield successive n-sized chunks from an iterable."""
#     for i in range(0, len(iterable), chunk_size):
#         yield iterable[i:i + chunk_size]


# def process_file_in_background(temp_file_path):
#     """
#     Extracts member details from the Excel sheet, prints all member_ids, 
#     and checks which members were not saved in the database.
#     """
#     try:
        
#         print("🚀 Starting Excel file processing...")
#         # Load the Excel workbook and sheet
#         workbook = load_workbook(temp_file_path)
#         sheet = workbook.active

#         # Extract member IDs from each row
#         all_member_ids = set()  # Store all member_ids from Excel
#         new_users = []  # Store new users for creation
#         skipped_users = []  # Store already existing users
#         duplicate_phones = set()  # Track duplicate phone numbers
        
#         for row in sheet.iter_rows(min_row=2, values_only=True):  # Start from row 2
#             member_id = row[4]  # fifth column contains the member ID
#             phone_number = row[6]  # Sixth column contains phone number

#             if not member_id:  # Ensure member_id is present
#                 print("⚠️ Skipping row with missing member ID.")
#                 continue

#             all_member_ids.add(member_id)  # Collect member_id

#             # Check if phone number already exists in DB
#             if CustomUser.objects.filter(phone=phone_number).exists():
#                 print(f"⚠️ Skipping user {member_id} - Phone number already exists: {phone_number}")
#                 skipped_users.append(member_id)
#                 continue

#             # Prevent duplicate phone numbers in the same file
#             if phone_number in duplicate_phones:
#                 print(f"⚠️ Skipping user {member_id} - Duplicate phone number in file: {phone_number}")
#                 skipped_users.append(member_id)
#                 continue
#             duplicate_phones.add(phone_number)  # Mark this phone as used

#             new_users.append(
#                 CustomUser(
#                     sacco_user_id=member_id,
#                     date_of_birth=row[3],
#                     name=row[5],
#                     phone=phone_number,
#                     email=row[7],
#                     kwara_active=True if row[8] == "Active" else False,
#                     physical_address=row[9],
#                     employer=row[10],
#                     gender=row[18],
#                     notes="Individual Member",
#                 )
#             )

#         print(f"✅ Total unique member IDs extracted: {len(all_member_ids)}")

#             # # Check if user exists
#             # if CustomUser.objects.filter(sacco_user_id=member_id).exists():
#             #     skipped_users.append(member_id)
#             #     print(f"Skipping existing user ID: {member_id}")
#             #     continue
            
#             # # Collect user data for creation
#             # new_users.append({
#             #     "sacco_user_id": member_id,
#             #     "date_of_birth" : row[3],
#             #     # add more details here
#             #     "name": row[5],
#             #     "phone": row[6],
#             #     "email": row[7],
#             #     # "id_number": row[3],
#             #     "kwara_active": True if row[8] == "Active" else False,
#             #     "physical_address": row[9],
#             #     "employer": row[10],
#             #     "gender": row[18],
#             # })

#         # Print all member IDs from Excel
#         # print("\nAll Member IDs from Excel:")
#         # print(all_member_ids)

#         # Break down queries to avoid "too many SQL variables" error
#         existing_ids = set()
#         for chunk in chunked_queryset(list(all_member_ids), 500):
#             existing_ids.update(
#                 CustomUser.objects.filter(sacco_user_id__in=chunk).values_list("sacco_user_id", flat=True)
#             )

#         missing_users = all_member_ids - existing_ids
#         print(f"🛑 Existing users found: {len(existing_ids)}")
#         print(f"🆕 New users to create: {len(missing_users)}")

#         # Track skipped users
#         for user_id in existing_ids:
#             print(f"⚠️ Skipping existing user ID: {user_id}")
#             skipped_users.append(user_id)

#         # Only insert users that don't exist
#         new_users_to_create = [user for user in new_users if user.sacco_user_id in missing_users]

#         if new_users_to_create:
#             with transaction.atomic():
#                 CustomUser.objects.bulk_create(new_users_to_create, batch_size=500)

#             # Set passwords separately because bulk_create doesn't trigger signals
#             for user in CustomUser.objects.filter(sacco_user_id__in=[u.sacco_user_id for u in new_users_to_create]):
#                 user.set_password("12Kagb@#")
#                 user.save()

#         os.remove(temp_file_path)
#         print(f"✅ Successfully processed {len(new_users_to_create)} new users.")
#         print(f"⚠️ Skipped {len(skipped_users)} users due to duplicates or existing records.")

#         # # Find missing users
#         # existing_ids = set(CustomUser.objects.filter(sacco_user_id__in=all_member_ids).values_list('sacco_user_id', flat=True))
#         # missing_users = all_member_ids - existing_ids  # Users not found in DB

#         # # Print missing users
#         # print("\nUsers not saved in the database:")
#         # print(missing_users)

#         # # Save new users
#         # for user_data in new_users:
#         #     try:
#         #         user = CustomUser(**user_data)
#         #         user.set_password("12Kagb@#")  # Set default password
#         #         user.save()
#         #         # don't feel like I'm not writing code bana. I am
#         #         print(f"Saved user: {user.sacco_user_id}")
#         #     except Exception as e:
#         #         print(f"Error saving user {user_data['sacco_user_id']}: {e}")

#         # # Remove temp file after processing
#         # os.remove(temp_file_path)
#         # print(f"Successfully processed {len(new_users)} new users.")

#     except Exception as e:
#         print(f"❌ Error processing file: {e}")


@csrf_exempt
def savings_deposit(request):
    # access_token = get_access_token()
    data = json.loads(request.body)

    savings_id = data.get('savings_id')
    member_id = data.get('member_id')
    fosa = data.get('fosa')
    amount = data.get('amount')
    phone = data.get('phone_number')
    notes = data.get('notes')
    description = f"{notes} to {savings_id}"

    savings_name = data.get("savings_name")

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    # if user_id != member_id and auth_user.role != 'Admin'/:
    # if not (str(user_id) == str(sacco_member_id) == str(form_member)):
    if not (str(user_id)) == str(member_id):
        return JsonResponse({"error": 'permission denied'}, status=403)

    # Fetch the CustomUser instance associated with the member_id
    try:
        user = CustomUser.objects.get(sacco_user_id=member_id)
    except CustomUser.DoesNotExist:
        return JsonResponse({"error": "User not found"}, status=404)
    
    # Convert the amount to a number (integer or float)
    try:
        amount = float(amount)  # or int(amount) if you're sure it's always an integer
    except ValueError:
        return JsonResponse({"error": "Invalid amount format"}, status=400)

    url = "https://api.kwara.com/savings_transactions"

    payload = { "data": { "attributes": {
        "type": "TRANSFER",
        "savings_id": fosa,
        "amount": amount,
        "phone_number": phone,
        "to_savings_account": savings_id,
        "notes": description,
        "manual_journal_entry": True,
    } } }
    headers = {
        "accept": "application/json",
        "Authorization": f"Bearer {access_token}"
    }

    response = requests.post(url, json=payload, headers=headers)

    response_data = response.json()

    formatted_amount = "{:,.0f}".format(amount)

    # Check if the response status code is 201 (Created)
    if response.status_code == 201:
        # Log user activity for viewing savings deposit
        log_user_activity(user, f"Savings Deposit of KES {formatted_amount} from {fosa} to {savings_name}", request.path)
        log_user_transaction(user,"Savings Deposit",f"{response_data['data']['id']}", f"{description}",account_no=savings_id,account_name=savings_name,amount=amount,status="SUCCESS")
    if response.status_code == 422:
        log_user_transaction(user,"Savings Deposit",f"{response_data['data']['id']}", f"{description}",account_no=savings_id,account_name=savings_name,amount=amount,status="FAILED")


    # Handle API error responses
    elif response.status_code == 400:
        error_data = response.json()
        error_details = error_data.get("errors", [])
        if error_details:
            return JsonResponse({"error": error_details[0].get("detail", "An error occurred.")}, status=400)
        log_user_transaction(user,"Savings Deposit",f"{response_data['data']['id']}", f"{description}",account_no=savings_id,account_name=savings_name,amount=amount,status="FAILED")

    return JsonResponse(response.json(), status=response.status_code)

    # # Check if the response status code is 201 (Created)
    # if response.status_code == 201:
    #     # Log user activity for viewing savings deposit
    #     log_user_activity(user, f"Savings Deposit of KES {formatted_amount} from {fosa} to {savings_id}", request.path)
    
    # # Handle API error responses
    # elif response.status_code == 400:
    #     error_data = response.json()
    #     error_details = error_data.get("errors", [])
    #     if error_details:
    #         return JsonResponse({"error": error_details[0].get("detail", "An error occurred.")}, status=400)

    # return JsonResponse(response.json(), status=response.status_code)

# @csrf_exempt
# def savings_withdrawal(request):

#     token = request.headers.get("Authorization")
#     if not token:
#         return JsonResponse({"error": 'Permission denied'}, status=403)

#     auth_response = extract_user(token=token)

#     # Check if the token is invalid
#     if "error" in auth_response:
#         return JsonResponse({"error": auth_response["error"]}, status=401)
#     user_id = auth_response.get("user_id")
    
#     auth_user = CustomUser.objects.get(sacco_user_id=user_id)

#     if user_id != member_id and auth_user.role != 'Admin':
#         return JsonResponse({"error": 'permission denied'}, status=403)

#     url = "https://api.kwara.com/savings_transactions"

#     payload = { "data": { "attributes": {
#         "type": "WITHDRAWAL",
#         "savings_id": "19567311",
#         "amount": 100,
#         "phone_number": "0792908623",
#         # "to_savings_account": "19567311",
#         "to_savings_account": "20040304211",
#         # "to_loan_account": "SC501NNC",
#         "authorization_hold_id": "9fbadd7e-3a9f-4215-85c6-eff64a1c47a5",
#         "bank_branch": "Kayole",
#         "notes": "Trial",
#         "payment_method": "cash",
#         # "reference": "SXB387DBU",
#         "manual_journal_entry": True,
#         "idempotency_key": "9fbadd7e-3a9f-4215-85c6-eff64a1c47a5",
#         # "predefined_fee_name": ""
#     } } }
#     headers = {
#         "accept": "application/json",
#         "Authorization": f"Bearer {access_token}"
#     }

#     response = requests.post(url, json=payload, headers=headers)
#     print("Payload: ", json.dumps(payload, indent=4))
#     print("Response Status Code: ", response.status_code)
#     print("Response Text: ", response.text)

#     return JsonResponse(response.json(), status=response.status_code)

@csrf_exempt
def savings_transfer(request, member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)
    
    if not (str(user_id)) == str(member_id):
        return JsonResponse({"error": 'permission denied'}, status=403)

    # access_token = get_access_token()
    user = CustomUser.objects.get(sacco_user_id=member_id)
    data = json.loads(request.body)
    savings_id = data.get('savings_id')
    amount = data.get('amount')
    phone_number = data.get('phone_number')
    to_savings_account = data.get('acc_number')
    notes = data.get('notes')
    description = f"{notes} to {to_savings_account}"

    url = "https://api.kwara.com/savings_transactions"

    payload = { "data": { "attributes": {
        "type": "TRANSFER",
        "savings_id": savings_id,
        "amount": amount,
        "phone_number": phone_number,
        "to_savings_account": to_savings_account,
        "notes": description,
        "manual_journal_entry": True,
    } } }
    headers = {
        "accept": "application/json",
        "Authorization": f"Bearer {access_token}"
    }

    response = requests.post(url, json=payload, headers=headers)
    response_data = response.json()
    try:
        amount = float(amount)  # or int(amount) if you're sure it's always an integer
    except ValueError:
        return JsonResponse({"error": "Invalid amount format"}, status=400)
    
    formatted_amount = "{:,.0f}".format(amount)

    # Check if the response status code is 201 (Created)
    if response.status_code == 201:
        # Log user activity for successful savings transfer
        log_user_activity(user, f"Savings Transfer of KES {formatted_amount} from {savings_id} to {to_savings_account}", request.path)
        log_user_transaction(user,"Savings Transfer",f"{response_data['data']['id']}", f"{description}",account_no=to_savings_account,amount=amount,status="SUCCESS")

    # Handle API error responses
    if response.status_code == 422:
        log_user_transaction(user,"Savings Transfer",f"{response_data['data']['id']}", f"{description}",account_no=to_savings_account,amount=amount,status="FAILED")

    elif response.status_code == 400:
        error_data = response.json()
        error_details = error_data.get("errors", [])
        if error_details:
            return JsonResponse({"error": error_details[0].get("detail", "An error occurred.")}, status=400)
        log_user_transaction(user,"Savings Transfer",f"{response_data['data']['id']}", f"{description}",account_no=to_savings_account,amount=amount,status="FAILED")

    return JsonResponse(response.json(), status=response.status_code)

    # # Check if the response status code is 201 (Created)
    # if response.status_code == 201:
    #     # Log user activity for successful savings transfer
    #     log_user_activity(user, f"Savings Transfer of KES {formatted_amount} from {savings_id} to {to_savings_account}", request.path)
    
    # # Handle API error responses
    # elif response.status_code == 400:
    #     error_data = response.json()
    #     error_details = error_data.get("errors", [])
    #     if error_details:
    #         return JsonResponse({"error": error_details[0].get("detail", "An error occurred.")}, status=400)

    # return JsonResponse(response.json(), status=response.status_code)


@csrf_exempt
def loan_repayment(request, member_id):

    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if not (str(user_id)) == str(member_id):
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    # access_token = get_access_token()
    user = CustomUser.objects.get(sacco_user_id=member_id)
    data = json.loads(request.body)
    loan_name = data.get("loan_name")
    loan_id = data.get('loan_id')
    amount = data.get('amount')
    savings_id = data.get('savings_id')
    notes = data.get('notes')
    description = f"{notes} to {loan_name}"

    url = "https://api.kwara.com/savings_transactions"

    payload = { "data": { "attributes": {
        "type": "TRANSFER",
        "savings_id": savings_id,
        "amount": amount,
        "to_loan_account": loan_id,
        "notes": description,
        "manual_journal_entry": True,
    } } }
    headers = {
        "accept": "application/json",
        "Authorization": f"Bearer {access_token}"
    }

    # Convert the amount to a number (integer or float)
    try:
        amount = float(amount)  # or int(amount) if you're sure it's always an integer
    except ValueError:
        return JsonResponse({"error": "Invalid amount format"}, status=400)
    
    formatted_amount = "{:,.0f}".format(amount)

    response = requests.post(url, json=payload, headers=headers)

    response_data = response.json()

    # Check if the response status code is 201 (Created)
    if response.status_code == 201:
        # Log user activity for viewing loan eligibility
        log_user_activity(user, f"Loan repayment of KES {formatted_amount} from {savings_id} to {loan_name} ", request.path)
        log_user_transaction(user,"Loan Repayment",f"{response_data['data']['id']}",f"{description}",loan_id, loan_name, amount,status="SUCCESS")
    else:
        log_user_transaction(user,"Loan Repayment",f"{response_data['data']['id']}",f"{description}",loan_id, loan_name, amount,status="FAILED")


    # print(response.text)
    return JsonResponse(response.json(), status=response.status_code)

    # # Check if the response status code is 201 (Created)
    # if response.status_code == 201:
    #     # Log user activity for viewing loan eligibility
    #     log_user_activity(user, f"Loan repayment of KES {formatted_amount} from {savings_id} to {loan_id} ", request.path)

    # # print(response.text)
    # return JsonResponse(response.json(), status=response.status_code)

@csrf_exempt
def token_na_mpesa(request):
    try:

        access_token = generate_access_token()

        api_url = 'https://sandbox.safaricom.co.ke/mpesa/b2b/v1/paymentrequest'

        headers = {
            'Authorization': f'Bearer {access_token}',
            'Content-Type': 'application/json'
        }

        business_shortCode = 174379
        # formatted_time = get_timestamp()
        # decoded_password = generate_password()
        # access_token = generate_access_token()

        payload = {
            "Initiator": 'Packline_Systems',
            "SecurityCredential": "ToVfosfH3sb2b/yiK1H555Lzf9t4m8BImJ/cSGomKgffoo6558+ah1pxhpkI1DzG+TH6jBfn49JpEU8Hrra86hJSSxm1B41ABY3MuZOht6/ro55drvRYqT4PTRBsGiOlHU8DlwCNQl7+GSB38rILuBEA3QziK4WdVX+nVkqcPLhyvYPCHGnzYlFJHoFWD4+DQ/67EIzi2H+SQRmg+6o/+w0YDXWkqS7N/qJO9NNEbUaJlSRBE6ddQJSOe2hvX/j/ZcawKFXwCyI1kgPwxgOvilwfaSzhx8kyrLWTffoBo/50QuPhs0XYSnmwrGl2dMAaGnFDtv8MJUsjUgG/k05MeQ==",
            "CommandID": "BusinessPayBill",
            "SenderIdentifierType": "4",
            "RecieverIdentifierType": "4",
            "Amount": "100",
            "PartyA": "4137281",
            "PartyB": "888880",
            "AccountReference": "37231995236",
            "Requester": "254745171342",
            "Remarks": "ok",
            "QueueTimeOutURL": "https://alutamax.com/ResultsListener.php",
            "ResultURL": "https://alutamax.com/TimeOutListener.php"
        }

        response = requests.post(api_url, json=payload, headers=headers)
        response_data = response.json()
        # print(response_data)
        return JsonResponse(response_data, status=response.status_code)

    except Exception as e:
        # print(f"Error: {e}")
        return JsonResponse({'error': str(e)}, status=500)


        # api_url = "https://sandbox.safaricom.co.ke/mpesa/b2b/v1/paymentrequest"

        # mpesa_request = {
        #     "Initiator":"Packline_Systems",
        #     "SecurityCredential": decoded_password,
        #     "Command ID": "BusinessPayBill",
        #     "SenderIdentifierType": "4",
        #     "RecieverIdentifierType":"4",
        #     "Amount":"100",
        #     "PartyA": business_shortCode,
        #     "PartyB":"888880",
        #     "AccountReference":"37231995236",
        #     "Requester":"254724265242",
        #     "Remarks":"OK",
        #     "QueueTimeOutURL":"http://127.0.0.1:8000/api/callback",
        #     "ResultURL":"http://127.0.0.1:8000/api/callback",
        # }

        # try:
        #     response = requests.post(api_url, json=mpesa_request, headers=headers)
        #     response_data = response.json()
        #     if response.status_code == 200:
        #         return JsonResponse(response_data, status=200)
        #     else:
        #         return JsonResponse(response_data, status=response.status_code)
        # except requests.exceptions.RequestException as e:
        #     return JsonResponse({'error': str(e)}, status=500)
    # else:
    #     return JsonResponse({'error': 'Invalid request method'}, status=405)


@csrf_exempt
def mpesa(request):

    try:
        business_shortCode = 174379
        formatted_time = get_timestamp()
        decoded_password = generate_password()
        access_token = generate_access_token()

        api_url = 'https://sandbox.safaricom.co.ke/mpesa/stkpush/v1/processrequest'

        headers = {
            'Authorization': f'Bearer {access_token}',
            'Content-Type': 'application/json'
        }

        payload = {
            'BusinessShortCode': str(business_shortCode),
            'Password': decoded_password,
            'Timestamp': formatted_time,
            'TransactionType': 'CustomerPayBillOnline',
            'Amount': str(100),
            'PartyA': str(254724265242),  # Ensure it's a string
            'PartyB': "888880",  # Ensure it's a string and correct paybill number
            'PhoneNumber': str(254724265242),  # Ensure it's a string
            'CallBackURL': "https://mydomain.com/b2b/queue/",
            'AccountReference': "37231995236",
            'TransactionDesc': "transaction_desc"
        }

        response = requests.post(api_url, json=payload, headers=headers)
        response_data = response.json()
        # print(response_data)
        return JsonResponse(response_data, status=response.status_code)

    except Exception as e:
        # print(f"Error: {e}")
        return JsonResponse({'error': str(e)}, status=500)

# @csrf_exempt
# def test_loan_repayment(request):
#     # access_token = get_access_token()
#     # data = json.loads(request.body)

#     # loan_id = data.get('loan_id')
#     # amount = data.get('amount')
#     # phone_number = data.get('phone_number')
#     # bank_branch = data.get('bank_branch')
#     # notes = data.get('notes')
#     # payment_method = data.get('payment_method')
#     # reference = data.get('reference')

#     url = "https://api.kwara.com/loan_transactions"

#     payload = { "data": { "attributes": {
#         "type": "REPAYMENT",
#         "loan_id": "DE082579",
#         "amount": 3000,
#         # "phone_number": phone_number,
#         # "bank_branch": bank_branch,
#         # "notes": notes,
#         # "payment_method": payment_method,
#         # "reference": reference,
#         "manual_journal_entry": True
#     } } }
#     headers = {
#         "accept": "application/json",
#         "Authorization": f"Bearer {access_token}"
#     }

#     response = requests.post(url, json=payload, headers=headers)

#     print(response.text)
#     return JsonResponse(response.json(), status=response.status_code)

@csrf_exempt
def checkout_paypal(request):

    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    if request.method == 'POST':
        data = json.loads(request.body)
        amount = data.get('amount')
        member_id = data.get("sacco_member_id")

        if not amount:
            return HttpResponseBadRequest("Amount is required")
        
        invoice_id = str(uuid.uuid4())

        PaypalDeposit.objects.create(
            member=member_id,
            status= "Pending",
            amount=amount,
            invoice=invoice_id,
        )

        host = request.get_host()
        paypal_checkout = {
            'business': settings.PAYPAL_RECEIVER_EMAIL,
            'amount': amount,
            'item_name': "Deposit",
            'invoice': invoice_id,
            'currency': 'KES',
            'notify_url': f"https://{host}{reverse('paypal-ipn')}",
            'return_url': f"https://{host}{reverse('paypal-payment-success')}",
            'cancel_url': f"https://{host}{reverse('paypal-payment-fail')}",
            'cmd': '_xclick',
        }

        base_url = "https://www.sandbox.paypal.com/cgi-bin/webscr" if settings.PAYPAL_TEST else "https://www.paypal.com/cgi-bin/webscr"
        query_string = urlencode(paypal_checkout)
        paypal_url = f"{base_url}?{query_string}"

        return JsonResponse({'paypal_url': paypal_url})
    return HttpResponseBadRequest("Invalid request method")

def payment_successfull(request):
    return HttpResponse("Payment Successful")

def payment_failed(request):
    return HttpResponse("Payment Failed")

def return_auth_token():
    client_id = settings.STANBIC_CLIENT_ID
    client_secret = settings.STANBIC_CLIENT_SECRET
    token_url = settings.STANBIC_TOKEN_URL
    scope = settings.STANBIC_SCOPE

    payload = {
    'grant_type': 'client_credentials',
    'client_id': client_id,
    'client_secret': client_secret,
    'scope': scope
    }
    response = requests.post(token_url,data=payload)
    access_token = response.json().get("access_token")
    # print(access_token)
    return access_token

@csrf_exempt
def swift_payment(request):
  
  """
    Handles SWIFT payment processing via Stanbic Bank's API.

    This function processes a POST request to initiate a SWIFT payment by sending a request
    to the Stanbic Bank sandbox API. It collects payment details from the request, constructs
    a payload, and makes an API call to the SWIFT endpoint.

    Parameters:
    - request (HttpRequest): The HTTP request object, expected to be a POST request with the
      following form data:
        - from_account: The originator's bank account number.
        - to_account: The recipient's bank account number.
        - phone: The phone number of the originator.
        - from_bank: The originator's bank code.
        - to_bank: The recipient's bank code.
        - amount: The amount to be transferred.
        - reason: The reason for the transfer.

    Returns:
    - JsonResponse: If the request method is POST, returns the JSON response from the Stanbic
      Bank API.
    - HttpResponse: If the request method is not POST, renders the "swift_acccount_to_account.html" template.

    API Details:
    - Endpoint: https://api.connect.stanbicbank.co.ke/api/sandbox/swift-payments/
    - Authorization: Bearer token obtained from return_auth_token()
    - Payload:
        - originatorAccount: Contains the account and mobile number of the originator.
        - requestedExecutionDate: Static date set to "2024-08-09".
        - dbsReferenceId: Randomly generated 6-digit reference ID.
        - txnNarrative: Static value "TESEAPS123".
        - callBackUrl: Static callback URL "https://clientdomain.com/client/Callback".
        - schedule: Contains scheduling information such as transfer frequency and date range.
        - transferTransactionInformation: Contains details about the amount, counterparty
          account, counterparty identity, and remittance information.

    Example Usage:
    - Sending a POST request with the necessary form data to initiate a SWIFT payment.
    """
  
  token = request.headers.get("Authorization")
  member_id = request.headers.get("Member-ID")
  if not token:
    return JsonResponse({"error": 'Permission denied'}, status=403)
  
  auth_response = extract_user(token=token)
  # Check if the token is invalid
  if "error" in auth_response:
    return JsonResponse({"error": auth_response["error"]}, status=401)
  user_id = auth_response.get("user_id")
  auth_user = CustomUser.objects.get(sacco_user_id=user_id)
  if user_id != member_id and auth_user.role != 'Admin':
    return JsonResponse({"error": 'permission denied'}, status=403)
  
  from .models import WithdrawRequest

  if request.method == "POST":
            try:
                data = json.loads(request.body)
                # You can add more validation or processing of the data here if needed

                # Call the create_withdraw_request method
                response = WithdrawRequest.create_swift_withdraw_request(data)
                return response
            except json.JSONDecodeError:
                return JsonResponse({"error": "Invalid JSON data"}, status=400)
  else:
            return JsonResponse({"error": "Invalid request method"}, status=405)

#   if request.method == "POST":
#     access_token = return_auth_token()
#     data = json.loads(request.body)
#     amount = data.get('amount')
#     url = "https://api.connect.stanbicbank.co.ke/api/sandbox/swift-payments/"
#     headers = {
#       "Authorization": f"Bearer {access_token}",
#       "content-type": "application/json",
#       "accept": "application/json"
#     }

#     from_account = settings.KBS_FROM_ACCOUNT
#     phone = settings.KBS_FROM_PHONE

#     # from_account = request.POST.get("from_account")
#     to_account = data.get("to_account")
#     # phone = request.POST.get("phone")
#     # from_bank = request.POST.get("from_bank")
#     from_bank = "SBICKENX"
#     to_bank = data.get("to_bank")
#     amount = data.get("amount")
#     # reason = request.POST.get("reason")
#     creditCurrency = data.get("creditCurrency")
#     if not all([to_account, to_bank, amount, creditCurrency]):
#         return JsonResponse({"error": "Missing required fields"}, status=400)
#     payload = {
#     "originatorAccount": {
#       "identification": {
#         "identification": from_account,
#         "debitCurrency": "KES",
#         "mobileNumber": phone
#       }
#     },
#     "requestedExecutionDate": "2024-08-09",
#     "dbsReferenceId": str(random.randrange(100000, 1000000)),
#     "txnNarrative": "TESEAPS123",
#     "callBackUrl": "https://clientdomain.com/client/Callback",
#     "schedule": {
#       "transferFrequency": "DAILY",
#       "on": "12",
#       "startDate": "2021-02-13",
#       "endDate": "2022-01-03",
#       "repeat": "3",
#       "every": "1"
#     },
#     # 1220179020894 0100013845845
#     "transferTransactionInformation": {
#       "instructedAmount": {
#         "amount": amount,
#         "creditCurrency": creditCurrency
#       },
#       "counterpartyAccount": {
#         "identification": {
#           "identification": to_account,
#           "correspondentBank": from_bank,
#           "beneficiaryBank": to_bank
#         }
#         },
#         "counterparty": {
#           "name": "TAAM OIL LTD",
#           "postalAddress": {
#             "addressLine": "UGANDA",
#             "postCode": "1100 ZZ",
#             "town": "Kampala",
#             "country": "UG"
#           }
#         },
#         "remittanceInformation": {
#           "type": "deposit",
#           "content": "deposit"
#         },
#         "endToEndIdentification": "5e1a3da132cc"
#       }
#     }

#     response = requests.post(url=url,headers=headers,json=payload)
#     # print("response "+response)
#     # print(payload)
#     return JsonResponse(response.json())
#   else:
#     return JsonResponse({"Error": "Invalid request method"})

def get_date(self):
    current_date = date.today()
    formatted_day = current_date.isoformat()
    # print(formatted_day)
    return formatted_day

from .models import PaypalPayout
@csrf_exempt
def payout_paypal(request):

    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    if request.method == "POST":
        data = json.loads(request.body)
        amount = data.get('amount')
        receiver_email = data.get('email')
        member_id = data.get("sacco_member_id")

        fosa_balance = helper_return_fosa_balance(sacco_member_id=member_id)
        # fosa_account = helper_return_fosa_account(sacco_member_id=member_id)

        if int(amount) > int(fosa_balance):
            return JsonResponse({"error": "not enough balance"})


        paypalrestsdk.configure({
            "mode": settings.PAYPAL_MODE,
            "client_id": settings.PAYPAL_CLIENT_ID,
            "client_secret": settings.PAYPAL_SECRET
        })
        payout = paypalrestsdk.Payout({
            "sender_batch_header": {
                "sender_batch_id": str(uuid.uuid4()),
                "email_subject": "You have a payout!",
            },
            "items": [
                {
                    "recipient_type": "EMAIL",
                    "amount": {
                        "value": amount,  # Amount to send
                        "currency": "USD"
                    },
                    "receiver": receiver_email,  # User's PayPal email
                    "note": "Thank you for using our service!",
                    "sender_item_id": str(uuid.uuid4())
                }
            ]
        })
        if payout.create():
            payout_batch_id = payout.batch_header.payout_batch_id
            batch_status = payout.batch_header.batch_status
            receiver_email = payout.items[0].receiver
            amount_sent = payout.items[0].amount['value']
            currency_sent = payout.items[0].amount['currency']

            PaypalPayout.objects.create(
                payout_id = payout_batch_id,
                status = batch_status,
                receiver = receiver_email,
                amount_sent = amount_sent,
                currency_sent = currency_sent
            )
            check_paypal_payout_and_withdraw(payout_id=payout_batch_id,member_id=member_id, amount=amount)

            # withdraw from FOSA here
            return JsonResponse({"status": "success", "payout_batch_id": payout.batch_header.payout_batch_id})
        else:
                return JsonResponse({"status": "failure", "error": payout.error})

    else:
        return JsonResponse({"Error": "Invalid request method"})

def get_paypal_access_token():
    """
    This function gets the OAuth 2.0 access token from PayPal.
    """
    auth_url = "https://api.sandbox.paypal.com/v1/oauth2/token"
    headers = {
        "Accept": "application/json",
        "Accept-Language": "en_US",
    }
    # Client ID and Secret from settings
    client_id = settings.PAYPAL_CLIENT_ID
    client_secret = settings.PAYPAL_SECRET
    auth = (client_id, client_secret)

    # Data to get access token
    data = {
        "grant_type": "client_credentials"
    }

    # Send request to get access token
    response = requests.post(auth_url, headers=headers, data=data, auth=auth)

    # Check if the request was successful
    if response.status_code == 200:
        access_token = response.json().get("access_token")
        return access_token
    else:
        raise Exception(f"Failed to get access token: {response.status_code} - {response.text}")

@csrf_exempt
def check_paypal_payout_status(request, payout_id):
    """
    This function checks the status of a payout using the PayPal API.
    """
    # Get access token
    access_token = get_paypal_access_token()

    # Payouts API URL
    payout_url = f"https://api.sandbox.paypal.com/v1/payments/payouts/{payout_id}"

    # Headers with authorization token
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {access_token}"
    }

    # Send request to get payout status
    response = requests.get(payout_url, headers=headers)
    return JsonResponse(response.json())

def check_paypal_payout_and_withdraw(member_id, payout_id,amount):
    """
    This function checks the status of a payout using the PayPal API.
    """
    # Get access token
    access_token = get_paypal_access_token()

    # Payouts API URL
    payout_url = f"https://api.sandbox.paypal.com/v1/payments/payouts/{payout_id}"

    # Headers with authorization token
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {access_token}"
    }

    # Send request to get payout status
    response = requests.get(payout_url, headers=headers)
    # return JsonResponse(response.json())
        # Check if the response is successful
    if response.status_code == 200:
        payout_data = response.json()

        # Check if the payout batch status is "SUCCESS"
        batch_status = payout_data.get("batch_header", {}).get("batch_status")

        if batch_status == "SUCCESS":
            payout_record = PaypalPayout.objects.get(payout_id=payout_id)
            payout_record.status = "SUCCESS"
            payout_record.save()  # Save the updated status to the database
            fosa_account = helper_return_fosa_account(sacco_member_id=member_id)
            if isinstance(fosa_account, tuple):
                fosa_account_no = fosa_account[0]
            WithdrawRequest.objects.create(
                    member_sacco_id=member_id,
                    amount=amount,
                    payment_method="paypal",
                    request_response="SUCCESS"
                )
            helper_fosa_withdrawal(amount=amount,sacco_member_id=member_id,fosa_account=fosa_account_no)

            return JsonResponse({
                "status": "success",
                "message": "Payout was successful.",
                "payout_details": payout_data  # Return payout details if needed
            })

        else:
            # Payout is not successful
            return JsonResponse({
                "status": "failed",
                "message": f"Payout status is {batch_status}."
            })
    else:
        # Handle request failure
        return JsonResponse({
            "status": "error",
            "message": "Failed to retrieve payout status from PayPal.",
            "error_details": response.text
        })



@csrf_exempt
def checkout_paypal_restsdk(request):
    # if request.method == 'POST':
    #     data = json.loads(request.body)
    #     amount = data.get('amount')

        # if not amount:
        #     return HttpResponseBadRequest("Amount is required")

        # Configure PayPal SDK
        paypalrestsdk.configure({
            "mode": settings.PAYPAL_MODE,  # 'sandbox' or 'live'
            "client_id": settings.PAYPAL_CLIENT_ID,
            "client_secret": settings.PAYPAL_SECRET
        })

        # Create payment
        payment = paypalrestsdk.Payment({
            "intent": "sale",  # or 'authorize' for authorization
            "payer": {
                "payment_method": "paypal"
            },
            "transactions": [{
                "amount": {
                    "total": 43,
                    "currency": "USD"
                },
                "description": "Deposit"
            }],
            "redirect_urls": {
                "return_url": f"http://{request.get_host()}{reverse('paypal-payment-success')}",
                "cancel_url": f"http://{request.get_host()}{reverse('paypal-payment-fail')}"
            }
        })

        if payment.create():
            # Redirect the user to PayPal to approve the payment
            for link in payment['links']:
                if link['rel'] == 'approval_url':
                    approval_url = link['href']
                    return HttpResponseRedirect(approval_url)
            return HttpResponseBadRequest("Approval URL not found.")
        else:
            return JsonResponse({"status": "failure", "error": payment.error})

    # return HttpResponseBadRequest("Invalid request method")

# @csrf_exempt
# def pay_customer_mpesa(request):

#     token = request.headers.get("Authorization")
#     member_id = request.headers.get("Member-ID")
#     if not token:
#         return JsonResponse({"error": 'Permission denied'}, status=403)

#     auth_response = extract_user(token=token)

#     # Check if the token is invalid
#     if "error" in auth_response:
#         return JsonResponse({"error": auth_response["error"]}, status=401)
#     user_id = auth_response.get("user_id")
    
#     auth_user = CustomUser.objects.get(sacco_user_id=user_id)

#     if user_id != member_id and auth_user.role != 'Admin':
#         return JsonResponse({"error": 'permission denied'}, status=403)

#     from .models import WithdrawRequest

#     if request.method == "POST":
#             try:
#                 data = json.loads(request.body)
#                 # You can add more validation or processing of the data here if needed

#                 # Call the create_withdraw_request method
#                 response = WithdrawRequest.mpesa_withdraw_request(data)
#                 return response
#             except json.JSONDecodeError:
#                 return JsonResponse({"error": "Invalid JSON data"}, status=400)
#     else:
#             return JsonResponse({"error": "Invalid request method"}, status=405)

@csrf_exempt
def pay_customer_mpesa(request, sacco_member_id):
    data = json.loads(request.body)
    form_member = data.get("sacco_member_id")
    
    token = request.headers.get("Authorization")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")

    # if user_id != sacco_member_id:
    #     return JsonResponse({"error": 'permission denied'}, status=403)
    
    if str(user_id) != str(sacco_member_id) != str(form_member):
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)
    
    if request.method == "POST":
            try:
                # You can add more validation or processing of the data here if needed

                # Call the create_withdraw_request method
                response = WithdrawRequest.mpesa_withdraw_request(data)
                payment_status = "SUCCESSFUL" if response.status_code == 200 else "FAILED" if response.status_code == 400 else " "
                log_user_activity(auth_user, f"Mpesa FOSA Withdrawal of KES {data.get('amount')} to {data.get('mpesa_number')}. {payment_status}", request.path)
                return response
            except json.JSONDecodeError:
                return JsonResponse({"error": "Invalid JSON data"}, status=400)
            except Exception as e:  # Catch unexpected errors
                # print(f'error {e}')
                return JsonResponse({"error": str(e)}, status=500)
    else:
            return JsonResponse({"error": "Invalid request method"}, status=405)

@csrf_exempt
def pay_bill(request):
    print("Running")
    # data = json.loads(request.body)
    amount = 10
    phone_number = "254792009556"
    # M-Pesa credentials and environment setup
    env = "sandbox"
    app_key = "SE0XXGYedB9EGpSUwmqXZpU8S4GGAxtE5CBAS0CzH2PMGTer"
    app_secret = "FYuKxMJ75xaruVqWXqG5lNiLy508SwEmTNk3A8zZqDjeCtPnYXBwK8MvyPQAvkD9"
    business_shortcode = "174379"  # Replace with your Business Shortcode
    passcode = "nteSGPPHrFIJDB9PC+P3og1GuQROO1sxGzUwAJEhUArukeMiVjAF6D0Gwwei8gwpisAEk9ZjfJSM6E2J21AVUYizdmxtTxwM3B+d7xTOTSFwYpHedH74O99lgrhQcVv+ajUiTVCI79q0Iewk0B01RGBL19dtkLPZcA3PdgP0TFG2f0n6CdWAf4Ep5f2MUk7QLlu7tJINRK5Uffzn1xpxoo/r4yFslC5HSpLVwMSa0S2RHiahs4z2jzzfO40JzYbe/lZBcujkoDtrkpRdvfyOOcjFgM9fyZz6ad8rYKwHTxIAiq0Gs6yXQ5kiXyWoIAck6n++t2lyAe5xCJTr6LUVaQ=="  # Replace with your passcode
    callback_url = "https://mydomain.com/callback"  # Replace with your callback URL
    reference_code = "your_reference_code"  # Replace with your reference code
    description = "Payment for services"
    # Create an instance of MpesaExpress
    # mpesa = MpesaExpress(env=env, app_key=app_key, app_secret=app_secret)
    # # Make the payment request using stk_push
    # response = mpesa.stk_push(
    #     business_shortcode=business_shortcode,
    #     passcode=passcode,
    #     amount=amount,
    #     callback_url=callback_url,
    #     reference_code=reference_code,
    #     phone_number=phone_number,
    #     description=description
    # )
    response = {"success": "Here we are"}
    # Return the response as JSON
    return JsonResponse(response)

@csrf_exempt
def customer_pay_bill(request):

    token = request.headers.get("Authorization")
    member_id = request.headers.get("Member-ID")
    if not token:
        return JsonResponse({"error": 'Permission denied'}, status=403)

    auth_response = extract_user(token=token)

    # Check if the token is invalid
    if "error" in auth_response:
        return JsonResponse({"error": auth_response["error"]}, status=401)
    user_id = auth_response.get("user_id")
    
    auth_user = CustomUser.objects.get(sacco_user_id=user_id)

    if user_id != member_id and auth_user.role != 'Admin':
        return JsonResponse({"error": 'permission denied'}, status=403)
    
    if request.method == "POST":
        data = json.loads(request.body)
        amount = data.get('amount')
        phone = data.get('phone')
        account_number = str(data.get('account_number'))
        if phone.startswith('0'):
                # Replace the leading '0' with '254'
                formatted_phone = '254' + phone[1:]
        else:
                # If it doesn't start with '0', keep it unchanged or handle accordingly
                formatted_phone = phone
        cl = MpesaClient()
        # print("phone "+formatted_phone)
        phone_number = formatted_phone
        amount = int(amount)
        account_reference = account_number
        transaction_desc = 'paybill'
        callback_url = "https://kbs-internet-banking.com/api/callback"
        response = cl.stk_push(phone_number, amount, account_reference, transaction_desc, callback_url)
        response_data = response.json()
        if response_data.get('ResponseCode') == '0':
            Payment.objects.create(
                merchant_request_id=response_data.get('MerchantRequestID'),
                checkout_request_id=response_data.get('CheckoutRequestID'),
                response_code=response_data.get('ResponseCode'),
                response_description=response_data.get('ResponseDescription'),
                customer_message=response_data.get('CustomerMessage'),
                amount=amount,
                phone_number=phone_number,
                account_reference=account_reference
            )
        return HttpResponse(response)
    else:
        return JsonResponse({"Error": "Invalid request method"})
    
@csrf_exempt
def customer_pay_joining_fee(request):
    if request.method == "POST":
        data = json.loads(request.body)
        amount = data.get('amount')
        phone = data.get('phone')
        account_number = str(data.get('phone'))
        if phone.startswith('0'):
                # Replace the leading '0' with '254'
                formatted_phone = '254' + phone[1:]
        else:
                # If it doesn't start with '0', keep it unchanged or handle accordingly
                formatted_phone = phone
        cl = MpesaClient()
        # print("phone "+formatted_phone)
        phone_number = formatted_phone
        amount = int(amount)
        account_reference = account_number
        transaction_desc = 'paybill'
        callback_url = "https://backend.kbs-internet-banking.net/api/payment_callback_mpesa"
        response = cl.stk_push(phone_number, amount, account_reference, transaction_desc, callback_url)
        response_data = response.json()
        if response_data.get('ResponseCode') == '0':
            Payment.objects.create(
                merchant_request_id=response_data.get('MerchantRequestID'),
                checkout_request_id=response_data.get('CheckoutRequestID'),
                response_code=response_data.get('ResponseCode'),
                response_description=response_data.get('ResponseDescription'),
                customer_message=response_data.get('CustomerMessage'),
                amount=amount,
                phone_number=phone_number,
                account_reference=account_reference
            )
        return HttpResponse(response)
    else:
        return JsonResponse({"Error": "Invalid request method"})
    
@csrf_exempt
def customer_deposit_to_fosa(request):
    try:
        token = request.headers.get("Authorization")
        member_id = request.headers.get("Member-ID")
        if not token:
            return JsonResponse({"error": 'Permission denied'}, status=403)

        auth_response = extract_user(token=token)

        # Check if the token is invalid
        if "error" in auth_response:
            return JsonResponse({"error": auth_response["error"]}, status=401)
        user_id = auth_response.get("user_id")
        
        auth_user = CustomUser.objects.get(sacco_user_id=user_id)

        if user_id != member_id and auth_user.role != 'Admin':
            return JsonResponse({"error": 'permission denied'}, status=403)
        
        data = json.loads(request.body)
        amount = data.get('amount')
        phone = data.get('phone')
        sacco_member_id = data.get('sacco_member_id')
        account_number = account_number = helper_return_fosa_account(sacco_member_id=f"{sacco_member_id}")
        if phone.startswith('0'):
                formatted_phone = '254' + phone[1:]
        else:
                formatted_phone = phone
        # print("phone "+formatted_phone)
        phone_number = formatted_phone
        amount = int(amount)
        account_reference = account_number
        transaction_desc = 'Deposit to FOSA'
        callback_url = "https://backend.kbs-internet-banking.net/api/payment_callback_mpesa"
        # Send STK Push
        mpesa_access_token = generate_kbs_mpesa_live_access_token()
        timestamp = datetime.now().strftime('%Y%m%d%H%M%S')

        stk_password = base64.b64encode(("400444" + "8b8cefc5ffee270b3831aeaf4378df5181f92c487149e5b2acd37b3ec1295a26" + timestamp).encode('ascii')).decode('utf-8') 

        stk_payload = {
            "BusinessShortCode": 400444,
            "Password":  stk_password,
            "Timestamp": timestamp,
            "TransactionType": "CustomerPayBillOnline",
            "Amount": amount,
            "PartyA": phone_number,
            "PartyB": 400444,
            "PhoneNumber": phone_number,
            "CallBackURL": callback_url,
            "AccountReference": account_reference,
            "TransactionDesc": transaction_desc,
         }

        stk_headers = {
        'Content-Type': 'application/json',
        'Authorization': f'Bearer {mpesa_access_token}'
        }
        response = requests.post(url='https://api.safaricom.co.ke/mpesa/stkpush/v1/processrequest',json=stk_payload, headers=stk_headers)
        # End Send STK Push
        response_data = response.json()
        if response_data.get('ResponseCode') == '0':
            Payment.objects.create(
                member_sacco_id=sacco_member_id,
                merchant_request_id=response_data.get('MerchantRequestID'),
                checkout_request_id=response_data.get('CheckoutRequestID'),
                response_code=response_data.get('ResponseCode'),
                response_description=response_data.get('ResponseDescription'),
                customer_message=response_data.get('CustomerMessage'),
                amount=amount,
                phone_number=phone_number,
                account_reference=account_reference
            )
        return HttpResponse(response)
    except Exception as e:
        return JsonResponse({"Error": f"Invalid request method {e}"})

    
@csrf_exempt
def get_mpesa_reference(request,checkout_id):
    payment = MpesaTransaction.objects.get(checkout_request_id=checkout_id)
    # payment = MpesaTransaction.objects.first()
    return JsonResponse({'reference': payment.mpesa_receipt_number})
    
def generate_stk_query_password(shortcode, passkey, timestamp):
    """
    Function to generate Mpesa password for STK Push Query.
    Password is a Base64 encoded string of BusinessShortCode + Passkey + Timestamp
    """
    data_to_encode = shortcode + passkey + timestamp
    encoded_string = base64.b64encode(data_to_encode.encode())
    return encoded_string.decode('utf-8')
    
# @csrf_exempt
# def stk_push_query_payment(request, checkout_id):

#     # check the stk request to user

#     """
#     returns such a response
#     {
#     "ResponseCode": "0",
#     "ResponseDescription": "The service request has been accepted successsfully",
#     "MerchantRequestID": "feab-4d34-8ffb-457d02cd9bfc35261277",
#     "CheckoutRequestID": "ws_CO_19092024101342214792009556",
#     "ResultCode": "1032",
#     "ResultDesc": "Request cancelled by user"
#     }
#     """
#     # Step 1: Generate Timestamp
#     timestamp = datetime.now().strftime('%Y%m%d%H%M%S')  # Format: YYYYMMDDHHMMSS

#     mpesa_access_token = generate_mpesa_live_access_token()

#     # print(mpesa_access_token)
#     # auth_url = "https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials"

#     # Step 2: Generate Password
#     password = generate_stk_query_password("4137281", "ed834553e4654db24c84b6118a3b4cdaabf5324762e7399f1cb56b9a85e98d10", timestamp)

#     # Step 3: Create the request body
#     request_body = {
#         "BusinessShortCode": "4137281",
#         "Password": password,
#         "Timestamp": timestamp,
#         "CheckoutRequestID": f"{checkout_id}"
#     }

#     # Step 4: Define the endpoint and headers
#     api_url = "https://api.safaricom.co.ke/mpesa/stkpushquery/v1/query"
#     headers = {
#         "Authorization": f"Bearer {mpesa_access_token}",  # Replace with your access token
#         "Content-Type": "application/json"
#     }

#     # Step 5: Send the POST request
#     response = requests.post(api_url, json=request_body, headers=headers)
#     print(response.json())
#     return JsonResponse(response.json())

@csrf_exempt
def stk_push_query_payment(request, checkout_id):
    # Step 1: Generate Timestamp
    timestamp = datetime.now().strftime('%Y%m%d%H%M%S')  # Format: YYYYMMDDHHMMSS

    mpesa_access_token = generate_kbs_mpesa_live_access_token()
    # Step 2: Generate Password
    password = generate_stk_query_password("400444", "8b8cefc5ffee270b3831aeaf4378df5181f92c487149e5b2acd37b3ec1295a26", timestamp)

    # Step 3: Create the request body
    request_body = {
        "BusinessShortCode": "400444",
        "Password": password,
        "Timestamp": timestamp,
        "CheckoutRequestID": f"{checkout_id}"
    }

    # Step 4: Define the endpoint and headers
    api_url = "https://api.safaricom.co.ke/mpesa/stkpushquery/v1/query"
    headers = {
        "Authorization": f"Bearer {mpesa_access_token}",  # Replace with your access token
        "Content-Type": "application/json"
    }

    # Step 5: Send the POST request
    response = requests.post(api_url, json=request_body, headers=headers)
    # print(response.json())
    return JsonResponse(response.json())

@csrf_exempt
def mpesa_callback(request):
    if request.method == 'POST':
        # Parse the JSON data from the request
        try:
            data = json.loads(request.body)
            body = data.get('Body', {})
            stk_callback = body.get('stkCallback', {})

            # Extract top-level fields
            merchant_request_id = stk_callback.get('MerchantRequestID')
            checkout_request_id = stk_callback.get('CheckoutRequestID')
            result_code = stk_callback.get('ResultCode')
            result_desc = stk_callback.get('ResultDesc')

            # Initialize fields with default values
            amount = None
            mpesa_receipt_number = None
            transaction_date = None
            phone_number = None

            # Extract CallbackMetadata items if ResultCode indicates success
            if result_code == 0:
                callback_metadata = stk_callback.get('CallbackMetadata', {}).get('Item', [])

                # Loop through each item to get required values
                for item in callback_metadata:
                    name = item.get('Name')
                    value = item.get('Value')

                    if name == 'Amount':
                        amount = value
                    elif name == 'MpesaReceiptNumber':
                        mpesa_receipt_number = value
                    elif name == 'TransactionDate':
                        transaction_date = value
                    elif name == 'PhoneNumber':
                        phone_number = value

                # Save the transaction details to the database
                MpesaTransaction.objects.create(
                    merchant_request_id=merchant_request_id,
                    checkout_request_id=checkout_request_id,
                    result_code=result_code,
                    result_description=result_desc,
                    amount=amount,
                    mpesa_receipt_number=mpesa_receipt_number,
                    transaction_date=transaction_date,
                    phone_number=phone_number
                )

                # print(f"Transaction successful: {result_desc}")
            else:
                # Handle failed transactions here if needed
                print(f"Transaction failed")

            # Return a 200 OK response to acknowledge receipt
            return JsonResponse({"ResultCode": 0, "ResultDesc": "Callback received successfully"})

        except json.JSONDecodeError:
            return JsonResponse({"ResultCode": 1, "ResultDesc": "Invalid JSON format"})
    else:
        return JsonResponse({"ResultCode": 1, "ResultDesc": "Invalid request method"})


@csrf_exempt
def mpesa_b2c_callback(request):
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            result = data.get("Result", {})

            # Extract required fields
            result_type = result.get("ResultType")
            result_code = result.get("ResultCode")
            result_desc = result.get("ResultDesc")
            originator_conversation_id = result.get("OriginatorConversationID")
            conversation_id = result.get("ConversationID")
            transaction_id = result.get("TransactionID")

            # Extract parameters from ResultParameters if available
            result_parameters = result.get("ResultParameters", {}).get("ResultParameter", [])
            transaction_amount = None
            receiver_party_name = None
            transaction_completed_time = None

            # if result_code != 0:
            #     withdraw_request = WithdrawRequest.objects.get(conversation_id=conversation_id)
            #     if withdraw_request:
            #         response = deposit_to_fosa(sacco_member_id=withdraw_request.member_sacco_id,amount=withdraw_request.amount)
            #         # print(response.json())
            #         # deposit to fosa from here
            #         # pass

            for param in result_parameters:
                if param["Key"] == "TransactionAmount":
                    transaction_amount = param["Value"]
                elif param["Key"] == "ReceiverPartyPublicName":
                    receiver_party_name = param["Value"]
                elif param["Key"] == "TransactionCompletedDateTime":
                    transaction_completed_time = param["Value"]

            # Store the extracted data in the database
            MpesaB2CCallback.objects.create(
                result_type=result_type,
                result_code=result_code,
                result_desc=result_desc,
                originator_conversation_id=originator_conversation_id,
                conversation_id=conversation_id,
                transaction_id=transaction_id,
                transaction_amount=transaction_amount,
                receiver_party_name=receiver_party_name,
                transaction_completed_time=transaction_completed_time
            )

            return JsonResponse({"message": "Callback received successfully"}, status=200)

        except json.JSONDecodeError:
            return JsonResponse({"error": "Invalid JSON"}, status=400)
        except Exception as e:
            return JsonResponse({"error": str(e)}, status=500)

    return JsonResponse({"error": "Invalid request method"}, status=405)

@csrf_exempt
def sms_callback_advanta(request):
    if request.method == 'POST':
        data_received = request.body.decode('utf-8')  # Get the raw POST data
    elif request.method == 'GET':
        data_received = request.GET.dict()  # Get query parameters as a dictionary
    else:
        return HttpResponse("Unsupported request method", status=400)

    msisdn = data_received.get('msisdn')  # Phone number
    message = data_received.get('message')  # User's response

    if not msisdn or not message:
        return HttpResponse("Missing phone number or message", status=400)

    try:
        # Normalize phone number by stripping "+" from guarantor_phone
        # guarantors = Guarantor.objects.all()
        # guarantor = None

        guarantor = Guarantor.objects.filter(
            guarantor_phone__endswith=msisdn,
            approved=False,
            rejected=False
        ).first()

        # If no match found for unapproved/rejected guarantor, check for already approved/rejected
        # If no unapproved guarantor, look for an approved/rejected guarantor with no confirming_id
        if not guarantor:
            guarantor = Guarantor.objects.filter(
                guarantor_phone__endswith=msisdn,
                confirming_id__isnull=True
            ).filter(Q(approved=True) | Q(rejected=True)).first()


        if not guarantor:
            return HttpResponse("No valid guarantee found for this response")

        # Process the message
        if message == "1" and not guarantor.approved and not guarantor.rejected:
            guarantor.approved = True
            guarantor.save()
            helper_send_sms(phone='254720861566', message=f"{guarantor.guarantor_name} has accepted to guarantee {guarantor.product_name} for {guarantor.sender_name}.", department="Loans & Credit")
            helper_send_sms(phone='254721662453', message=f"{guarantor.guarantor_name} has accepted to guarantee {guarantor.product_name} for {guarantor.sender_name}.", department="Loans & Credit")
            helper_send_sms(phone='254722281318', message=f"{guarantor.guarantor_name} has accepted to guarantee {guarantor.product_name} for {guarantor.sender_name}.", department="Loans & Credit")
            helper_send_sms(phone='254727336746', message=f"{guarantor.guarantor_name} has accepted to guarantee {guarantor.product_name} for {guarantor.sender_name}.", department="Loans & Credit")
            helper_send_sms(phone='254790094839', message=f"{guarantor.guarantor_name} has accepted to guarantee {guarantor.product_name} for {guarantor.sender_name}.", department="Business Development")
            send_mail(
                "Kenya Bankers Internet Banking Loan Guarantor Reply",
                f"Kenya Bankers Internet Banking Loan Guarantor Reply",
                settings.DEFAULT_FROM_EMAIL,
                ["retail@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{guarantor.guarantor_name} has accepted to guarantee {guarantor.product_name} for {guarantor.sender_name}.</p>'
            )
            return HttpResponse("As part of the loan guarantor request, please enter your National ID/Passport to validate")
        elif message == "2" and not guarantor.approved and not guarantor.rejected:
            guarantor.rejected = True
            guarantor.save()
            helper_send_sms(phone='254720861566', message=f"{guarantor.guarantor_name} has rejected to guarantee {guarantor.product_name} for {guarantor.sender_name}.", department="Loans & Credit")
            helper_send_sms(phone='254721662453', message=f"{guarantor.guarantor_name} has rejected to guarantee {guarantor.product_name} for {guarantor.sender_name}.", department="Loans & Credit")
            helper_send_sms(phone='254722281318', message=f"{guarantor.guarantor_name} has rejected to guarantee {guarantor.product_name} for {guarantor.sender_name}.", department="Loans & Credit")
            helper_send_sms(phone='254727336746', message=f"{guarantor.guarantor_name} has rejected to guarantee {guarantor.product_name} for {guarantor.sender_name}.", department="Loans & Credit")
            helper_send_sms(phone='254790094839', message=f"{guarantor.guarantor_name} has rejected to guarantee {guarantor.product_name} for {guarantor.sender_name}.", department="Business Development")
            send_mail(
                "Kenya Bankers Internet Banking Loan Guarantor Reply",
                f"Kenya Bankers Internet Banking Loan Guarantor Reply",
                settings.DEFAULT_FROM_EMAIL,
                ["retail@kenyabankers.coop"],  # Make sure user has an email field
                fail_silently=False,
                html_message=f'<p>{guarantor.guarantor_name} has rejected to guarantee {guarantor.product_name} for {guarantor.sender_name}.</p>'
            )
            return HttpResponse("As part of the loan guarantor request, please enter your National ID/Passport to validate")
        elif message.isdigit() and message not in ["1", "2"] and (guarantor.approved or guarantor.rejected):
            guarantor.confirming_id = message
            loan_application_phone = guarantor.loan_application.account_holder_id.phone.lstrip('+')
            guarantor.save()
            helper_send_sms(phone=loan_application_phone, message=f"{guarantor.guarantor_name} has responded to your guarantor request via text. Login to KBS Internet Banking to check.", department="Loans & Credit")
            return HttpResponse("Guarantee updated successfully")
        else:
            return HttpResponse("Thank you for contacting Kenya Bankers Sacco")
    except Exception as e:
        return HttpResponse("We are not able to complete your request at this time. KBSACCO")

@csrf_exempt
def sms_callback_advanta_two(request):
    if request.method == 'POST':
        data_received = request.body.decode('utf-8')  # Get the raw POST data
    elif request.method == 'GET':
        data_received = request.GET.dict()  # Get query parameters as a dictionary

    # Create the file path in the same folder as this script
    file_path = os.path.join(os.path.dirname(__file__), 'callback_data.txt')
    try:
        # Write the received data to a file
        with open(file_path, 'a') as file:
            file.write(f"Request Method: {request.method}\n")
            file.write(f"Data Received: {data_received}\n")
            file.write("-" * 40 + "\n")
        return JsonResponse({'message': 'Callback data saved successfully'}, status=200)
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)

# @csrf_exempt
# def return_fosa_balance(request):
#     # access_token = get_access_token()

#     url = f"https://api.kwara.com/members/7125HQOE/savings"
#     headers = {
#         'Authorization': f'Bearer {access_token}',
#         'accept': 'application/json',
#     }
#     try:
#         response = requests.get(url, headers=headers)
#         response.raise_for_status()
#         savings_data = response.json().get('data', [])

#         # Extract details of "FOSA Current" or product id "6006"
#         fosa_savings = next(
#             (s for s in savings_data if s.get('attributes', {}).get('product_name') == "FOSA Current" or s.get('attributes', {}).get('product_id') == "6006"),
#             None
#         )

#         if fosa_savings:
#             available_balance = fosa_savings['attributes'].get('available_balance')
#             return HttpResponse(available_balance, content_type="application/json", status=200)
#         else:
#             return HttpResponse('Login successful, but no FOSA Current savings account found', content_type="application/json", status=200)

#     except requests.exceptions.RequestException as e:
#         return HttpResponse('Failed to fetch savings details: ' + str(e), content_type="application/json", status=500)


# @csrf_exempt
# def mambu_client(request):
#     headers = {
#         'Accept': 'application/vnd.mambu.v2+json'
#     }

#     r = requests.get('https://TENANT_NAME.sandbox.mambu.com/api/clients/{40304}', params={

#     }, headers = headers)

#     print (r.json())

# @csrf_exempt
# def deposit_to_fosa(request, sacco_member_id, amount):
#     # print("Here we are")
#     account_number = helper_return_fosa_account(sacco_member_id=f"{sacco_member_id}")
#     print(f"account number: {account_number}")
#     phone_number = helper_return_member_phone_number(member_id=f"{sacco_member_id}")
#     # account_number = account_number_tuple[0]
#     # print(f"account number: {account_number}")
#     # print(f"Phone Number Number : {phone_number}")
#     # access_token = get_access_token()
#     user = CustomUser.objects.get(sacco_user_id=sacco_member_id)

#     url = "https://api.kwara.com/savings_transactions"

#     payload = { "data": { "attributes": {
#                 "type": "DEPOSIT",
#                 "amount": amount,
#                 "savings_id": f"{account_number}",
#                 "phone_number": f"{phone_number}",
#                 "payment_method": "mobile_money",
#                 "notes": "Deposit from GL to FOSA",
#             } } }
#     headers = {
#         "accept": "application/json",
#         'Authorization': f'Bearer {access_token}',
#         "content-type": "application/json"
#     }

#     response = requests.post(url, json=payload, headers=headers)

#     print(f"status code {response.status_code}")
#     if response.status_code == 201:
#         # Successful deposit, return the data as JSON
#         log_user_activity(user, f"Deposit of KES {amount} from Mpesa to FOSA", request.path)
#         return JsonResponse(response.json(), status=201)

#     elif response.status_code == 400:
#         # Unauthorized request, return the error details
#         error_details = response.json().get("errors", [])
#         return JsonResponse({
#             "message": "Unauthorized Request",
#             "errors": error_details
#         }, status=400)

#     elif response.status_code == 422:
#         # Validation errors, return detailed error information
#         error_details = response.json().get("errors", [])
#         return JsonResponse({
#             "message": "Validation Error",
#             "errors": error_details
#         }, status=422)

#     else:
#         # Handle other unexpected errors
#         return JsonResponse({
#             "message": "An unexpected error occurred",
#             "status_code": response.status_code,
#             "response": response.json() if response.content else {}
#         }, status=response.status_code)

def deposit_to_fosa(sacco_member_id, amount):
    # print("Here we are")
    account_number = helper_return_fosa_account(sacco_member_id=f"{sacco_member_id}")
    # print(f"account number: {account_number}")
    phone_number = helper_return_member_phone_number(member_id=f"{sacco_member_id}")
    # account_number = account_number_tuple[0]
    # print(f"account number: {account_number}")
    # print(f"Phone Number Number : {phone_number}")
    access_token = get_P_access_token()
    user = CustomUser.objects.get(sacco_user_id=sacco_member_id)

    url = "https://api.kwara.com/savings_transactions"

    payload = { "data": { "attributes": {
                "type": "DEPOSIT",
                "amount": amount,
                "savings_id": f"{account_number}",
                "phone_number": f"{phone_number}",
                "payment_method": "mobile_money",
                "notes": "Deposit from GL to FOSA",
            } } }
    headers = {
        "accept": "application/json",
        'Authorization': f'Bearer {access_token}',
        "content-type": "application/json"
    }

    response = requests.post(url, json=payload, headers=headers)

    # print(f"status code {response.status_code}")
    if response.status_code == 201:
        # Successful deposit, return the data as JSON
        helper_send_sms(phone=phone_number,message="Deposit to Mpesa unsuccessful, amount reversed to FOSA", department="User")
        log_user_activity(user, f"Deposit of KES {amount} from Mpesa to FOSA", "/api/b2c_result")
        return JsonResponse(response.json(), status=201)

    elif response.status_code == 400:
        # Unauthorized request, return the error details
        error_details = response.json().get("errors", [])
        return JsonResponse({
            "message": "Unauthorized Request",
            "errors": error_details
        }, status=400)

    elif response.status_code == 422:
        # Validation errors, return detailed error information
        error_details = response.json().get("errors", [])
        return JsonResponse({
            "message": "Validation Error",
            "errors": error_details
        }, status=422)

    else:
        # Handle other unexpected errors
        return JsonResponse({
            "message": "An unexpected error occurred",
            "status_code": response.status_code,
            "response": response.json() if response.content else {}
        }, status=response.status_code)

# @csrf_exempt
# def deposit_to_fosa(request, sacco_member_id, amount):
#     # print("Here we are")
#     account_number_tuple = helper_return_fosa_account(sacco_member_id=f"{sacco_member_id}")
#     phone_number = helper_return_member_phone_number(member_id=f"{sacco_member_id}")
#     account_number = account_number_tuple[0]
#     print(f"Phone Number Number : {phone_number}")
#     access_token = get_access_token()
#     user = CustomUser.objects.get()

#     url = "https://api.kwara.com/savings_transactions"

#     payload = { "data": { "attributes": {
#                 "type": "DEPOSIT",
#                 "amount": amount,
#                 "savings_id": f"{account_number}",
#                 "phone_number": f"{phone_number}",
#                 "payment_method": "mobile_money",
#                 "notes": "Deposit from Mpesa to FOSA",
#             } } }
#     headers = {
#         "accept": "application/json",
#         'Authorization': f'Bearer {access_token}',
#         "content-type": "application/json"
#     }

#     response = requests.post(url, json=payload, headers=headers)

#     print(f"status code {response.status_code}")
#     if response.status_code == 201:
#         # Successful deposit, return the data as JSON
#         log_user_activity(user, f"Deposit of KES {amount} from Mpesa to FOSA", request.path)
#         return JsonResponse(response.json(), status=201)

#     elif response.status_code == 400:
#         # Unauthorized request, return the error details
#         error_details = response.json().get("errors", [])
#         return JsonResponse({
#             "message": "Unauthorized Request",
#             "errors": error_details
#         }, status=400)

#     elif response.status_code == 422:
#         # Validation errors, return detailed error information
#         error_details = response.json().get("errors", [])
#         return JsonResponse({
#             "message": "Validation Error",
#             "errors": error_details
#         }, status=422)

#     else:
#         # Handle other unexpected errors
#         return JsonResponse({
#             "message": "An unexpected error occurred",
#             "status_code": response.status_code,
#             "response": response.json() if response.content else {}
#         }, status=response.status_code)


# from django.contrib.auth.hashers import make_password

# def encrypt_password(password, salt=None, hasher='pbkdf2_sha256'):
#     """
#     Encrypts a password using Django's PBKDF2 hashing.

#     Args:
#         password (str): The plaintext password to encrypt.
#         salt (str): An optional salt to use. If not provided, Django generates one automatically.
#         hasher (str): The hashing algorithm to use (default: pbkdf2_sha256).

#     Returns:
#         str: The encrypted password in Django's format.
#     """
#     encrypted_password = make_password(password, salt, hasher)
#     return encrypted_password

# # Example usage
# if __name__ == "__main__":
#     plaintext_password = "my_secure_password"
#     encrypted = encrypt_password(plaintext_password)
#     print(f"Encrypted Password: {encrypted}")




# def check_account(request):
#     # url = f"https://api.kwara.com/members/30469/savings"
#     DormantUrl = f"https://api.kwara.com/members/29536/savings?filter[state]=DORMANT"
#     headers = {
#         'Authorization': f'Bearer {access_token}',
#         'accept': 'application/json',
#     }
#     try:
#         response = requests.get(DormantUrl, headers=headers)
#         response.raise_for_status()

#         # Convert the response to JSON format (Python dict)
#         return JsonResponse(response.json(), status=response.status_code)

#     except Exception as e:
#         return JsonResponse({'error': str(e)}, status=500)

