from django.db import connection
from questbanker_api.utils import get_current_user
from rest_framework.response import Response
from .general_helper import convert_json_to_sql_where

def filter_loan_tracking_reports(report_filters):
    results       = []
    filter_1  = report_filters['filter_1']
    filter_2  = report_filters['filter_2']

    report_filter = report_filters['report_filter']
    
    organisation_branch_id = get_current_user(report_filters['request'], 'organisation_branch_id', None)
    organisation_id = get_current_user(report_filters['request'], 'organisation_id', None)
    as_at = report_filters['as_at']
    extra_filters = f"date(lad.loan_disbursement_date at time zone ''Africa/Nairobi'') <= ''{as_at}''"

    if report_filter == 'product_branch':
        loan_filter  = convert_json_to_sql_where({"lv.loan_product_id": filter_1, "lv.branch_id": filter_2})
        loan_filter = f"{loan_filter} AND {extra_filters}"
        results = filter_tracking_product_branch(organisation_id, loan_filter, as_at)

    elif report_filter == 'officer_branch':
        loan_filter  = convert_json_to_sql_where({"lv.loan_officer_id": filter_1, "lv.branch_id": filter_2})
        loan_filter = f"{loan_filter} AND {extra_filters}"
        results = filter_tracking_officer_branch(organisation_id, loan_filter, as_at)
    
    elif report_filter == 'client_type_product':
        loan_filter  = convert_json_to_sql_where({"lv.loan_product_id": filter_1, "lv.customer_type_id": filter_2, "lv.branch_id": [organisation_branch_id]})
        loan_filter = f"{loan_filter} AND {extra_filters}"
        results = filter_tracking_client_type_product(organisation_id, loan_filter, as_at)

    elif report_filter == 'client_type_branch':
        loan_filter  = convert_json_to_sql_where({"lv.branch_id": filter_1, "lv.customer_type_id": filter_2})
        loan_filter = f"{loan_filter} AND {extra_filters}"
        results = filter_tracking_client_type_branch(organisation_id, loan_filter, as_at)

    elif report_filter == 'product_officer':
        loan_filter  = convert_json_to_sql_where({"lv.loan_officer_id": filter_1, "lv.loan_product_id": filter_2, "lv.branch_id": [organisation_branch_id]})
        loan_filter = f"{loan_filter} AND {extra_filters}"
        results = filter_tracking_product_officer(organisation_id, loan_filter, as_at)

    elif report_filter == 'client_type_officer':
        loan_filter  = convert_json_to_sql_where({"lv.loan_officer_id": filter_1, "lv.customer_type_id": filter_2, "lv.branch_id": [organisation_branch_id]})
        loan_filter = f"{loan_filter} AND {extra_filters}"
        results = filter_tracking_client_type_officer(organisation_id, loan_filter, as_at)

    elif report_filter == 'group_branch':
        loan_filter  = convert_json_to_sql_where({"lv.branch_id": filter_1, "lv.group_id": filter_2})
        loan_filter = f"{loan_filter} AND {extra_filters}"
        results = filter_tracking_group_branch(organisation_id, loan_filter, as_at)

    elif report_filter == 'product_sector':
        loan_filter  = convert_json_to_sql_where({"lv.loan_product_id": filter_1, "lv.loan_sector_id": filter_2, "lv.branch_id": [organisation_branch_id]})
        loan_filter = f"{loan_filter} AND {extra_filters}"
        results = filter_tracking_product_sector(organisation_id, loan_filter, as_at)

    elif report_filter == 'gender_product':
        loan_filter  = convert_json_to_sql_where({"lv.loan_product_id": filter_1, "lv.gender": filter_2, "lv.branch_id": [organisation_branch_id]})
        loan_filter = f"{loan_filter} AND {extra_filters}"
        results = filter_tracking_gender_product(organisation_id, loan_filter, as_at)
    
    elif report_filter == 'gender_branch':
        loan_filter  = convert_json_to_sql_where({"lv.branch_id": filter_1, "lv.gender": filter_2})
        loan_filter = f"{loan_filter} AND {extra_filters}"
        results = filter_tracking_gender_branch(organisation_id, loan_filter, as_at)
    
    elif report_filter == 'gender_officer':
        loan_filter  = convert_json_to_sql_where({"lv.loan_officer_id": filter_1, "lv.gender": filter_2, "lv.branch_id": [organisation_branch_id] })
        loan_filter = f"{loan_filter} AND {extra_filters}"
        results = filter_tracking_gender_officer(organisation_id, loan_filter, as_at)

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

def filter_tracking_product_branch(organisation_id, loan_filter, as_at):
    with connection.cursor() as cursor:
        query = f"""
                WITH aggregated_data AS (
                    SELECT
                        branch_id,
                        loan_product_id,
                        SUM(disbursed_loan_amount) - SUM(princ_paid) AS total,
                        ARRAY_AGG(json_build_object(
                            'id', id,
                            'name', name,
                            'telephone', telephone,
                            'member_number', member_number,
                            'old_member_number', old_member_number,
                            'loan_sector_name', loan_sector_name,
                            'loan_amount', loan_amount,
                            'disbursed_loan_amount', disbursed_loan_amount,
                            'princ_expected', princ_expected,
                            'int_expected', int_expected,
                            'loan_date', loan_date,
                            'loan_start_date', loan_start_date,
                            'int_waivered', int_waivered,
                            'princ_paid', princ_paid,
                            'int_paid', int_paid,
                            'int_paid_with_waiver', int_paid + int_waivered,
                            'total_paid', total_paid,
                            'penalty_paid', penalty_paid,
                            'total_paid_with_penalty', total_paid + penalty_paid,
                            'branch_name', branch_name,
                            'gender', gender,
                            'princ_bal', princ_expected - princ_paid,
                            'int_bal', int_expected - (int_paid + int_waivered),
                            'penalty_bal', total_penalty - penalty_paid,
                            'total_bal', ( (int_expected + princ_expected) -  total_paid ),
                            'total_bal_with_penalty', ( (int_expected + princ_expected + total_penalty) -  (total_paid + penalty_paid ) ),
                            'int_rate', int_rate,
                            'app_grace_period', app_grace_period,
                            'grace_period_type', grace_period_type,
                            'loan_period', loan_period,
                            'period_type', period_type,
                            'loan_officer_full_name', loan_officer_full_name,
                            'loan_requester_full_name', loan_requester.loan_requester_full_name,
                            'loan_approver_full_name', loan_approver.loan_approver_full_name,
                            'loan_disburser_full_name', loan_disburser.loan_disburser_full_name
                        )) AS loans
                    FROM
                        public.get_loan_tracking_data({organisation_id}, '{as_at}', '{loan_filter}') AS lv
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_requester_full_name
                        FROM loan_applications la
                        JOIN users_user uu ON uu.id = la.loan_app_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE la.id = lv.id AND la.deleted = false AND la.is_deleted = false
                        LIMIT 1
                    ) loan_requester ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_approver_full_name
                        FROM loan_application_approval laa
                        JOIN users_user uu ON uu.id = laa.loan_approval_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE laa.loan_application_id = lv.id AND laa.deleted = false
                        LIMIT 1
                    ) loan_approver ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_disburser_full_name
                        FROM loan_application_disbursement lad
                        JOIN users_user uu ON uu.id = lad.loan_disburse_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE lad.loan_application_id = lv.id AND lad.deleted = false
                        LIMIT 1
                    ) loan_disburser ON true
                    GROUP BY
                        branch_id, loan_product_id
                )
                SELECT
                    json_build_object(
                        'filter_1', ad.branch_id,
                        'filter_1_name', b.name,
                        'filter_2', ad.loan_product_id,
                        'filter_2_name', lp.product_name,
                        'total', ad.total,
                        'loans', ad.loans
                    ) AS branch_data
                FROM
                    aggregated_data ad
                JOIN
                    organisation_branch b ON ad.branch_id = b.id
                JOIN loan_products lp ON ad.loan_product_id = lp.id
                ORDER BY ad.branch_id;
            """
        cursor.execute(query)

        # Fetch all rows
        rows = cursor.fetchall()
        response = []
        branch_map = {}

        for row in rows:
            branch_id = row[0]['filter_1']
            branch_name = row[0]['filter_1_name']
            loan_product_id = row[0]['filter_2']
            product_name = row[0]['filter_2_name']

            # Check if the branch_id is already in the response
            if branch_id not in branch_map:
                # Create a new entry for the branch
                branch_entry = {
                    'filter_1': branch_id,
                    'filter_1_name': branch_name,
                    'filter_2': []
                }
                branch_map[branch_id] = branch_entry
                response.append(branch_entry)

            # Get the current branch entry
            branch_entry = branch_map[branch_id]

            # Add the loan product entry to filter_2
            loan_product_entry = {
                'filter_2': loan_product_id,
                'filter_2_name': product_name,
                'total': row[0]['total'],
                'loans': row[0]['loans']
            }

            branch_entry['filter_2'].append(loan_product_entry)
        return response


