<?php

namespace App\Http\Controllers\Admin\Odoo;

use App\Http\Controllers\Controller;
use Auth;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\PartnerData;
use Illuminate\Support\Facades\Log;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

class OdooController extends Controller
{
    private $request;

    private $creditAmountStepKey = [];

    public function __construct(Request $request)
    {
        $this->request = $request;
    }

    public static function registry(){
        return [
            [
                'name'    => 'Odoo Partners',
                'summary' => 'Manage Odoo partners configurations and details.',
                'url'     => '/admin/odoo',
            ],
            [
                'name'    => 'Odoo JVs',
                'summary' => 'Manage Odoo JVs configurations and details.',
                'url'     => '/admin/odoo/jvs',
            ],
            [
                'name'    => 'Odoo Dashboard',
                'summary' => 'Manage Odoo dashborad configurations and details.'
            ],
        ];
    }

    public function index()
    {
        $fromDate = $this->request->get('from_date');
        $toDate = $this->request->get('to_date');

        $query = PartnerData::with(['odooDetail', 'parent'])->whereNotNull('sub_partner_id');

        if ($fromDate) {
            $query->whereDate('created_at', '>=', $fromDate);
        }
        if ($toDate) {
            $query->whereDate('created_at', '<=', $toDate);
        }

        $partners = $query->orderBy('id', 'desc')->paginate(20);

        return view('admin.odoo.generate-odoo', compact('partners', 'fromDate', 'toDate'));
    }

    public function jvs()
    {
        $fromDate = $this->request->get('from_date', \Carbon\Carbon::now()->subWeek()->format('Y-m-d'));
        $toDate = $this->request->get('to_date', \Carbon\Carbon::now()->format('Y-m-d'));

        $query = \App\DaSystemData::query();

        if ($fromDate) {
            $query->whereDate('created_at', '>=', $fromDate);
        }
        if ($toDate) {
            $query->whereDate('created_at', '<=', $toDate);
        }

        $applications = $query->orderBy('id', 'desc')->paginate(20);

        return view('admin.odoo.jvs', compact('applications', 'fromDate', 'toDate'));
    }

    public function getJvStepsAjax()
    {
        $applicationId = $this->request->get('application_id');
        if (!$applicationId) {
            return response()->json([
                'status' => 'error',
                'message' => 'application_id is required'
            ], 400);
        }

        $application = \App\DaSystemData::with('partner')->find($applicationId);
        if (!$application) {
            return response()->json([
                'status' => 'error',
                'message' => 'DA System record not found'
            ], 404);
        }

        $partner = $application->partner;
        $partnerName = $application->member_name ?? '';
        $partnerUniqueCode = strtoupper(substr(trim($application->member_name ?? 'CUST'), 0, 3)) . '-' . $application->id;
        
        if ($partner) {
            $partnerName = $partner->name ?? ($application->member_name ?? '');
            $partnerUniqueCode = strtoupper(substr(trim($partner->name), 0, 3)) . '-' . $partner->id;
        }

        $month = $this->request->get('month') ?? Carbon::now()->format('m');
        $year = $this->request->get('year') ?? Carbon::now()->format('Y');

        $loan_data = $this->fetchLoanData($application->loan_no, $month, $year);

        $data = [
            'applicationId' => $applicationId,
            'partnerName' => $partnerName,
            'partnerUniqueCode' => $partnerUniqueCode,
            'application' => $application,
            'loan_data' => $loan_data,
            'month' => $month,
            'year' => $year
        ];

        $jvSections = $this->getJvSteps();
        $calculatedSections = [];

        foreach ($jvSections as $section) {
            $calculatedSteps = [];
            foreach ($section['steps'] as $step) {
                // Call getStepsWithCalculation to calculate the real amount based on gl_code
                $calculatedEntries = $this->getStepsWithCalculation($step['id'], $data);

                $originalEntries = $step['entries'];
                $finalEntries = [];
                $totalDebit = 0;
                $totalCredit = 0;

                foreach ($calculatedEntries as $index => $calcEntry) {
                    $orig = $originalEntries[$index] ?? null;

                    $debitVal = isset($calcEntry['debit']) ? (float)$calcEntry['debit'] : 0.0;
                    $creditVal = isset($calcEntry['credit']) ? (float)$calcEntry['credit'] : 0.0;

                    $totalDebit += $debitVal;
                    $totalCredit += $creditVal;

                    $finalEntries[] = [
                        'type' => $orig ? $orig['type'] : ($debitVal > 0 ? 'Dr' : 'Cr'),
                        'account' => $orig ? $orig['account'] : 'Unknown',
                        'gl_code' => $calcEntry['gl_code'] ?? ($orig ? $orig['gl_code'] : ''),
                        'sequence' => $calcEntry['sequence'] ?? ($orig ? $orig['sequence'] : ($index + 1)),
                        'debit' => $debitVal,
                        'credit' => $creditVal,
                        'summary' => $orig && isset($orig['summary']) ? $orig['summary'] : '',
                    ];
                }

                // Check if already completed in odoo_jv_logs
                $queryLog = \DB::table('odoo_jv_logs')
                    ->where('application_id', $applicationId)
                    ->where('step_key', $step['id'])
                    ->where('status', 'success');

                if ($step['id'] !== 'disbursement_pv') {
                    $queryLog->where('month', $month)->where('year', $year);
                }

                $isCompleted = $queryLog->exists();

                $isMismatch = (abs($totalDebit - $totalCredit) > 0.01) || ($totalDebit == 0 && $totalCredit == 0);

                $calculatedSteps[] = [
                    'id' => $step['id'],
                    'voucher_type' => $step['voucher_type'],
                    'entries' => $finalEntries,
                    'is_mismatch' => $isMismatch,
                    'is_completed' => $isCompleted,
                    'total_debit' => $totalDebit,
                    'total_credit' => $totalCredit,
                    'diff' => abs($totalDebit - $totalCredit)
                ];
            }

            $calculatedSections[] = [
                'section' => $section['section'],
                'steps' => $calculatedSteps
            ];
        }

        return response()->json([
            'status' => 'success',
            'data' => $calculatedSections
        ]);
    }

