<?php
// File: src/Services/JournalEntryGenerator.php
// Version 5.0 - UK Edition - All FR account codes mapped to UK nominal codes

namespace ComptaFlowUK\Services;

use ComptaFlowUK\Services\ChartOfAccounts;

defined('ABSPATH') || exit;

class JournalEntryGenerator {
    
    /**
     * Generate journal entries for financial operations
     */
    public static function generateFinancialEntries(array $financialData, int $transaction_id): void {
        global $wpdb;
        $p = $wpdb->prefix . 'cfuk_';
        
        $date = $financialData['date_txn'];
        $amount = floatval($financialData['amount_ttc']);
        $label = $financialData['label'];
        $user_id = $financialData['created_by'] ?? get_current_user_id();
        $payment_status = $financialData['payment_status'] ?? 'PAID';
        
        $base_data = [
            'transaction_id' => $transaction_id,
            'date_ecriture' => $date,
            'journal_code' => 'NL',
            'piece_ref' => $financialData['piece_ref'] ?? null,
            'created_by' => $user_id,
            'source' => 'FINANCIAL',
        ];

        $entry_lines = [];
        
        switch ($financialData['type']) {
            case 'CAPITAL_IN_KIND':
                $meta = json_decode($financialData['meta_json'] ?? '{}', true);
                $asset_account = $meta['asset_account'] ?? '0030';
                $entry_lines = [
                    ['compte_num' => $asset_account, 'libelle' => 'Capital in kind - ' . $label, 'debit' => $amount, 'credit' => 0],
                    ['compte_num' => '3000', 'libelle' => 'Capital increase by asset contribution', 'debit' => 0, 'credit' => $amount]
                ];
                break;

            case 'CAPITAL_INCREASE':
            case 'CAPITAL_CASH_INJECTION':
                if ($payment_status === 'PAID') {
                    $entry_lines = [
                        ['compte_num' => '1200', 'libelle' => $label, 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '3000', 'libelle' => 'Capital increase', 'debit' => 0, 'credit' => $amount]
                    ];
                } else {
                    $entry_lines = [
                        ['compte_num' => '3010', 'libelle' => 'Called up capital, unpaid', 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '3000', 'libelle' => 'Share capital', 'debit' => 0, 'credit' => $amount]
                    ];
                }
                break;

            case 'CAPITAL_CONTRIBUTION':
                if ($payment_status === 'PAID') {
                    $entry_lines = [
                        ['compte_num' => '1200', 'libelle' => 'Director loan credit', 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '3050', 'libelle' => $label, 'debit' => 0, 'credit' => $amount]
                    ];
                } else {
                    $entry_lines = [
                        ['compte_num' => '1250', 'libelle' => 'Promised contribution - ' . $label, 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '3050', 'libelle' => 'Director loan account', 'debit' => 0, 'credit' => $amount]
                    ];
                }
                break;

            case 'OWNER_DRAWING':
                if ($payment_status === 'PAID') {
                    $entry_lines = [
                        ['compte_num' => '3050', 'libelle' => $label, 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '1200', 'libelle' => 'Owner drawing - bank transfer', 'debit' => 0, 'credit' => $amount]
                    ];
                } else {
                    $entry_lines = [
                        ['compte_num' => '3050', 'libelle' => 'Owner drawing - ' . $label, 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '2100', 'libelle' => 'Amount owed to director', 'debit' => 0, 'credit' => $amount]
                    ];
                }
                break;

            case 'CC_TO_CAPITAL':
                if ($payment_status === 'PAID') {
                    $entry_lines = [
                        ['compte_num' => '3050', 'libelle' => 'Director loan converted to capital - ' . $label, 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '3000', 'libelle' => 'Capital increase by loan conversion', 'debit' => 0, 'credit' => $amount]
                    ];
                } else {
                    $entry_lines = [
                        ['compte_num' => '3050', 'libelle' => 'Loan to convert - ' . $label, 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '3010', 'libelle' => 'Capital to formalise', 'debit' => 0, 'credit' => $amount]
                    ];
                }
                break;

            case 'CC_INTEREST':
                if ($payment_status === 'PAID') {
                    $entry_lines = [
                        ['compte_num' => '6855', 'libelle' => 'Director loan interest - ' . $label, 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '3050', 'libelle' => 'Credit director loan account', 'debit' => 0, 'credit' => $amount]
                    ];
                } else {
                    $entry_lines = [
                        ['compte_num' => '6855', 'libelle' => 'Accrued interest - ' . $label, 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '3055', 'libelle' => 'Accrued interest payable', 'debit' => 0, 'credit' => $amount]
                    ];
                }
                break;

            case 'DIVIDEND_TO_CC':
                if ($payment_status === 'PAID') {
                    $entry_lines = [
                        ['compte_num' => '3060', 'libelle' => 'Dividends declared - ' . $label, 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '3050', 'libelle' => 'Credit director loan account', 'debit' => 0, 'credit' => $amount]
                    ];
                } else {
                    $entry_lines = [
                        ['compte_num' => '3060', 'libelle' => 'Dividends to allocate - ' . $label, 'debit' => 0, 'credit' => $amount]
                    ];
                }
                break;
            
            case 'LOAN_RECEIVED':
                if ($payment_status === 'PAID') {
                    $entry_lines = [
                        ['compte_num' => '1200', 'libelle' => 'Loan funds received', 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '2300', 'libelle' => $label, 'debit' => 0, 'credit' => $amount]
                    ];
                } else {
                    $entry_lines = [
                        ['compte_num' => '1250', 'libelle' => 'Bank receivable - loan pending', 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '2300', 'libelle' => 'Loan contracted - ' . $label, 'debit' => 0, 'credit' => $amount]
                    ];
                }
                break;
                
            case 'LOAN_REPAYMENT':
                if ($payment_status === 'PAID') {
                    $entry_lines = [
                        ['compte_num' => '2300', 'libelle' => 'Loan repayment - ' . $label, 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '1200', 'libelle' => 'Bank transfer - loan repayment', 'debit' => 0, 'credit' => $amount]
                    ];
                } else {
                    $entry_lines = [
                        ['compte_num' => '2300', 'libelle' => 'Loan repayment due - ' . $label, 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '2310', 'libelle' => 'Repayment liability', 'debit' => 0, 'credit' => $amount]
                    ];
                }
                break;
                
            case 'INTEREST_PAYMENT':
                if ($payment_status === 'PAID') {
                    $entry_lines = [
                        ['compte_num' => '6850', 'libelle' => 'Loan interest - ' . $label, 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '1200', 'libelle' => 'Interest payment', 'debit' => 0, 'credit' => $amount]
                    ];
                } else {
                    $entry_lines = [
                        ['compte_num' => '6850', 'libelle' => 'Accrued interest - ' . $label, 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '2310', 'libelle' => 'Accrued interest payable', 'debit' => 0, 'credit' => $amount]
                    ];
                }
                break;
            
            case 'VAT_PAYMENT':
                if ($payment_status === 'PAID') {
                    $entry_lines = [
                        ['compte_num' => '2200', 'libelle' => 'VAT payment - ' . $label, 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '1200', 'libelle' => 'Bank transfer - VAT', 'debit' => 0, 'credit' => $amount]
                    ];
                } else {
                    $entry_lines = [
                        ['compte_num' => '2200', 'libelle' => 'VAT payable - ' . $label, 'debit' => 0, 'credit' => $amount]
                    ];
                }
                break;
                
            case 'CORPORATE_TAX':
                if ($payment_status === 'PAID') {
                    $entry_lines = [
                        ['compte_num' => '2220', 'libelle' => 'Corporation tax payment - ' . $label, 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '1200', 'libelle' => 'Bank transfer - tax', 'debit' => 0, 'credit' => $amount]
                    ];
                } else {
                    $entry_lines = [
                        ['compte_num' => '2220', 'libelle' => 'Corporation tax payable - ' . $label, 'debit' => 0, 'credit' => $amount]
                    ];
                }
                break;
                
            case 'DIVIDEND_PAYMENT':
                if ($payment_status === 'PAID') {
                    $entry_lines = [
                        ['compte_num' => '3060', 'libelle' => 'Dividend payment - ' . $label, 'debit' => $amount, 'credit' => 0],
                        ['compte_num' => '1200', 'libelle' => 'Bank transfer - dividends', 'debit' => 0, 'credit' => $amount]
                    ];
                } else {
                    $entry_lines = [
                        ['compte_num' => '3060', 'libelle' => 'Dividends payable - ' . $label, 'debit' => 0, 'credit' => $amount]
                    ];
                }
                break;
            
            case 'BANK_TRANSFER':
                $meta = json_decode($financialData['meta_json'] ?? '{}', true);
                $source_account = $meta['source_account'] ?? '1200';
                $dest_account = $meta['dest_account'] ?? '1200';
                $entry_lines = [
                    ['compte_num' => $dest_account, 'libelle' => 'Transfer received - ' . $label, 'debit' => $amount, 'credit' => 0],
                    ['compte_num' => $source_account, 'libelle' => 'Transfer sent - ' . $label, 'debit' => 0, 'credit' => $amount]
                ];
                break;
                
            case 'CASH_DEPOSIT':
                $entry_lines = [
                    ['compte_num' => '1200', 'libelle' => 'Cash deposit - ' . $label, 'debit' => $amount, 'credit' => 0],
                    ['compte_num' => '1230', 'libelle' => 'Cash out', 'debit' => 0, 'credit' => $amount]
                ];
                break;
                
            case 'CASH_WITHDRAWAL':
                $entry_lines = [
                    ['compte_num' => '1230', 'libelle' => 'Cash withdrawal - ' . $label, 'debit' => $amount, 'credit' => 0],
                    ['compte_num' => '1200', 'libelle' => 'Bank withdrawal', 'debit' => 0, 'credit' => $amount]
                ];
                break;
            
            case 'BANK_FEES':
            case 'LEGAL_FEES':
            case 'ACCOUNTING_FEES':
                $amount_ht = floatval($financialData['amount_ht']);
                $amount_tva = floatval($financialData['amount_tva']);
                $charge_account = '6800';
                if ($financialData['type'] === 'LEGAL_FEES') {
                    $charge_account = '6310';
                } elseif ($financialData['type'] === 'ACCOUNTING_FEES') {
                    $charge_account = '6300';
                }
                
                if ($payment_status === 'PAID') {
                    $entry_lines = [
                        ['compte_num' => $charge_account, 'libelle' => $label, 'debit' => $amount_ht, 'credit' => 0],
                        ['compte_num' => '2201', 'libelle' => 'Input VAT', 'debit' => $amount_tva, 'credit' => 0],
                        ['compte_num' => '1200', 'libelle' => 'Payment', 'debit' => 0, 'credit' => $amount]
                    ];
                } else {
                    $entry_lines = [
                        ['compte_num' => $charge_account, 'libelle' => $label, 'debit' => $amount_ht, 'credit' => 0],
                        ['compte_num' => '2201', 'libelle' => 'Input VAT', 'debit' => $amount_tva, 'credit' => 0],
                        ['compte_num' => '2100', 'libelle' => 'Trade creditor', 'debit' => 0, 'credit' => $amount]
                    ];
                }
                break;
        }

        foreach ($entry_lines as $line) {
            $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
                'uuid' => wp_generate_uuid4(),
                'compte_num' => $line['compte_num'],
                'libelle' => $line['libelle'],
                'debit' => $line['debit'],
                'credit' => $line['credit'],
            ]));
        }
    }
    
    public static function generatePaymentEntry(array $transaction, int $transaction_id): void {
        global $wpdb;
        $p = $wpdb->prefix . 'cfuk_';
        
        $date = gmdate('Y-m-d');
        $amount = floatval($transaction['amount_ttc']);
        $type = $transaction['type'];
        $label = $transaction['label'];
        
        $base_data = [
            'transaction_id' => $transaction_id,
            'date_ecriture' => $date,
            'journal_code' => 'CB',
            'created_by' => get_current_user_id(),
            'source' => 'FINANCIAL_PAYMENT',
        ];
        
        $entry_lines = [];
        
        switch ($type) {
            case 'CAPITAL_INCREASE': 
            case 'CAPITAL_CASH_INJECTION':
                $entry_lines = [
                    ['compte_num' => '1200', 'libelle' => 'Capital received', 'debit' => $amount, 'credit' => 0], 
                    ['compte_num' => '3010', 'libelle' => 'Called up capital settled', 'debit' => 0, 'credit' => $amount]
                ];
                break;
                
            case 'CAPITAL_CONTRIBUTION':
                $entry_lines = [
                    ['compte_num' => '1200', 'libelle' => 'Contribution received', 'debit' => $amount, 'credit' => 0], 
                    ['compte_num' => '1250', 'libelle' => 'Contribution receivable settled', 'debit' => 0, 'credit' => $amount]
                ];
                break;
                
            case 'OWNER_DRAWING':
                $entry_lines = [
                    ['compte_num' => '2100', 'libelle' => 'Owner drawing paid', 'debit' => $amount, 'credit' => 0], 
                    ['compte_num' => '1200', 'libelle' => 'Bank transfer - drawing', 'debit' => 0, 'credit' => $amount]
                ];
                break;
                
            case 'CC_TO_CAPITAL':
                $entry_lines = [
                    ['compte_num' => '3010', 'libelle' => 'Capital formalised', 'debit' => $amount, 'credit' => 0], 
                    ['compte_num' => '3000', 'libelle' => 'Capital increase registered', 'debit' => 0, 'credit' => $amount]
                ];
                break;
                
            case 'CC_INTEREST':
                $entry_lines = [
                    ['compte_num' => '3055', 'libelle' => 'Accrued interest settled', 'debit' => $amount, 'credit' => 0], 
                    ['compte_num' => '3050', 'libelle' => 'Credit director loan', 'debit' => 0, 'credit' => $amount]
                ];
                break;
                
            case 'DIVIDEND_TO_CC':
                $entry_lines = [
                    ['compte_num' => '3060', 'libelle' => 'Dividends allocated', 'debit' => $amount, 'credit' => 0], 
                    ['compte_num' => '3050', 'libelle' => 'Credit director loan', 'debit' => 0, 'credit' => $amount]
                ];
                break;
                
            case 'LOAN_RECEIVED':
                $entry_lines = [
                    ['compte_num' => '1200', 'libelle' => 'Loan received', 'debit' => $amount, 'credit' => 0], 
                    ['compte_num' => '1250', 'libelle' => 'Bank receivable settled', 'debit' => 0, 'credit' => $amount]
                ];
                break;
                
            case 'LOAN_REPAYMENT':
                $entry_lines = [
                    ['compte_num' => '2310', 'libelle' => 'Repayment settled', 'debit' => $amount, 'credit' => 0], 
                    ['compte_num' => '1200', 'libelle' => 'Bank transfer', 'debit' => 0, 'credit' => $amount]
                ];
                break;
                
            case 'VAT_PAYMENT':
                $entry_lines = [
                    ['compte_num' => '2200', 'libelle' => 'VAT payment', 'debit' => $amount, 'credit' => 0], 
                    ['compte_num' => '1200', 'libelle' => 'Bank transfer', 'debit' => 0, 'credit' => $amount]
                ];
                break;
                
            case 'CORPORATE_TAX':
                $entry_lines = [
                    ['compte_num' => '2220', 'libelle' => 'Corporation tax payment', 'debit' => $amount, 'credit' => 0], 
                    ['compte_num' => '1200', 'libelle' => 'Bank transfer', 'debit' => 0, 'credit' => $amount]
                ];
                break;
                
            case 'DIVIDEND_PAYMENT':
                $entry_lines = [
                    ['compte_num' => '3060', 'libelle' => 'Dividend payment', 'debit' => $amount, 'credit' => 0], 
                    ['compte_num' => '1200', 'libelle' => 'Bank transfer', 'debit' => 0, 'credit' => $amount]
                ];
                break;
                
            case 'INTEREST_PAYMENT':
                $entry_lines = [
                    ['compte_num' => '2310', 'libelle' => 'Interest payment', 'debit' => $amount, 'credit' => 0], 
                    ['compte_num' => '1200', 'libelle' => 'Bank transfer - interest', 'debit' => 0, 'credit' => $amount]
                ];
                break;
                
            case 'BANK_FEES': 
            case 'LEGAL_FEES': 
            case 'ACCOUNTING_FEES':
                $entry_lines = [
                    ['compte_num' => '2100', 'libelle' => 'Payment - ' . $label, 'debit' => $amount, 'credit' => 0], 
                    ['compte_num' => '1200', 'libelle' => 'Payment made', 'debit' => 0, 'credit' => $amount]
                ];
                break;
        }
        
        foreach ($entry_lines as $line) {
            $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
                'uuid' => wp_generate_uuid4(),
                'compte_num' => $line['compte_num'],
                'libelle' => $line['libelle'],
                'debit' => $line['debit'],
                'credit' => $line['credit'],
            ]));
        }
    }
    
    public static function generateSaleEntries(array $saleData, int $transaction_id): void {
        global $wpdb; 
        $p = $wpdb->prefix . 'cfuk_';
        $date = $saleData['date_txn'];
        $partner = $saleData['partner_name'] ?: 'Customer';
        $user_id = $saleData['created_by'] ?? get_current_user_id();
        
        $base_data = [
            'transaction_id' => $transaction_id, 
            'date_ecriture' => $date, 
            'journal_code' => 'SL', 
            'piece_ref' => $saleData['piece_ref'] ?? null, 
            'created_by' => $user_id, 
            'source' => 'SALE'
        ];
        
        $revenue_account = $saleData['account_code'] ?? '4010';
        $revenue_label_desc = ChartOfAccounts::getAccount($revenue_account)['label'] ?? 'Sales - Services';
        
        $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
            'uuid' => wp_generate_uuid4(), 
            'compte_num' => $revenue_account, 
            'libelle' => sprintf('%s | %s | %s', $revenue_label_desc, date_i18n('d/m/Y', strtotime($date)), $partner), 
            'debit' => 0, 
            'credit' => $saleData['amount_ht']
        ]));
        
        if ($saleData['amount_tva'] > 0) {
            $vat_rate_formatted = number_format($saleData['vat_rate'], 2);
            $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
                'uuid' => wp_generate_uuid4(), 
                'compte_num' => '2200', 
                'libelle' => sprintf('Output VAT (%s%%) | %s | %s', $vat_rate_formatted, date_i18n('d/m/Y', strtotime($date)), $partner), 
                'debit' => 0, 
                'credit' => $saleData['amount_tva']
            ]));
        }
        
        $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
            'uuid' => wp_generate_uuid4(), 
            'compte_num' => '1100', 
            'partner_code' => '', 
            'libelle' => sprintf('Trade debtor | %s | %s', date_i18n('d/m/Y', strtotime($date)), $partner), 
            'debit' => $saleData['amount_ttc'], 
            'credit' => 0
        ]));
        
        if ($saleData['payment_status'] === 'PAID') {
            $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
                'uuid' => wp_generate_uuid4(), 
                'compte_num' => '1100', 
                'partner_code' => '', 
                'libelle' => sprintf('Customer receipt | %s | %s', date_i18n('d/m/Y', strtotime($date)), $partner), 
                'debit' => 0, 
                'credit' => $saleData['amount_ttc']
            ]));
            
            $treasury_account = self::getTreasuryAccountForSale($saleData['payment_method']);
            $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
                'uuid' => wp_generate_uuid4(), 
                'compte_num' => $treasury_account, 
                'libelle' => sprintf('Customer receipt | %s | %s', date_i18n('d/m/Y', strtotime($date)), $partner), 
                'debit' => $saleData['amount_ttc'], 
                'credit' => 0
            ]));
        }
    }
    
    public static function generateExpenseEntries(array $expenseData, int $transaction_id): void {
        global $wpdb; 
        $p = $wpdb->prefix . 'cfuk_';
        $date = $expenseData['date_txn'];
        $partner = $expenseData['partner_name'] ?: 'Supplier';
        $user_id = $expenseData['created_by'] ?? get_current_user_id();
        
        $base_data = [
            'transaction_id' => $transaction_id, 
            'date_ecriture' => $date, 
            'journal_code' => 'PL', 
            'piece_ref' => $expenseData['piece_ref'] ?? null, 
            'created_by' => $user_id, 
            'source' => 'EXPENSE'
        ];
        
        $charge_account = $expenseData['account_code'] ?? '5010';
        $charge_label_desc = ChartOfAccounts::getAccount($charge_account)['label'] ?? 'General expense';
        
        $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
            'uuid' => wp_generate_uuid4(), 
            'compte_num' => $charge_account, 
            'libelle' => sprintf('%s | %s | %s', $charge_label_desc, date_i18n('d/m/Y', strtotime($date)), $partner), 
            'debit' => $expenseData['amount_ht'], 
            'credit' => 0
        ]));
        
        if ($expenseData['amount_tva'] > 0) {
            $vat_rate_formatted = number_format($expenseData['vat_rate'], 2);
            $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
                'uuid' => wp_generate_uuid4(), 
                'compte_num' => '2201', 
                'libelle' => sprintf('Input VAT (%s%%) | %s | %s', $vat_rate_formatted, date_i18n('d/m/Y', strtotime($date)), $partner), 
                'debit' => $expenseData['amount_tva'], 
                'credit' => 0
            ]));
        }
        
        $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
            'uuid' => wp_generate_uuid4(), 
            'compte_num' => '2100', 
            'partner_code' => '', 
            'libelle' => sprintf('Trade creditor | %s | %s', date_i18n('d/m/Y', strtotime($date)), $partner), 
            'debit' => 0, 
            'credit' => $expenseData['amount_ttc']
        ]));
        
        if ($expenseData['payment_status'] === 'PAID') {
            $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
                'uuid' => wp_generate_uuid4(), 
                'compte_num' => '2100', 
                'partner_code' => '', 
                'libelle' => sprintf('Supplier payment | %s | %s', date_i18n('d/m/Y', strtotime($date)), $partner), 
                'debit' => $expenseData['amount_ttc'], 
                'credit' => 0
            ]));
            
            $treasury_account = self::getTreasuryAccountForExpense($expenseData['payment_method']);
            $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
                'uuid' => wp_generate_uuid4(), 
                'compte_num' => $treasury_account, 
                'libelle' => sprintf('Supplier payment | %s | %s', date_i18n('d/m/Y', strtotime($date)), $partner), 
                'debit' => 0, 
                'credit' => $expenseData['amount_ttc']
            ]));
        }
    }

    /**
     * Generate journal entries for an invoice.
     * DR 1100 Trade Debtors (gross total)
     * CR 4010 Sales / account_code per line (net per line)
     * CR 2200 Output VAT (total VAT)
     */
    public static function generateInvoiceEntries(array $invoice, array $lines): void {
        global $wpdb;
        $p = $wpdb->prefix . 'cfuk_';

        $ref = $invoice['invoice_number'] ?? '';
        $date = $invoice['issue_date'] ?? gmdate('Y-m-d');

        $base_data = [
            'transaction_id' => 0,
            'date_ecriture' => $date,
            'journal_code' => 'SL',
            'piece_ref' => $ref,
            'created_by' => get_current_user_id(),
            'source' => 'INVOICE',
        ];

        // Debit Trade Debtors for the gross total
        $total = floatval($invoice['total'] ?? 0);
        $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
            'uuid' => wp_generate_uuid4(),
            'compte_num' => '1100',
            'libelle' => sprintf('Trade debtor | %s', $ref),
            'debit' => $total,
            'credit' => 0,
        ]));

        // Credit each revenue account (net per line)
        foreach ($lines as $line) {
            $line_total = round(floatval($line['quantity']) * floatval($line['unit_price']), 2);
            if ($line_total <= 0) {
                continue;
            }
            $account = $line['account_code'] ?? '4010';
            $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
                'uuid' => wp_generate_uuid4(),
                'compte_num' => $account,
                'libelle' => sprintf('Sales | %s | %s', $ref, $line['description'] ?? ''),
                'debit' => 0,
                'credit' => $line_total,
            ]));
        }

        // Credit Output VAT
        $total_vat = floatval($invoice['total_vat'] ?? 0);
        if ($total_vat > 0) {
            $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
                'uuid' => wp_generate_uuid4(),
                'compte_num' => '2200',
                'libelle' => sprintf('Output VAT | %s', $ref),
                'debit' => 0,
                'credit' => $total_vat,
            ]));
        }
    }

    /**
     * Generate journal entries when an invoice is marked as paid.
     * DR 1200 Bank (total)
     * CR 1100 Trade Debtors (total)
     */
    public static function generateInvoicePaymentEntries(array $invoice): void {
        global $wpdb;
        $p = $wpdb->prefix . 'cfuk_';

        $amount = floatval($invoice['total']);
        $date = gmdate('Y-m-d');
        $ref = $invoice['invoice_number'] ?? '';

        $base_data = [
            'transaction_id' => 0,
            'date_ecriture' => $date,
            'journal_code' => 'CB',
            'piece_ref' => $ref,
            'created_by' => get_current_user_id(),
            'source' => 'INVOICE_PAYMENT',
        ];

        $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
            'uuid' => wp_generate_uuid4(),
            'compte_num' => '1200',
            'libelle' => sprintf('Customer receipt | %s', $ref),
            'debit' => $amount,
            'credit' => 0,
        ]));

        $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
            'uuid' => wp_generate_uuid4(),
            'compte_num' => '1100',
            'libelle' => sprintf('Trade debtor settled | %s', $ref),
            'debit' => 0,
            'credit' => $amount,
        ]));
    }

    /**
     * Generate journal entries for a credit note.
     * Reverses sales entries:
     * DR 4010 Sales (net per line, using line account_code)
     * DR 2200 Output VAT (total VAT)
     * CR 1100 Trade Debtors (total)
     */
    public static function generateCreditNoteEntries(array $creditNote, array $lines): void {
        global $wpdb;
        $p = $wpdb->prefix . 'cfuk_';

        $ref = $creditNote['invoice_number'] ?? '';
        $date = $creditNote['issue_date'] ?? gmdate('Y-m-d');

        $base_data = [
            'transaction_id' => 0,
            'date_ecriture' => $date,
            'journal_code' => 'SL',
            'piece_ref' => $ref,
            'created_by' => get_current_user_id(),
            'source' => 'CREDIT_NOTE',
        ];

        // Debit each revenue account (reverse the sale)
        foreach ($lines as $line) {
            $line_total = round(floatval($line['quantity']) * floatval($line['unit_price']), 2);
            if ($line_total <= 0) {
                continue;
            }
            $account = $line['account_code'] ?? '4010';
            $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
                'uuid' => wp_generate_uuid4(),
                'compte_num' => $account,
                'libelle' => sprintf('Credit note | %s | %s', $ref, $line['description'] ?? ''),
                'debit' => $line_total,
                'credit' => 0,
            ]));
        }

        // Debit Output VAT
        $total_vat = floatval($creditNote['total_vat'] ?? 0);
        if ($total_vat > 0) {
            $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
                'uuid' => wp_generate_uuid4(),
                'compte_num' => '2200',
                'libelle' => sprintf('Output VAT reversal | %s', $ref),
                'debit' => $total_vat,
                'credit' => 0,
            ]));
        }

        // Credit Trade Debtors
        $total = floatval($creditNote['total'] ?? 0);
        $wpdb->insert($p . 'journal_entries', array_merge($base_data, [
            'uuid' => wp_generate_uuid4(),
            'compte_num' => '1100',
            'libelle' => sprintf('Trade debtor credit note | %s', $ref),
            'debit' => 0,
            'credit' => $total,
        ]));
    }

    private static function getTreasuryAccountForSale(string $payment_method = ''): string {
        switch ($payment_method) {
            case 'CASH':
                return '1230';
            case 'CHEQUE':
                return '1210';
            case 'PAYPAL':
            case 'STRIPE':
                return '1250';
            case 'BANK_TRANSFER':
            case 'CARD':
            default:
                return '1200';
        }
    }

    private static function getTreasuryAccountForExpense(string $payment_method = ''): string {
        switch ($payment_method) {
            case 'CASH':
                return '1230';
            case 'CHEQUE':
                return '1210';
            case 'PAYPAL':
            case 'STRIPE':
                return '1250';
            case 'CARD':
                return '1240';
            case 'BANK_TRANSFER':
            default:
                return '1200';
        }
    }
    
}