def filter_tracking_officer_branch(organisation_id, loan_filter, as_at):
    with connection.cursor() as cursor:
        query = f"""
                WITH aggregated_data AS (
                    SELECT
                        branch_id,
                        loan_officer_id,
                        SUM(disbursed_loan_amount) - SUM(princ_paid) AS total,
                        ARRAY_AGG(json_build_object(
                            'id', id,
                            'name', name,
                            'telephone', telephone,
                            'member_number', member_number,
                            'old_member_number', old_member_number,
                            'loan_sector_name', loan_sector_name,
                            'loan_amount', loan_amount,
                            'disbursed_loan_amount', disbursed_loan_amount,
                            'princ_expected', princ_expected,
                            'int_expected', int_expected,
                            'loan_date', loan_date,
                            'loan_start_date', loan_start_date,
                            'int_waivered', int_waivered,
                            'princ_paid', princ_paid,
                            'int_paid', int_paid,
                            'int_paid_with_waiver', int_paid + int_waivered,
                            'total_paid', total_paid,
                            'penalty_paid', penalty_paid,
                            'total_paid_with_penalty', total_paid + penalty_paid,
                            'branch_name', branch_name,
                            'gender', gender,
                            'princ_bal', princ_expected - princ_paid,
                            'int_bal', int_expected - (int_paid + int_waivered),
                            'penalty_bal', total_penalty - penalty_paid,
                            'total_bal', ( (int_expected + princ_expected) -  total_paid ),
                            'total_bal_with_penalty', ( (int_expected + princ_expected + total_penalty) -  (total_paid + penalty_paid ) ),
                            'int_rate', int_rate,
                            'app_grace_period', app_grace_period,
                            'grace_period_type', grace_period_type,
                            'loan_period', loan_period,
                            'period_type', period_type,
                            'loan_officer_full_name', loan_officer_full_name,
                            'loan_requester_full_name', loan_requester.loan_requester_full_name,
                            'loan_approver_full_name', loan_approver.loan_approver_full_name,
                            'loan_disburser_full_name', loan_disburser.loan_disburser_full_name
                        )) AS loans
                    FROM
                        public.get_loan_tracking_data({organisation_id}, '{as_at}', '{loan_filter}') AS lv
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_requester_full_name
                        FROM loan_applications la
                        JOIN users_user uu ON uu.id = la.loan_app_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE la.id = lv.id AND la.deleted = false AND la.is_deleted = false
                        LIMIT 1
                    ) loan_requester ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_approver_full_name
                        FROM loan_application_approval laa
                        JOIN users_user uu ON uu.id = laa.loan_approval_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE laa.loan_application_id = lv.id AND laa.deleted = false
                        LIMIT 1
                    ) loan_approver ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_disburser_full_name
                        FROM loan_application_disbursement lad
                        JOIN users_user uu ON uu.id = lad.loan_disburse_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE lad.loan_application_id = lv.id AND lad.deleted = false
                        LIMIT 1
                    ) loan_disburser ON true
                    GROUP BY
                        branch_id, loan_officer_id
                )
                SELECT
                    json_build_object(
                        'filter_1', ad.branch_id,
                        'filter_1_name', b.name,
                        'filter_2', ad.loan_officer_id,
                        'filter_2_name', sf.name,
                        'total', ad.total,
                        'loans', ad.loans
                    ) AS branch_data
                FROM
                    aggregated_data ad
                JOIN
                    organisation_branch b ON ad.branch_id = b.id
                JOIN staff sf ON ad.loan_officer_id = sf.id
                ORDER BY ad.branch_id;
            """
        cursor.execute(query)

        # Fetch all rows
        rows = cursor.fetchall()
        response = []
        branch_map = {}

        for row in rows:
            branch_id = row[0]['filter_1']
            branch_name = row[0]['filter_1_name']
            loan_officer_id = row[0]['filter_2']
            staff_name = row[0]['filter_2_name']

            # Check if the branch_id is already in the response
            if branch_id not in branch_map:
                # Create a new entry for the branch
                branch_entry = {
                    'filter_1': branch_id,
                    'filter_1_name': branch_name,
                    'filter_2': []
                }
                branch_map[branch_id] = branch_entry
                response.append(branch_entry)

            # Get the current branch entry
            branch_entry = branch_map[branch_id]

            # Add the  staff entry to filter_2
            loan_product_entry = {
                'filter_2': loan_officer_id,
                'filter_2_name': staff_name,
                'total': row[0]['total'],
                'loans': row[0]['loans']
            }

            branch_entry['filter_2'].append(loan_product_entry)
        return response