    public function createJv()
    {
        try {
            $applicationId = $this->request->get('application_id');
            $stepKey = $this->request->get('step_key');
            $month = $this->request->get('month') ?? Carbon::now()->format('m');
            $year = $this->request->get('year') ?? Carbon::now()->format('Y');

            if (!$applicationId || !$stepKey) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'application_id and JV are required'
                ], 400);
            }

            $application = \App\DaSystemData::with('partner')->find($applicationId);
            if (!$application) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'DA System record not found'
                ], 404);
            }

            // Check if already completed in odoo_jv_logs
            $queryCheck = \DB::table('odoo_jv_logs')
                ->where('application_id', $applicationId)
                ->where('step_key', $stepKey)
                ->where('status', 'success');

            if ($stepKey !== 'disbursement_pv') {
                $queryCheck->where('month', $month)->where('year', $year);
            }

            if ($queryCheck->exists()) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'JV entry has already been successfully created for this period.'
                ], 400);
            }

            $partner = $application->partner;

            $partnerName = $application->member_name ?? '';
            $partnerUniqueCode = strtoupper(substr(trim($application->member_name ?? 'CUST'), 0, 3)) . '-' . $application->id;
            
            if ($partner) {
                $partnerName = $partner->name ?? ($application->member_name ?? '');
                $partnerUniqueCode = strtoupper(substr(trim($partner->name), 0, 3)) . '-' . $partner->id;
            }

            $txNo = "TXN_" . date('YmdHis') . "_" . $stepKey . "_" . $applicationId;
            $postingDate = \Carbon\Carbon::now()->format('Y-m-d');
            
            $loan_data = $this->fetchLoanData($application->loan_no, $month, $year);

            $lines = $this->getStepsWithCalculation($stepKey, [
                'applicationId' => $applicationId,
                'partnerName' => $partnerName,
                'partnerUniqueCode' => $partnerUniqueCode,
                'application' => $application,
                'loan_data' => $loan_data
            ]);

            $payload = [
                "transaction_number" => $txNo,
                "posting_date"       => $postingDate,
                "company_name"       => "BLACKSOIL CAPITAL PRIVATE LIMITED",
                "type"               => "payment",
                "lines"              => $lines
            ];

            $odooService = new \App\Odoo\OdooService();
            $apiResult = $odooService->createJvEntry($payload);

            $statusCode = $apiResult['http_code'];
            $responseData = is_array($apiResult['response']) ? $apiResult['response'] : json_decode($apiResult['response'], true);
            $body = is_string($apiResult['response']) ? $apiResult['response'] : json_encode($apiResult['response']);

            if ($statusCode >= 200 && $statusCode < 300) {
                // Record log
                $totalAmount = 0.0;
                foreach ($lines as $line) {
                    $totalAmount += (float)($line['debit'] ?? 0.0);
                }

                $odooMoveId = $responseData['odoo_move_id'] ?? null;
                $odooVoucherNumber = $responseData['odoo_voucher_number'] ?? null;

                $logId = \DB::table('odoo_jv_logs')->insertGetId([
                    'application_id' => $applicationId,
                    'step_key' => $stepKey,
                    'month' => $month,
                    'year' => $year,
                    'amount' => $totalAmount,
                    'status' => 'success',
                    'transaction_number' => $txNo,
                    'odoo_move_id' => $odooMoveId,
                    'odoo_voucher_number' => $odooVoucherNumber,
                    'created_by' => Auth::check() ? Auth::user()->id : 107,
                    'odoo_response' => $body,
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ]);

                // Record line-level logs
                $respLines = $responseData['lines'] ?? [];
                // Group response lines by sequence for easy lookup
                $respLinesBySeq = [];
                foreach ($respLines as $rLine) {
                    if (isset($rLine['sequence'])) {
                        $respLinesBySeq[$rLine['sequence']] = $rLine;
                    }
                }

                foreach ($lines as $line) {
                    $seq = $line['sequence'] ?? null;
                    $moveLineId = null;
                    if ($seq && isset($respLinesBySeq[$seq])) {
                        $moveLineId = $respLinesBySeq[$seq]['move_line_id'] ?? null;
                    }

                    \DB::table('odoo_jv_line_logs')->insert([
                        'odoo_jv_log_id' => $logId,
                        'sequence' => $seq ?? 0,
                        'move_line_id' => $moveLineId ?? 0,
                        'gl_code' => $line['gl_code'] ?? null,
                        'account' => $line['account'] ?? null,
                        'debit' => (float)($line['debit'] ?? 0.0),
                        'credit' => (float)($line['credit'] ?? 0.0),
                        'created_at' => Carbon::now(),
                        'updated_at' => Carbon::now(),
                    ]);
                }

                return response()->json([
                    'status'  => 'success',
                    'message' => 'Successfully created JV in Odoo for JvKey ' . $stepKey,
                    'data'    => $responseData,
                ], $statusCode);
            } else {
                $errorMsg = 'Failed to create JV in Odoo';
                if (is_array($responseData) && isset($responseData['message'])) {
                    $errorMsg = $responseData['message'];
                }

                return response()->json([
                    'status'  => 'error',
                    'message' => $errorMsg,
                    'error'   => $responseData ?? $body,
                ], $statusCode);
            }

        } catch (\Exception $e) {
            Log::error('Odoo createJv Exception: ' . $e->getMessage(), [
                'trace' => $e->getTraceAsString()
            ]);

            return response()->json([
                'status'  => 'error',
                'message' => 'An internal error occurred',
                'error'   => $e->getMessage(),
            ], 500);
        }
    }


    public function getStepsWithCalculation($stepKey,$data){
        $this->creditAmountStepKey[$stepKey] = 0;
        $steps = $this->getJvSteps($stepKey);


        $lines = array_map(function ($step) use ($data, $stepKey) {
            $line = [
                "sequence"            => $step['sequence'],
                "gl_code"             => $step['gl_code'],
                "reference"           => "REF" . $data['applicationId'],
                "partner_name"        => $data['partnerName'],
                "partner_unique_code" => $data['partnerUniqueCode']
            ];

            $line = array_merge($line, $this->calculateJvAmount($stepKey, $step['gl_code'], $data['application'], $data['loan_data'], $step['type'] ?? 'Dr'));

            return $line;
        }, $steps);

        return $lines;
    }

    /**
     * Calculate JV amount based on GL code
     */
    private function calculateJvAmount($stepKey, $glCode, $application, $loanData, $type = 'Dr')
    {
        $glCode = (string)$glCode;

        // Determine if this is a balancing credit entry that consumes the accumulated debit amounts
        $isBalancingCredit = (
            ($stepKey === 'disbursement_pv' && $glCode === '100201') ||
            ($stepKey === 'loan_processing_fee_gst_invoice' && $glCode === '154005') ||
            ($stepKey === 'lpf_received_rv' && $glCode === '154005') || 
            ($stepKey === 'penal_charges_jv' && $glCode === '303006') || 
            ($stepKey === 'interest_due_for_the_month' && $glCode === '303004')
        );

        if ($isBalancingCredit) {
            if ($type === 'Cr') {
                $amount = $this->creditAmountStepKey[$stepKey] ?? 0.0;
                return ['credit' => (float)$amount, 'debit' => 0.0];
            }
            return ['credit' => 0.0, 'debit' => 0.0];
        }

        $amount = 0.0;

        switch ($stepKey) {
            case 'disbursement_pv':
                if ($glCode === '133001') {
                    $amount = (float)($application->disbursement_amount ?? $application->principal_total ?? 0);
                }
                break;

            case 'loan_processing_fee_gst_invoice':
                if ($glCode === '300007') {
                    $amount = (float)($application->processing_fee ?? 0);
                } elseif ($glCode === '300002') {
                    $amount = (float)($application->document_charges ?? 0);
                }
                break;

            case 'lpf_received_rv':
                if ($glCode === '160002') {
                    $amount = (float)($application->processing_fee ?? 0);
                }
                break;
            case 'penal_charges_jv':
                if ($glCode === '151001') {
                    $amount = (float)($loanData[0]->penal_charges_received ?? 0);
                }
                break;
            case 'interest_due_for_the_month':
                if ($glCode === '145000') {
                    $amount = (float)($loanData[0]->interest_due ?? 0);
                }
                break;
            case 'emi_amount_received':
                if ($glCode === '160002') {
                    $amount = (float)($loanData[0]->total_emi_received ?? 0);
                }else if ($glCode === '145000') {
                    $amount = (float)($loanData[0]->total_interest_received ?? 0);
                }else if ($glCode === '133001') {
                    $amount = (float)($loanData[0]->total_principal_received ?? 0);
                }
                break;
        }

        if ($amount > 0) {
            $this->updateCreditAmountThroughStepKey($stepKey, $amount);
        }

        if ($type === 'Dr') {
            return ['debit' => $amount, 'credit' => 0.0];
        } else {
            return ['credit' => $amount, 'debit' => 0.0];
        }
    }

    public function updateCreditAmountThroughStepKey($stepKey, $amount){
        if(isset($this->creditAmountStepKey[$stepKey])){
            $this->creditAmountStepKey[$stepKey] += $amount;
        }else{
            $this->creditAmountStepKey[$stepKey] = $amount;
        }
    }

    private function fetchLoanData($loanNo, $month, $year)
    {
        if (!$loanNo) {
            return [];
        }
        
        $query = "with payment_agg as (
    select
        loan_id,
        DATE_FORMAT(payment_date, '%Y-%m') AS payment_month_year,
        SUM(CASE WHEN payment_for = 'principal' THEN amount ELSE 0 END) AS principal_received,
        SUM(CASE WHEN payment_for = 'interest' THEN amount ELSE 0 END) AS interest_received,
        SUM(CASE WHEN payment_for = 'overdue_principal' THEN amount ELSE 0 END) AS overdue_principal_received,
        SUM(CASE WHEN payment_for = 'overdue_interest' THEN amount ELSE 0 END) AS overdue_interest_received,
        SUM(CASE WHEN payment_for = 'penal_charges' THEN amount ELSE 0 END) AS penal_charges_received

    from blacksoil_payment_transactions
    WHERE (is_deleted_at IS NULL AND deleted_at IS NULL AND refunded_at IS NULL) 
    AND payment_for in ('principal','interest','overdue_principal','overdue_interest','penal_charges')
    GROUP BY loan_id, cust_id, DATE_FORMAT(payment_date, '%Y-%m')
)