def filter_tracking_client_type_product(organisation_id, loan_filter, as_at):
    with connection.cursor() as cursor:
        query = f"""
                WITH aggregated_data AS (
                    SELECT
                        customer_type_id,
                        loan_product_id,
                        SUM(disbursed_loan_amount) - SUM(princ_paid) AS total,
                        ARRAY_AGG(json_build_object(
                            'id', id,
                            'name', name,
                            'telephone', telephone,
                            'member_number', member_number,
                            'old_member_number', old_member_number,
                            'loan_sector_name', loan_sector_name,
                            'loan_amount', loan_amount,
                            'disbursed_loan_amount', disbursed_loan_amount,
                            'princ_expected', princ_expected,
                            'int_expected', int_expected,
                            'loan_date', loan_date,
                            'loan_start_date', loan_start_date,
                            'int_waivered', int_waivered,
                            'princ_paid', princ_paid,
                            'int_paid', int_paid,
                            'int_paid_with_waiver', int_paid + int_waivered,
                            'total_paid', total_paid,
                            'penalty_paid', penalty_paid,
                            'total_paid_with_penalty', total_paid + penalty_paid,
                            'branch_name', branch_name,
                            'gender', gender,
                            'princ_bal', princ_expected - princ_paid,
                            'int_bal', int_expected - (int_paid + int_waivered),
                            'penalty_bal', total_penalty - penalty_paid,
                            'total_bal', ( (int_expected + princ_expected) -  total_paid ),
                            'total_bal_with_penalty', ( (int_expected + princ_expected + total_penalty) -  (total_paid + penalty_paid ) ),
                            'int_rate', int_rate,
                            'app_grace_period', app_grace_period,
                            'grace_period_type', grace_period_type,
                            'loan_period', loan_period,
                            'period_type', period_type,
                            'loan_officer_full_name', loan_officer_full_name,
                            'loan_requester_full_name', loan_requester.loan_requester_full_name,
                            'loan_approver_full_name', loan_approver.loan_approver_full_name,
                            'loan_disburser_full_name', loan_disburser.loan_disburser_full_name
                        )) AS loans
                    FROM
                        public.get_loan_tracking_data({organisation_id}, '{as_at}', '{loan_filter}') AS lv
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_requester_full_name
                        FROM loan_applications la
                        JOIN users_user uu ON uu.id = la.loan_app_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE la.id = lv.id AND la.deleted = false AND la.is_deleted = false
                        LIMIT 1
                    ) loan_requester ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_approver_full_name
                        FROM loan_application_approval laa
                        JOIN users_user uu ON uu.id = laa.loan_approval_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE laa.loan_application_id = lv.id AND laa.deleted = false
                        LIMIT 1
                    ) loan_approver ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_disburser_full_name
                        FROM loan_application_disbursement lad
                        JOIN users_user uu ON uu.id = lad.loan_disburse_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE lad.loan_application_id = lv.id AND lad.deleted = false
                        LIMIT 1
                    ) loan_disburser ON true
                    GROUP BY
                        customer_type_id, loan_product_id
                )
                SELECT
                    json_build_object(
                        'filter_1', ad.customer_type_id,
                        'filter_1_name', b.customer_type,
                        'filter_2', ad.loan_product_id,
                        'filter_2_name', lp.product_name,
                        'total', ad.total,
                        'loans', ad.loans
                    ) AS branch_data
                FROM
                    aggregated_data ad
                JOIN
                    customer_type b ON ad.customer_type_id = b.id
                JOIN loan_products lp ON ad.loan_product_id = lp.id
                ORDER BY ad.customer_type_id;
            """
        cursor.execute(query)

        # Fetch all rows
        rows = cursor.fetchall()
        response = []
        branch_map = {}

        for row in rows:
            customer_type_id = row[0]['filter_1']
            customer_type = row[0]['filter_1_name']
            loan_product_id = row[0]['filter_2']
            product_name = row[0]['filter_2_name']

            # Check if the branch_id is already in the response
            if customer_type_id not in branch_map:
                # Create a new entry for the branch
                branch_entry = {
                    'filter_1': customer_type_id,
                    'filter_1_name': customer_type,
                    'filter_2': []
                }
                branch_map[customer_type_id] = branch_entry
                response.append(branch_entry)

            # Get the current branch entry
            branch_entry = branch_map[customer_type_id]

            # Add the  staff entry to filter_2
            loan_product_entry = {
                'filter_2': loan_product_id,
                'filter_2_name': product_name,
                'total': row[0]['total'],
                'loans': row[0]['loans']
            }

            branch_entry['filter_2'].append(loan_product_entry)
        return response

def filter_tracking_client_type_branch(organisation_id, loan_filter, as_at):
    with connection.cursor() as cursor:
        query = f"""
                WITH aggregated_data AS (
                    SELECT
                        branch_id,
                        customer_type_id,
                        SUM(disbursed_loan_amount) - SUM(princ_paid) AS total,
                        ARRAY_AGG(json_build_object(
                            'id', id,
                            'name', name,
                            'telephone', telephone,
                            'member_number', member_number,
                            'old_member_number', old_member_number,
                            'loan_sector_name', loan_sector_name,
                            'loan_amount', loan_amount,
                            'disbursed_loan_amount', disbursed_loan_amount,
                            'princ_expected', princ_expected,
                            'int_expected', int_expected,
                            'loan_date', loan_date,
                            'loan_start_date', loan_start_date,
                            'int_waivered', int_waivered,
                            'princ_paid', princ_paid,
                            'int_paid', int_paid,
                            'int_paid_with_waiver', int_paid + int_waivered,
                            'total_paid', total_paid,
                            'penalty_paid', penalty_paid,
                            'total_paid_with_penalty', total_paid + penalty_paid,
                            'branch_name', branch_name,
                            'gender', gender,
                            'princ_bal', princ_expected - princ_paid,
                            'int_bal', int_expected - (int_paid + int_waivered),
                            'penalty_bal', total_penalty - penalty_paid,
                            'total_bal', ( (int_expected + princ_expected) -  total_paid ),
                            'total_bal_with_penalty', ( (int_expected + princ_expected + total_penalty) -  (total_paid + penalty_paid ) ),
                            'int_rate', int_rate,
                            'app_grace_period', app_grace_period,
                            'grace_period_type', grace_period_type,
                            'loan_period', loan_period,
                            'period_type', period_type,
                            'loan_officer_full_name', loan_officer_full_name,
                            'loan_requester_full_name', loan_requester.loan_requester_full_name,
                            'loan_approver_full_name', loan_approver.loan_approver_full_name,
                            'loan_disburser_full_name', loan_disburser.loan_disburser_full_name
                        )) AS loans
                    FROM
                        public.get_loan_tracking_data({organisation_id}, '{as_at}', '{loan_filter}') AS lv
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_requester_full_name
                        FROM loan_applications la
                        JOIN users_user uu ON uu.id = la.loan_app_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE la.id = lv.id AND la.deleted = false AND la.is_deleted = false
                        LIMIT 1
                    ) loan_requester ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_approver_full_name
                        FROM loan_application_approval laa
                        JOIN users_user uu ON uu.id = laa.loan_approval_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE laa.loan_application_id = lv.id AND laa.deleted = false
                        LIMIT 1
                    ) loan_approver ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_disburser_full_name
                        FROM loan_application_disbursement lad
                        JOIN users_user uu ON uu.id = lad.loan_disburse_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE lad.loan_application_id = lv.id AND lad.deleted = false
                        LIMIT 1
                    ) loan_disburser ON true
                    GROUP BY
                        branch_id, customer_type_id
                )
                SELECT
                    json_build_object(
                        'filter_1', ad.branch_id,
                        'filter_1_name', b.name,
                        'filter_2', ad.customer_type_id,
                        'filter_2_name', lp.customer_type,
                        'total', ad.total,
                        'loans', ad.loans
                    ) AS branch_data
                FROM
                    aggregated_data ad
                JOIN
                    organisation_branch b ON ad.branch_id = b.id
                JOIN customer_type lp ON ad.customer_type_id = lp.id
                ORDER BY ad.branch_id;
            """
        cursor.execute(query)

        # Fetch all rows
        rows = cursor.fetchall()
        response = []
        branch_map = {}

        for row in rows:
            branch_id = row[0]['filter_1']
            branch_name = row[0]['filter_1_name']
            customer_type_id = row[0]['filter_2']
            customer_type = row[0]['filter_2_name']

            # Check if the branch_id is already in the response
            if branch_id not in branch_map:
                # Create a new entry for the branch
                branch_entry = {
                    'filter_1': branch_id,
                    'filter_1_name': branch_name,
                    'filter_2': []
                }
                branch_map[branch_id] = branch_entry
                response.append(branch_entry)

            # Get the current branch entry
            branch_entry = branch_map[branch_id]

            # Add the loan product entry to filter_2
            loan_product_entry = {
                'filter_2': customer_type_id,
                'filter_2_name': customer_type,
                'total': row[0]['total'],
                'loans': row[0]['loans']
            }

            branch_entry['filter_2'].append(loan_product_entry)
        return response


def filter_tracking_product_officer(organisation_id, loan_filter, as_at):
    with connection.cursor() as cursor:
        query = f"""
                WITH aggregated_data AS (
                    SELECT
                        loan_officer_id,
                        loan_product_id,
                        SUM(disbursed_loan_amount) - SUM(princ_paid) AS total,
                        ARRAY_AGG(json_build_object(
                            'id', id,
                            'name', name,
                            'telephone', telephone,
                            'member_number', member_number,
                            'old_member_number', old_member_number,
                            'loan_sector_name', loan_sector_name,
                            'loan_amount', loan_amount,
                            'disbursed_loan_amount', disbursed_loan_amount,
                            'princ_expected', princ_expected,
                            'int_expected', int_expected,
                            'loan_date', loan_date,
                            'loan_start_date', loan_start_date,
                            'int_waivered', int_waivered,
                            'princ_paid', princ_paid,
                            'int_paid', int_paid,
                            'int_paid_with_waiver', int_paid + int_waivered,
                            'total_paid', total_paid,
                            'penalty_paid', penalty_paid,
                            'total_paid_with_penalty', total_paid + penalty_paid,
                            'branch_name', branch_name,
                            'gender', gender,
                            'princ_bal', princ_expected - princ_paid,
                            'int_bal', int_expected - (int_paid + int_waivered),
                            'penalty_bal', total_penalty - penalty_paid,
                            'total_bal', ( (int_expected + princ_expected) -  total_paid ),
                            'total_bal_with_penalty', ( (int_expected + princ_expected + total_penalty) -  (total_paid + penalty_paid ) ),
                            'int_rate', int_rate,
                            'app_grace_period', app_grace_period,
                            'grace_period_type', grace_period_type,
                            'loan_period', loan_period,
                            'period_type', period_type,
                            'loan_officer_full_name', loan_officer_full_name,
                            'loan_requester_full_name', loan_requester.loan_requester_full_name,
                            'loan_approver_full_name', loan_approver.loan_approver_full_name,
                            'loan_disburser_full_name', loan_disburser.loan_disburser_full_name
                        )) AS loans
                    FROM
                        public.get_loan_tracking_data({organisation_id}, '{as_at}', '{loan_filter}') AS lv
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_requester_full_name
                        FROM loan_applications la
                        JOIN users_user uu ON uu.id = la.loan_app_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE la.id = lv.id AND la.deleted = false AND la.is_deleted = false
                        LIMIT 1
                    ) loan_requester ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_approver_full_name
                        FROM loan_application_approval laa
                        JOIN users_user uu ON uu.id = laa.loan_approval_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE laa.loan_application_id = lv.id AND laa.deleted = false
                        LIMIT 1
                    ) loan_approver ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_disburser_full_name
                        FROM loan_application_disbursement lad
                        JOIN users_user uu ON uu.id = lad.loan_disburse_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE lad.loan_application_id = lv.id AND lad.deleted = false
                        LIMIT 1
                    ) loan_disburser ON true
                    GROUP BY
                        loan_officer_id, loan_product_id
                )
                SELECT
                    json_build_object(
                        'filter_1', ad.loan_officer_id,
                        'filter_1_name', b.name,
                        'filter_2', ad.loan_product_id,
                        'filter_2_name', lp.product_name,
                        'total', ad.total,
                        'loans', ad.loans
                    ) AS branch_data
                FROM
                    aggregated_data ad
                JOIN
                    staff b ON ad.loan_officer_id = b.id
                JOIN loan_products lp ON ad.loan_product_id = lp.id
                ORDER BY ad.loan_officer_id;
            """
        cursor.execute(query)

        # Fetch all rows
        rows = cursor.fetchall()
        response = []
        branch_map = {}

        for row in rows:
            loan_officer_id = row[0]['filter_1']
            staff_name = row[0]['filter_1_name']
            loan_product_id = row[0]['filter_2']
            product_name = row[0]['filter_2_name']

            # Check if the branch_id is already in the response
            if loan_officer_id not in branch_map:
                # Create a new entry for the branch
                branch_entry = {
                    'filter_1': loan_officer_id,
                    'filter_1_name': staff_name,
                    'filter_2': []
                }
                branch_map[loan_officer_id] = branch_entry
                response.append(branch_entry)

            # Get the current branch entry
            branch_entry = branch_map[loan_officer_id]

            # Add the loan product entry to filter_2
            loan_product_entry = {
                'filter_2': loan_product_id,
                'filter_2_name': product_name,
                'total': row[0]['total'],
                'loans': row[0]['loans']
            }

            branch_entry['filter_2'].append(loan_product_entry)
        return response