,bep as (
    select loan_id, DATE_FORMAT(emi_date, '%Y-%m') AS emi_month_year, interest_due
    from blacksoil_emi_payments
    where blacksoil_emi_payments.deleted_at is null
)



select bep.loan_id, interest_due, 
interest_received + overdue_interest_received total_interest_received,
principal_received + overdue_principal_received total_principal_received,
principal_received + interest_received + overdue_interest_received + overdue_principal_received total_emi_received, 
penal_charges_received

from bep
left join payment_agg on payment_agg.loan_id = bep.loan_id and payment_agg.payment_month_year = bep.emi_month_year
where bep.loan_id = '".$loanNo."' and bep.emi_month_year = '".$year."-".$month."'";

        return \DB::select($query);
    }


    public function createCustomer()
    {
        try {
            $partnerId = $this->request->get('partner_id');
            if (!$partnerId) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'partner_id is required'
                ], 400);
            }

            $odooDetail = \App\OdooDetail::firstOrNew(['partner_id' => $partnerId]);
            if ($odooDetail->status === 'success' || $odooDetail->status === 'Customer already exists') {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Customer is already created in Odoo.'
                ], 400);
            }

            $partner = PartnerData::with('parent')->find($partnerId);

            if (!$partner) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Partner not found'
                ], 404);
            }

            $payload = $this->mapPartnerToOdooPayload($partner);

            $odooService = new \App\Odoo\OdooService();
            $apiResult = $odooService->createCustomer($payload);

            if ($apiResult['http_code'] === 500 && isset($apiResult['message'])) {
                return response()->json([
                    'status' => 'error',
                    'message' => $apiResult['message'],
                    'error' => null
                ], 500);
            }

            $statusCode = $apiResult['http_code'];
            $responseData = is_array($apiResult['response']) ? $apiResult['response'] : json_decode($apiResult['response'], true);
            
            // Reassign $body for fallback error response later
            $body = is_string($apiResult['response']) ? $apiResult['response'] : json_encode($apiResult['response']);
            $odooDetail->api_response = $body;
            $odooDetail->created_by = Auth::user()->id ?? 107;

            if ($statusCode >= 200 && $statusCode < 300) {
                $odooDetail->status = 'success';
                if (isset($responseData['customer']['customer_id'])) {
                    $odooDetail->odoo_customer_id = $responseData['customer']['customer_id'];
                }
                $odooDetail->save();

                return response()->json([
                    'status' => 'success',
                    'message' => 'Successfully created customer in Odoo',
                    'data' => $responseData,
                ], $statusCode);
            } else {
                if (isset($responseData['message']) && $responseData['message'] === 'Customer already exists') {
                    $odooDetail->status = 'Customer already exists';
                } else {
                    $odooDetail->status = 'failed';
                }
                $odooDetail->save();

                $errorMsg = 'Failed to create customer in Odoo';
                if (is_array($responseData) && isset($responseData['message'])) {
                    $errorMsg = $responseData['message'];
                }

                return response()->json([
                    'status' => 'error',
                    'message' => $errorMsg,
                    'error' => $responseData ?? $body,
                ], $statusCode);
            }

        } catch (\Exception $e) {
            Log::error('Odoo createCustomer Exception: ' . $e->getMessage(), [
                'trace' => $e->getTraceAsString()
            ]);

            return response()->json([
                'status' => 'error',
                'message' => 'An internal error occurred',
                'error' => $e->getMessage(),
            ], 500);
        }
    }

    private function mapPartnerToOdooPayload(PartnerData $partner)
    {
        $payload = $this->buildPartnerData($partner);

        // Map parent if exists
        if ($partner->parent) {
            $payload['parent_company'] = $this->buildPartnerData($partner->parent);
        } else {
            $payload['parent_company'] = new \stdClass();
        }

        return $payload;
    }

    private function buildPartnerData(PartnerData $partner)
    {
        $uniqueCode = strtoupper(substr(trim($partner->name), 0, 3)) . '-' . $partner->id;

        return [
            "name"                => $partner->name ?? "",
            "phone"               => $partner->mobile ?? "",
            "email"               => $partner->email ?? "",
            "vat"                 => $partner->gstn ?? "",
            "pan"                 => $partner->pan ?? "",
            "tan"                 => $partner->tan ?? "",
            "gst_treatment"       => "regular",
            "company_name"        => $partner->company ?? "",
            "contact_type"        => "customer",
            "partner_unique_code" => $uniqueCode,
            "product"             => $partner->product ?? "",
            "source"              => $partner->source ?? "CreadFair", // Fallback to CreadFair if null
            "segment"             => $partner->industry ?? "Udhyam", // Mapped from industry, defaulting to Udhyam
            "address" => [
                "street"  => $partner->gst_address ?? "",
                "street2" => "",
                "city"    => $partner->city ?? "",
                "state"   => $partner->state ?? "",
                "country" => "India",
                "zip"     => $partner->zip ?? ""
            ]
        ];
    }

    public function getJvSteps($stepKey = '', $application = ''){

        $steps = [

            // ── 1. Disbursement ──────────────────────────────────────────────
            [
                'section' => 'Disbursement',
                'steps'   => [
                    [
                        'id'           => 'disbursement_pv',
                        'voucher_type' => 'Payment Voucher',
                        'disable_step' => false,
                        'entries'      => [
                            ['type' => 'Dr', 'account' => 'Loans and Advances', 'debit' => '0', 'credit' => '-', 'gl_code' => 133001, 'sequence' => 1, 'summary' => 'Disbursed Amount'],
                            ['type' => 'Cr', 'account' => 'Bank A/c',  'debit' => '-', 'credit' => '0', 'gl_code' => 100201, 'sequence' => 2, 'summary' => ''],
                        ],
                    ],
                ],
            ],

            // ── 2. Interest ───────────────────────────────────────────────────
            [
                'section' => 'Interest',
                'steps'   => [
                    [
                        'id'           => 'interest_accrued_not_due_month_end_jv',
                        'voucher_type' => 'Journal Voucher',
                        'disable_step' => true,
                        'entries'      => [
                            ['type' => 'Dr', 'account' => 'Interest Accrued and not due', 'debit' => '0', 'credit' => '-', 'gl_code' => 145001, 'sequence' => 1, 'summary' => ''],
                            ['type' => 'Cr', 'account' => 'Interest Income',               'debit' => '-',         'credit' => '0', 'gl_code' => 303004, 'sequence' => 2, 'summary' => ''],
                        ],
                    ],
                    [
                        'id'           => 'reversal_interest_accrued_not_due_jv',
                        'voucher_type' => 'Journal Voucher',
                        'disable_step' => true,
                        'entries'      => [
                            ['type' => 'Dr', 'account' => 'Interest Income',               'debit' => '0', 'credit' => '-', 'gl_code' => 303004, 'sequence' => 1, 'summary' => ''],
                            ['type' => 'Cr', 'account' => 'Interest Accrued and not due',  'debit' => '-',         'credit' => '0', 'gl_code' => 145001, 'sequence' => 2, 'summary' => ''],
                        ],
                    ],
                    [
                        'id'           => 'interest_due_for_the_month',
                        'voucher_type' => 'Journal Voucher',
                        'disable_step' => false,
                        'entries'      => [
                            ['type' => 'Dr', 'account' => 'Accrued Interest for Loans Due',               'debit' => '0', 'credit' => '-', 'gl_code' => 145000, 'sequence' => 1, 'summary' => 'Interest due for the month'],
                            ['type' => 'Cr', 'account' => 'Interest Income',  'debit' => '-',         'credit' => '0', 'gl_code' => 303004, 'sequence' => 2, 'summary' => ''],
                        ],
                    ],
                ],
            ],

            // ── 3. Penal Charges ─────────────────────────────────────────────
            [
                'section' => 'Penal Charges',
                'steps'   => [
                    [
                        'id'           => 'penal_charges_jv',
                        'voucher_type' => 'Journal Voucher',
                        'disable_step' => false,
                        'entries'      => [
                            ['type' => 'Dr', 'account' => 'Penal charges receivable', 'debit' => '0', 'credit' => '-', 'gl_code' => 151001, 'sequence' => 1, 'summary' => 'Penal charges received'],
                            ['type' => 'Cr', 'account' => 'Penal charges',             'debit' => '-',         'credit' => '0', 'gl_code' => 303006, 'sequence' => 2, 'summary' => ''],
                        ],
                    ],
                ],
            ],

            // ── 4. Foreclosure Charges ───────────────────────────────────────
            [
                'section' => 'Foreclosure Charges',
                'steps'   => [
                    [
                        'id'           => 'foreclosure_charges_jv',
                        'voucher_type' => 'Journal Voucher',
                        'disable_step' => true,
                        'entries'      => [
                            ['type' => 'Dr', 'account' => 'Forclosure charges receivable', 'debit' => '0', 'gl_code' => 1, 'credit' => '-', 'sequence' => 1, 'summary' => ''],
                            ['type' => 'Cr', 'account' => 'Forclosure charges',             'debit' => '-',         'credit' => '0', 'gl_code' => 1, 'sequence' => 2, 'summary' => ''],
                            ['type' => 'Cr', 'account' => 'IGST',                           'debit' => '-',         'credit' => '0', 'gl_code' => 115007, 'sequence' => 3, 'summary' => ''],
                            ['type' => 'Cr', 'account' => 'CGST',                           'debit' => '-',         'credit' => '0', 'gl_code' => 115002, 'sequence' => 4, 'summary' => ''],
                            ['type' => 'Cr', 'account' => 'SGST',                           'debit' => '-',         'credit' => '0', 'gl_code' => 115010, 'sequence' => 5, 'summary' => ''],
                        ],
                    ],
                ],
            ],

            // ── 5. Collections ───────────────────────────────────────────────
            [
                'section' => 'Collections',
                'steps'   => [
                    [
                        'id'           => 'collections_rv',
                        'voucher_type' => 'Receipt Voucher',
                        'disable_step' => true,
                        'entries'      => [
                            ['type' => 'Cr', 'account' => 'Interest Accrual',                       'debit' => '-',          'credit' => '0', 'gl_code' => 145000, 'sequence' => 1, 'summary' => ''],
                            ['type' => 'Cr', 'account' => 'Loans',                                  'debit' => '-',          'credit' => '0', 'gl_code' => 133001, 'sequence' => 2, 'summary' => ''],
                            ['type' => 'Cr', 'account' => 'Penal charges receivable',               'debit' => '-',          'credit' => '0', 'gl_code' => 1, 'sequence' => 3, 'summary' => ''],
                            ['type' => 'Cr', 'account' => 'Forclosure charges receivable',          'debit' => '-',          'credit' => '0', 'gl_code' => 1, 'sequence' => 4, 'summary' => ''],
                            ['type' => 'Cr', 'account' => 'Excess / advance received from customers','debit' => '-',         'credit' => '0', 'gl_code' => 236004, 'sequence' => 5, 'summary' => ''],
                            ['type' => 'Dr', 'account' => 'Bank A/c',                               'debit' => '0','credit' => '-', 'gl_code' => 100201, 'sequence' => 6, 'summary' => ''],
                        ],
                    ],
                    [
                        'id'           => 'refund_of_excess_pv',
                        'voucher_type' => 'Payment Voucher',
                        'disable_step' => true,
                        'entries'      => [
                            ['type' => 'Dr', 'account' => 'Excess / advance received from customers', 'debit' => '0', 'credit' => '-', 'gl_code' => 236004, 'sequence' => 1, 'summary' => ''],
                            ['type' => 'Cr', 'account' => 'Bank A/c',                                  'debit' => '-',         'credit' => '0', 'gl_code' => 100201, 'sequence' => 2, 'summary' => ''],
                        ],
                    ],
                    [
                        'id'           => 'emi_amount_received',
                        'voucher_type' => 'Payment Voucher',
                        'disable_step' => false,
                        'entries'      => [
                            ['type' => 'Cr', 'account' => 'Bank A/c',  'debit' => '-',  'credit' => '0', 'gl_code' => 160002, 'sequence' => 1, 'summary' => 'EMI received'],
                            ['type' => 'Dr', 'account' => 'Accrued Interest for Loans Due', 'debit' => '0', 'credit' => '-', 'gl_code' => 145000, 'sequence' => 2, 'summary' => 'Interest received'],
                            ['type' => 'Dr', 'account' => 'Loans and Advances', 'debit' => '0', 'credit' => '-', 'gl_code' => 133001, 'sequence' => 3, 'summary' => 'Principal received'],
                        ],
                    ],
                ],
            ],

            // ── 6. NPA / Bad Debts ───────────────────────────────────────────
            [
                'section' => 'NPA / Bad Debts',
                'steps'   => [
                    [
                        'id'           => 'bad_debts_written_off_jv',
                        'voucher_type' => 'Journal Voucher',
                        'disable_step' => true,
                        'entries'      => [
                            ['type' => 'Dr', 'account' => 'Bad Debts Written-Off', 'debit' => '0', 'credit' => '-', 'gl_code' => 418012, 'sequence' => 1, 'summary' => ''],
                            ['type' => 'Cr', 'account' => 'Loans A/c',             'debit' => '-',         'credit' => '0', 'gl_code' => 133001, 'sequence' => 2, 'summary' => ''],
                        ],
                    ],
                    [
                        'id'           => 'write_off_collections_rv',
                        'voucher_type' => 'Receipt Voucher',
                        'disable_step' => true,
                        'entries'      => [
                            ['type' => 'Cr', 'account' => 'Bad Debts Recovered', 'debit' => '-',         'credit' => '0', 'gl_code' => 309005, 'sequence' => 1, 'summary' => ''],
                            ['type' => 'Dr', 'account' => 'Bank A/c',            'debit' => '0', 'credit' => '-', 'gl_code' => 100201, 'sequence' => 2, 'summary' => ''],
                        ],
                    ],
                ],
            ],

            // ── 7. Loan Processing Fee ───────────────────────────────────────
            [
                'section' => 'Loan Processing Fee',
                'steps'   => [
                    [
                        'id'           => 'loan_processing_fee_gst_invoice',
                        'voucher_type' => 'GST Invoice',
                        'disable_step' => true,
                        'entries'      => [
                            ['type' => 'Dr', 'account' => 'Loan Processing Fee',                         'debit' => '0', 'credit' => '-', 'gl_code' => 300007, 'sequence' => 1, 'summary' => ''],
                            ['type' => 'Dr', 'account' => 'Documentation Charges',                       'debit' => '0',  'credit' => '-', 'gl_code' => 300002, 'sequence' => 2, 'summary' => ''],
                            ['type' => 'Dr', 'account' => 'GST',                                         'debit' => '0',  'credit' => '-', 'gl_code' => 206003, 'sequence' => 3, 'summary' => ''],
                            ['type' => 'Cr', 'account' => 'Loan Processing Fee Receivable',              'debit' => '-',  'credit' => '0', 'gl_code' => 154005, 'sequence' => 4, 'summary' => ''],
                        ],
                    ],
                    [
                        'id'           => 'tds_on_lpf_jv',
                        'voucher_type' => 'Journal Voucher',
                        'disable_step' => true,
                        'entries'      => [
                            ['type' => 'Dr', 'account' => 'Loan Processing Fee Receivable / Party Name', 'debit' => '0', 'credit' => '-', 'gl_code' => 1, 'sequence' => 1, 'summary' => ''],
                            ['type' => 'Cr', 'account' => 'TDS recoverable',                             'debit' => '-',        'credit' => '0', 'gl_code' => 160004, 'sequence' => 2, 'summary' => ''],
                        ],
                    ],
                    [
                        'id'           => 'lpf_received_rv',
                        'voucher_type' => 'Receipt Voucher',
                        'disable_step' => true,
                        'entries'      => [
                            ['type' => 'Dr', 'account' => 'Bank A/c',   'debit' => '0', 'credit' => '-', 'gl_code' => 160002, 'sequence' => 1, 'summary' => ''],
                            ['type' => 'Cr', 'account' => 'Loan Processing Fee Receivable', 'debit' => '-',         'credit' => '0', 'gl_code' => 154005, 'sequence' => 2, 'summary' => ''],
                        ],
                    ],
                ],
            ],

        ];

        if ($stepKey) {
            foreach ($steps as $section) {
                foreach ($section['steps'] as $stepEntry) {
                    if ($stepEntry['id'] === $stepKey) {
                        if (isset($stepEntry['disable_step']) && $stepEntry['disable_step']) {
                            return [];
                        }
                        return $stepEntry['entries'];
                    }
                }
            }

            return [];
        }

        $filteredSections = [];
        foreach ($steps as $section) {
            $filteredSteps = array_values(array_filter($section['steps'], function($stepEntry) {
                return !(isset($stepEntry['disable_step']) && $stepEntry['disable_step']);
            }));

            if (!empty($filteredSteps)) {
                $section['steps'] = $filteredSteps;
                $filteredSections[] = $section;
            }
        }

        return $filteredSections;
    }
}