def filter_tracking_client_type_officer(organisation_id, loan_filter, as_at):
    with connection.cursor() as cursor:
        query = f"""
                WITH aggregated_data AS (
                    SELECT
                        loan_officer_id,
                        customer_type_id,
                        SUM(disbursed_loan_amount) - SUM(princ_paid) AS total,
                        ARRAY_AGG(json_build_object(
                            'id', id,
                            'name', name,
                            'telephone', telephone,
                            'member_number', member_number,
                            'old_member_number', old_member_number,
                            'loan_sector_name', loan_sector_name,
                            'loan_amount', loan_amount,
                            'disbursed_loan_amount', disbursed_loan_amount,
                            'princ_expected', princ_expected,
                            'int_expected', int_expected,
                            'loan_date', loan_date,
                            'loan_start_date', loan_start_date,
                            'int_waivered', int_waivered,
                            'princ_paid', princ_paid,
                            'int_paid', int_paid,
                            'int_paid_with_waiver', int_paid + int_waivered,
                            'total_paid', total_paid,
                            'penalty_paid', penalty_paid,
                            'total_paid_with_penalty', total_paid + penalty_paid,
                            'branch_name', branch_name,
                            'gender', gender,
                            'princ_bal', princ_expected - princ_paid,
                            'int_bal', int_expected - (int_paid + int_waivered),
                            'penalty_bal', total_penalty - penalty_paid,
                            'total_bal', ( (int_expected + princ_expected) -  total_paid ),
                            'total_bal_with_penalty', ( (int_expected + princ_expected + total_penalty) -  (total_paid + penalty_paid ) ),
                            'int_rate', int_rate,
                            'app_grace_period', app_grace_period,
                            'grace_period_type', grace_period_type,
                            'loan_period', loan_period,
                            'period_type', period_type,
                            'loan_officer_full_name', loan_officer_full_name,
                            'loan_requester_full_name', loan_requester.loan_requester_full_name,
                            'loan_approver_full_name', loan_approver.loan_approver_full_name,
                            'loan_disburser_full_name', loan_disburser.loan_disburser_full_name
                        )) AS loans
                    FROM
                        public.get_loan_tracking_data({organisation_id}, '{as_at}', '{loan_filter}') AS lv
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_requester_full_name
                        FROM loan_applications la
                        JOIN users_user uu ON uu.id = la.loan_app_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE la.id = lv.id AND la.deleted = false AND la.is_deleted = false
                        LIMIT 1
                    ) loan_requester ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_approver_full_name
                        FROM loan_application_approval laa
                        JOIN users_user uu ON uu.id = laa.loan_approval_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE laa.loan_application_id = lv.id AND laa.deleted = false
                        LIMIT 1
                    ) loan_approver ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_disburser_full_name
                        FROM loan_application_disbursement lad
                        JOIN users_user uu ON uu.id = lad.loan_disburse_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE lad.loan_application_id = lv.id AND lad.deleted = false
                        LIMIT 1
                    ) loan_disburser ON true
                    GROUP BY
                        loan_officer_id, customer_type_id
                )
                SELECT
                    json_build_object(
                        'filter_1', ad.loan_officer_id,
                        'filter_1_name', b.name,
                        'filter_2', ad.customer_type_id,
                        'filter_2_name', lp.customer_type,
                        'total', ad.total,
                        'loans', ad.loans
                    ) AS branch_data
                FROM
                    aggregated_data ad
                JOIN
                    staff b ON ad.loan_officer_id = b.id
                JOIN customer_type lp ON ad.customer_type_id = lp.id
                ORDER BY ad.loan_officer_id;
            """
        cursor.execute(query)

        # Fetch all rows
        rows = cursor.fetchall()
        response = []
        branch_map = {}

        for row in rows:
            loan_officer_id = row[0]['filter_1']
            staff_name = row[0]['filter_1_name']
            customer_type_id = row[0]['filter_2']
            customer_type = row[0]['filter_2_name']

            # Check if the branch_id is already in the response
            if loan_officer_id not in branch_map:
                # Create a new entry for the branch
                branch_entry = {
                    'filter_1': loan_officer_id,
                    'filter_1_name': staff_name,
                    'filter_2': []
                }
                branch_map[loan_officer_id] = branch_entry
                response.append(branch_entry)

            # Get the current branch entry
            branch_entry = branch_map[loan_officer_id]

            # Add the loan product entry to filter_2
            loan_product_entry = {
                'filter_2': customer_type_id,
                'filter_2_name': customer_type,
                'total': row[0]['total'],
                'loans': row[0]['loans']
            }

            branch_entry['filter_2'].append(loan_product_entry)
        return response


def filter_tracking_group_branch(organisation_id, loan_filter, as_at):
    with connection.cursor() as cursor:
        query = f"""
                WITH aggregated_data AS (
                    SELECT
                        branch_id,
                        group_id,
                        SUM(disbursed_loan_amount) - SUM(princ_paid) AS total,
                        ARRAY_AGG(json_build_object(
                            'id', id,
                            'name', name,
                            'telephone', telephone,
                            'member_number', member_number,
                            'old_member_number', old_member_number,
                            'loan_sector_name', loan_sector_name,
                            'loan_amount', loan_amount,
                            'disbursed_loan_amount', disbursed_loan_amount,
                            'princ_expected', princ_expected,
                            'int_expected', int_expected,
                            'loan_date', loan_date,
                            'loan_start_date', loan_start_date,
                            'int_waivered', int_waivered,
                            'princ_paid', princ_paid,
                            'int_paid', int_paid,
                            'int_paid_with_waiver', int_paid + int_waivered,
                            'total_paid', total_paid,
                            'penalty_paid', penalty_paid,
                            'total_paid_with_penalty', total_paid + penalty_paid,
                            'branch_name', branch_name,
                            'gender', gender,
                            'princ_bal', princ_expected - princ_paid,
                            'int_bal', int_expected - (int_paid + int_waivered),
                            'penalty_bal', total_penalty - penalty_paid,
                            'total_bal', ( (int_expected + princ_expected) -  total_paid ),
                            'total_bal_with_penalty', ( (int_expected + princ_expected + total_penalty) -  (total_paid + penalty_paid ) ),
                            'int_rate', int_rate,
                            'app_grace_period', app_grace_period,
                            'grace_period_type', grace_period_type,
                            'loan_period', loan_period,
                            'period_type', period_type,
                            'loan_officer_full_name', loan_officer_full_name,
                            'loan_requester_full_name', loan_requester.loan_requester_full_name,
                            'loan_approver_full_name', loan_approver.loan_approver_full_name,
                            'loan_disburser_full_name', loan_disburser.loan_disburser_full_name
                        )) AS loans
                    FROM
                        public.get_loan_tracking_data({organisation_id}, '{as_at}', '{loan_filter}') AS lv
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_requester_full_name
                        FROM loan_applications la
                        JOIN users_user uu ON uu.id = la.loan_app_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE la.id = lv.id AND la.deleted = false AND la.is_deleted = false
                        LIMIT 1
                    ) loan_requester ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_approver_full_name
                        FROM loan_application_approval laa
                        JOIN users_user uu ON uu.id = laa.loan_approval_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE laa.loan_application_id = lv.id AND laa.deleted = false
                        LIMIT 1
                    ) loan_approver ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_disburser_full_name
                        FROM loan_application_disbursement lad
                        JOIN users_user uu ON uu.id = lad.loan_disburse_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE lad.loan_application_id = lv.id AND lad.deleted = false
                        LIMIT 1
                    ) loan_disburser ON true
                    GROUP BY
                        branch_id, group_id
                )
                SELECT
                    json_build_object(
                        'filter_1', ad.branch_id,
                        'filter_1_name', b.name,
                        'filter_2', ad.group_id,
                        'filter_2_name', lp.name,
                        'total', ad.total,
                        'loans', ad.loans
                    ) AS branch_data
                FROM
                    aggregated_data ad
                JOIN
                    organisation_branch b ON ad.branch_id = b.id
                JOIN customer lp ON ad.group_id = lp.id
                ORDER BY ad.branch_id;
            """
        cursor.execute(query)

        # Fetch all rows
        rows = cursor.fetchall()
        response = []
        branch_map = {}

        for row in rows:
            branch_id = row[0]['filter_1']
            branch_name = row[0]['filter_1_name']
            group_id = row[0]['filter_2']
            customer_name = row[0]['filter_2_name']

            # Check if the branch_id is already in the response
            if branch_id not in branch_map:
                # Create a new entry for the branch
                branch_entry = {
                    'filter_1': branch_id,
                    'filter_1_name': branch_name,
                    'filter_2': []
                }
                branch_map[branch_id] = branch_entry
                response.append(branch_entry)

            # Get the current branch entry
            branch_entry = branch_map[branch_id]

            # Add the loan product entry to filter_2
            loan_product_entry = {
                'filter_2': group_id,
                'filter_2_name': customer_name,
                'total': row[0]['total'],
                'loans': row[0]['loans']
            }

            branch_entry['filter_2'].append(loan_product_entry)
        return response

def filter_tracking_product_sector(organisation_id, loan_filter, as_at):
    with connection.cursor() as cursor:
        query = f"""
                WITH aggregated_data AS (
                    SELECT
                        loan_sector_id,
                        loan_product_id,
                        SUM(disbursed_loan_amount) - SUM(princ_paid) AS total,
                        ARRAY_AGG(json_build_object(
                            'id', id,
                            'name', name,
                            'telephone', telephone,
                            'member_number', member_number,
                            'old_member_number', old_member_number,
                            'loan_sector_name', loan_sector_name,
                            'loan_amount', loan_amount,
                            'disbursed_loan_amount', disbursed_loan_amount,
                            'princ_expected', princ_expected,
                            'int_expected', int_expected,
                            'loan_date', loan_date,
                            'loan_start_date', loan_start_date,
                            'int_waivered', int_waivered,
                            'princ_paid', princ_paid,
                            'int_paid', int_paid,
                            'int_paid_with_waiver', int_paid + int_waivered,
                            'total_paid', total_paid,
                            'penalty_paid', penalty_paid,
                            'total_paid_with_penalty', total_paid + penalty_paid,
                            'branch_name', branch_name,
                            'gender', gender,
                            'princ_bal', princ_expected - princ_paid,
                            'int_bal', int_expected - (int_paid + int_waivered),
                            'penalty_bal', total_penalty - penalty_paid,
                            'total_bal', ( (int_expected + princ_expected) -  total_paid ),
                            'total_bal_with_penalty', ( (int_expected + princ_expected + total_penalty) -  (total_paid + penalty_paid ) ),
                            'int_rate', int_rate,
                            'app_grace_period', app_grace_period,
                            'grace_period_type', grace_period_type,
                            'loan_period', loan_period,
                            'period_type', period_type,
                            'loan_officer_full_name', loan_officer_full_name,
                            'loan_requester_full_name', loan_requester.loan_requester_full_name,
                            'loan_approver_full_name', loan_approver.loan_approver_full_name,
                            'loan_disburser_full_name', loan_disburser.loan_disburser_full_name
                        )) AS loans
                    FROM
                        public.get_loan_tracking_data({organisation_id}, '{as_at}', '{loan_filter}') AS lv
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_requester_full_name
                        FROM loan_applications la
                        JOIN users_user uu ON uu.id = la.loan_app_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE la.id = lv.id AND la.deleted = false AND la.is_deleted = false
                        LIMIT 1
                    ) loan_requester ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_approver_full_name
                        FROM loan_application_approval laa
                        JOIN users_user uu ON uu.id = laa.loan_approval_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE laa.loan_application_id = lv.id AND laa.deleted = false
                        LIMIT 1
                    ) loan_approver ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_disburser_full_name
                        FROM loan_application_disbursement lad
                        JOIN users_user uu ON uu.id = lad.loan_disburse_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE lad.loan_application_id = lv.id AND lad.deleted = false
                        LIMIT 1
                    ) loan_disburser ON true
                    GROUP BY
                        loan_sector_id, loan_product_id
                )
                SELECT
                    json_build_object(
                        'filter_1', ad.loan_sector_id,
                        'filter_1_name', b.name,
                        'filter_2', ad.loan_product_id,
                        'filter_2_name', lp.product_name,
                        'total', ad.total,
                        'loans', ad.loans
                    ) AS branch_data
                FROM
                    aggregated_data ad
                JOIN
                    loan_sectors b ON ad.loan_sector_id = b.id
                JOIN loan_products lp ON ad.loan_product_id = lp.id
                ORDER BY ad.loan_sector_id;
            """
        cursor.execute(query)

        # Fetch all rows
        rows = cursor.fetchall()
        response = []
        branch_map = {}

        for row in rows:
            loan_sector_id = row[0]['filter_1']
            sectore_name = row[0]['filter_1_name']
            loan_product_id = row[0]['filter_2']
            product_name = row[0]['filter_2_name']

            # Check if the branch_id is already in the response
            if loan_sector_id not in branch_map:
                # Create a new entry for the branch
                branch_entry = {
                    'filter_1': loan_sector_id,
                    'filter_1_name': sectore_name,
                    'filter_2': []
                }
                branch_map[loan_sector_id] = branch_entry
                response.append(branch_entry)

            # Get the current branch entry
            branch_entry = branch_map[loan_sector_id]

            # Add the loan product entry to filter_2
            loan_product_entry = {
                'filter_2': loan_product_id,
                'filter_2_name': product_name,
                'total': row[0]['total'],
                'loans': row[0]['loans']
            }

            branch_entry['filter_2'].append(loan_product_entry)
        return response


def filter_tracking_gender_product(organisation_id, loan_filter, as_at):
    with connection.cursor() as cursor:
        query = f"""
                WITH aggregated_data AS (
                    SELECT
                        loan_product_id,
                        gender,
                        SUM(disbursed_loan_amount) - SUM(princ_paid) AS total,
                        ARRAY_AGG(json_build_object(
                            'id', id,
                            'name', name,
                            'telephone', telephone,
                            'member_number', member_number,
                            'old_member_number', old_member_number,
                            'loan_sector_name', loan_sector_name,
                            'loan_amount', loan_amount,
                            'disbursed_loan_amount', disbursed_loan_amount,
                            'princ_expected', princ_expected,
                            'int_expected', int_expected,
                            'loan_date', loan_date,
                            'loan_start_date', loan_start_date,
                            'int_waivered', int_waivered,
                            'princ_paid', princ_paid,
                            'int_paid', int_paid,
                            'int_paid_with_waiver', int_paid + int_waivered,
                            'total_paid', total_paid,
                            'penalty_paid', penalty_paid,
                            'total_paid_with_penalty', total_paid + penalty_paid,
                            'branch_name', branch_name,
                            'gender', gender,
                            'princ_bal', princ_expected - princ_paid,
                            'int_bal', int_expected - (int_paid + int_waivered),
                            'penalty_bal', total_penalty - penalty_paid,
                            'total_bal', ( (int_expected + princ_expected) -  total_paid ),
                            'total_bal_with_penalty', ( (int_expected + princ_expected + total_penalty) -  (total_paid + penalty_paid ) ),
                            'int_rate', int_rate,
                            'app_grace_period', app_grace_period,
                            'grace_period_type', grace_period_type,
                            'loan_period', loan_period,
                            'period_type', period_type,
                            'loan_officer_full_name', loan_officer_full_name,
                            'loan_requester_full_name', loan_requester.loan_requester_full_name,
                            'loan_approver_full_name', loan_approver.loan_approver_full_name,
                            'loan_disburser_full_name', loan_disburser.loan_disburser_full_name
                        )) AS loans
                    FROM
                        public.get_loan_tracking_data({organisation_id}, '{as_at}', '{loan_filter}') AS lv
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_requester_full_name
                        FROM loan_applications la
                        JOIN users_user uu ON uu.id = la.loan_app_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE la.id = lv.id AND la.deleted = false AND la.is_deleted = false
                        LIMIT 1
                    ) loan_requester ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_approver_full_name
                        FROM loan_application_approval laa
                        JOIN users_user uu ON uu.id = laa.loan_approval_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE laa.loan_application_id = lv.id AND laa.deleted = false
                        LIMIT 1
                    ) loan_approver ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_disburser_full_name
                        FROM loan_application_disbursement lad
                        JOIN users_user uu ON uu.id = lad.loan_disburse_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE lad.loan_application_id = lv.id AND lad.deleted = false
                        LIMIT 1
                    ) loan_disburser ON true
                    GROUP BY
                        loan_product_id, gender
                )
                SELECT
                    json_build_object(
                        'filter_1', ad.loan_product_id,
                        'filter_1_name', b.product_name,
                        'filter_2', ad.gender,
                        'filter_2_name', CASE 
                                WHEN ad.gender = 'M' THEN 'Male' 
                                WHEN ad.gender = 'F' THEN 'Female'
                                WHEN ad.gender = 'O' THEN 'Others' 
                                ELSE 'Others'
                             END,
                        'total', ad.total,
                        'loans', ad.loans
                    ) AS branch_data
                FROM
                    aggregated_data ad
                JOIN
                    loan_products b ON ad.loan_product_id = b.id
                ORDER BY ad.loan_product_id;
            """
        cursor.execute(query)

        # Fetch all rows
        rows = cursor.fetchall()
        response = []
        branch_map = {}

        for row in rows:
            loan_product_id = row[0]['filter_1']
            product_name = row[0]['filter_1_name']
            gender_id = row[0]['filter_2']
            gender_name = row[0]['filter_2_name']

            # Check if the branch_id is already in the response
            if loan_product_id not in branch_map:
                # Create a new entry for the branch
                branch_entry = {
                    'filter_1': loan_product_id,
                    'filter_1_name': product_name,
                    'filter_2': []
                }
                branch_map[loan_product_id] = branch_entry
                response.append(branch_entry)

            # Get the current branch entry
            branch_entry = branch_map[loan_product_id]

            # Add the loan product entry to filter_2
            loan_product_entry = {
                'filter_2': gender_id,
                'filter_2_name': gender_name,
                'total': row[0]['total'],
                'loans': row[0]['loans']
            }

            branch_entry['filter_2'].append(loan_product_entry)
        return response


def filter_tracking_gender_branch(organisation_id, loan_filter, as_at):
    with connection.cursor() as cursor:
        query = f"""
                WITH aggregated_data AS (
                    SELECT
                        branch_id,
                        gender,
                        SUM(disbursed_loan_amount) - SUM(princ_paid) AS total,
                        ARRAY_AGG(json_build_object(
                            'id', id,
                            'name', name,
                            'telephone', telephone,
                            'member_number', member_number,
                            'old_member_number', old_member_number,
                            'loan_sector_name', loan_sector_name,
                            'loan_amount', loan_amount,
                            'disbursed_loan_amount', disbursed_loan_amount,
                            'princ_expected', princ_expected,
                            'int_expected', int_expected,
                            'loan_date', loan_date,
                            'loan_start_date', loan_start_date,
                            'int_waivered', int_waivered,
                            'princ_paid', princ_paid,
                            'int_paid', int_paid,
                            'int_paid_with_waiver', int_paid + int_waivered,
                            'total_paid', total_paid,
                            'penalty_paid', penalty_paid,
                            'total_paid_with_penalty', total_paid + penalty_paid,
                            'branch_name', branch_name,
                            'gender', gender,
                            'princ_bal', princ_expected - princ_paid,
                            'int_bal', int_expected - (int_paid + int_waivered),
                            'penalty_bal', total_penalty - penalty_paid,
                            'total_bal', ( (int_expected + princ_expected) -  total_paid ),
                            'total_bal_with_penalty', ( (int_expected + princ_expected + total_penalty) -  (total_paid + penalty_paid ) ),
                            'int_rate', int_rate,
                            'app_grace_period', app_grace_period,
                            'grace_period_type', grace_period_type,
                            'loan_period', loan_period,
                            'period_type', period_type,
                            'loan_officer_full_name', loan_officer_full_name,
                            'loan_requester_full_name', loan_requester.loan_requester_full_name,
                            'loan_approver_full_name', loan_approver.loan_approver_full_name,
                            'loan_disburser_full_name', loan_disburser.loan_disburser_full_name
                        )) AS loans
                    FROM
                        public.get_loan_tracking_data({organisation_id}, '{as_at}', '{loan_filter}') AS lv
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_requester_full_name
                        FROM loan_applications la
                        JOIN users_user uu ON uu.id = la.loan_app_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE la.id = lv.id AND la.deleted = false AND la.is_deleted = false
                        LIMIT 1
                    ) loan_requester ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_approver_full_name
                        FROM loan_application_approval laa
                        JOIN users_user uu ON uu.id = laa.loan_approval_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE laa.loan_application_id = lv.id AND laa.deleted = false
                        LIMIT 1
                    ) loan_approver ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_disburser_full_name
                        FROM loan_application_disbursement lad
                        JOIN users_user uu ON uu.id = lad.loan_disburse_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE lad.loan_application_id = lv.id AND lad.deleted = false
                        LIMIT 1
                    ) loan_disburser ON true
                    GROUP BY
                        branch_id, gender
                )
                SELECT
                    json_build_object(
                        'filter_1', ad.branch_id,
                        'filter_1_name', b.name,
                        'filter_2', ad.gender,
                        'filter_2_name', CASE 
                                WHEN ad.gender = 'M' THEN 'Male'
                                WHEN ad.gender = 'F' THEN 'Female'
                                WHEN ad.gender = 'O' THEN 'Others'
                                ELSE 'Others'
                             END,
                        'total', ad.total,
                        'loans', ad.loans
                    ) AS branch_data
                FROM
                    aggregated_data ad
                JOIN
                    organisation_branch b ON ad.branch_id = b.id
                ORDER BY ad.branch_id;
            """
        cursor.execute(query)

        # Fetch all rows
        rows = cursor.fetchall()
        response = []
        branch_map = {}

        for row in rows:
            branch_id = row[0]['filter_1']
            branch_name = row[0]['filter_1_name']
            gender_id = row[0]['filter_2']
            gender_name = row[0]['filter_2_name']

            # Check if the branch_id is already in the response
            if branch_id not in branch_map:
                # Create a new entry for the branch
                branch_entry = {
                    'filter_1': branch_id,
                    'filter_1_name': branch_name,
                    'filter_2': []
                }
                branch_map[branch_id] = branch_entry
                response.append(branch_entry)

            # Get the current branch entry
            branch_entry = branch_map[branch_id]

            # Add the loan product entry to filter_2
            loan_product_entry = {
                'filter_2': gender_id,
                'filter_2_name': gender_name,
                'total': row[0]['total'],
                'loans': row[0]['loans']
            }

            branch_entry['filter_2'].append(loan_product_entry)
        return response


def filter_tracking_gender_officer(organisation_id, loan_filter, as_at):
    with connection.cursor() as cursor:
        query = f"""
                WITH aggregated_data AS (
                    SELECT
                        loan_officer_id,
                        gender,
                        SUM(disbursed_loan_amount) - SUM(princ_paid) AS total,
                        ARRAY_AGG(json_build_object(
                            'id', id,
                            'name', name,
                            'telephone', telephone,
                            'member_number', member_number,
                            'old_member_number', old_member_number,
                            'loan_sector_name', loan_sector_name,
                            'loan_amount', loan_amount,
                            'disbursed_loan_amount', disbursed_loan_amount,
                            'princ_expected', princ_expected,
                            'int_expected', int_expected,
                            'loan_date', loan_date,
                            'loan_start_date', loan_start_date,
                            'int_waivered', int_waivered,
                            'princ_paid', princ_paid,
                            'int_paid', int_paid,
                            'int_paid_with_waiver', int_paid + int_waivered,
                            'total_paid', total_paid,
                            'penalty_paid', penalty_paid,
                            'total_paid_with_penalty', total_paid + penalty_paid,
                            'branch_name', branch_name,
                            'gender', gender,
                            'princ_bal', princ_expected - princ_paid,
                            'int_bal', int_expected - (int_paid + int_waivered),
                            'penalty_bal', total_penalty - penalty_paid,
                            'total_bal', ( (int_expected + princ_expected) -  total_paid ),
                            'total_bal_with_penalty', ( (int_expected + princ_expected + total_penalty) -  (total_paid + penalty_paid ) ),
                            'int_rate', int_rate,
                            'app_grace_period', app_grace_period,
                            'grace_period_type', grace_period_type,
                            'loan_period', loan_period,
                            'period_type', period_type,
                            'loan_officer_full_name', loan_officer_full_name,
                            'loan_requester_full_name', loan_requester.loan_requester_full_name,
                            'loan_approver_full_name', loan_approver.loan_approver_full_name,
                            'loan_disburser_full_name', loan_disburser.loan_disburser_full_name
                        )) AS loans
                    FROM
                        public.get_loan_tracking_data({organisation_id}, '{as_at}', '{loan_filter}') AS lv
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_requester_full_name
                        FROM loan_applications la
                        JOIN users_user uu ON uu.id = la.loan_app_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE la.id = lv.id AND la.deleted = false AND la.is_deleted = false
                        LIMIT 1
                    ) loan_requester ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_approver_full_name
                        FROM loan_application_approval laa
                        JOIN users_user uu ON uu.id = laa.loan_approval_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE laa.loan_application_id = lv.id AND laa.deleted = false
                        LIMIT 1
                    ) loan_approver ON true
                    LEFT JOIN LATERAL (
                        SELECT s.name AS loan_disburser_full_name
                        FROM loan_application_disbursement lad
                        JOIN users_user uu ON uu.id = lad.loan_disburse_added_by_id
                        JOIN staff s ON s.id = uu.user_staff_id
                        WHERE lad.loan_application_id = lv.id AND lad.deleted = false
                        LIMIT 1
                    ) loan_disburser ON true
                    GROUP BY
                        loan_officer_id, gender
                )
                SELECT
                    json_build_object(
                        'filter_1', ad.loan_officer_id,
                        'filter_1_name', b.name,
                        'filter_2', ad.gender,
                        'filter_2_name', CASE 
                                WHEN ad.gender = 'M' THEN 'Male'
                                WHEN ad.gender = 'F' THEN 'Female'
                                WHEN ad.gender = 'O' THEN 'Others'
                                ELSE 'Others'
                             END,
                        'total', ad.total,
                        'loans', ad.loans
                    ) AS branch_data
                FROM
                    aggregated_data ad
                JOIN
                    staff b ON ad.loan_officer_id = b.id
                ORDER BY ad.loan_officer_id;
            """
        cursor.execute(query)

        # Fetch all rows
        rows = cursor.fetchall()
        response = []
        branch_map = {}

        for row in rows:
            loan_officer_id = row[0]['filter_1']
            staff_name = row[0]['filter_1_name']
            gender_id = row[0]['filter_2']
            gender_name = row[0]['filter_2_name']

            # Check if the branch_id is already in the response
            if loan_officer_id not in branch_map:
                # Create a new entry for the branch
                branch_entry = {
                    'filter_1': loan_officer_id,
                    'filter_1_name': staff_name,
                    'filter_2': []
                }
                branch_map[loan_officer_id] = branch_entry
                response.append(branch_entry)

            # Get the current branch entry
            branch_entry = branch_map[loan_officer_id]

            # Add the loan product entry to filter_2
            loan_product_entry = {
                'filter_2': gender_id,
                'filter_2_name': gender_name,
                'total': row[0]['total'],
                'loans': row[0]['loans']
            }

            branch_entry['filter_2'].append(loan_product_entry)
        return response