<?php
// File: src/Services/ProfitAndLossExporter.php
// Version 1.0 - Profit & Loss CSV export

namespace ComptaFlowUK\Services;

defined('ABSPATH') || exit;

class ProfitAndLossExporter
{
    /**
     * Export Profit & Loss statement as CSV
     * UK nominal code ranges: 4xxx Revenue, 5xxx Direct Costs, 6xxx Overheads, 7xxx Staff, 8xxx Depreciation/Finance
     */
    public static function export(int $user_id, string $start_date, string $end_date): void
    {
        global $wpdb;
        $journal_table = $wpdb->prefix . 'cfuk_journal_entries';
        
        // P&L accounts: 4xxx-8xxx (revenue + expenses)
        $like4 = $wpdb->esc_like('4') . '%';
        $like5 = $wpdb->esc_like('5') . '%';
        $like6 = $wpdb->esc_like('6') . '%';
        $like7 = $wpdb->esc_like('7') . '%';
        $like8 = $wpdb->esc_like('8') . '%';
        $entries = $wpdb->get_results($wpdb->prepare(
            "SELECT compte_num, SUM(debit) as total_debit, SUM(credit) as total_credit
             FROM $journal_table
             WHERE created_by = %d
             AND date_ecriture BETWEEN %s AND %s
             AND (compte_num LIKE %s OR compte_num LIKE %s OR compte_num LIKE %s OR compte_num LIKE %s OR compte_num LIKE %s)
             GROUP BY compte_num
             ORDER BY compte_num ASC",
            $user_id, $start_date, $end_date, $like4, $like5, $like6, $like7, $like8
        ));
        
        if (empty($entries)) {
            wp_die('No income or expense entries found for this period.');
        }
        
        $content = self::generateContent($entries, $start_date, $end_date);
        
        $filename = 'ProfitAndLoss_' . gmdate('Ymd') . '_' . str_replace('-', '', $start_date) . '_' . str_replace('-', '', $end_date) . '.csv';
        
        header('Content-Type: text/csv; charset=UTF-8');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header('Pragma: no-cache');
        header('Expires: 0');
        
        echo "\xEF\xBB\xBF";
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- CSV output, not HTML
        echo $content;
        exit;
    }
    
    private static function generateContent(array $entries, string $start_date, string $end_date): string
    {
        $lines = [];
        
        $lines[] = 'PROFIT & LOSS STATEMENT';
        $lines[] = 'Period: ' . gmdate('d/m/Y', strtotime($start_date)) . ' to ' . gmdate('d/m/Y', strtotime($end_date));
        $lines[] = '';
        
        // Separate revenue and expenses
        $revenue = [];
        $expenses = [];
        
        foreach ($entries as $entry) {
            $code = $entry->compte_num;
            $debit = (float)$entry->total_debit;
            $credit = (float)$entry->total_credit;
            $balance = $debit - $credit;
            
            $num = intval($code);
            if ($num >= 4000 && $num <= 4999) {
                $revenue[] = ['code' => $code, 'amount' => abs(min(0, $balance))];
            } elseif ($num >= 5000 && $num <= 8999) {
                $expenses[] = ['code' => $code, 'amount' => max(0, $balance)];
            }
        }
        
        // Group
        $revenue_grouped = self::groupRevenue($revenue);
        $expenses_grouped = self::groupExpenses($expenses);
        
        // REVENUE
        $lines[] = 'REVENUE,Amount';
        $lines[] = '================================================';
        
        $total_revenue = 0;
        foreach ($revenue_grouped as $category => $amount) {
            $total_revenue += $amount;
            $lines[] = $category . ',' . self::fmt($amount);
        }
        
        $lines[] = '';
        $lines[] = 'TOTAL REVENUE,' . self::fmt($total_revenue);
        $lines[] = '';
        
        // EXPENSES
        $lines[] = 'EXPENSES,Amount';
        $lines[] = '================================================';
        
        $total_expenses = 0;
        foreach ($expenses_grouped as $category => $amount) {
            $total_expenses += $amount;
            $lines[] = $category . ',' . self::fmt($amount);
        }
        
        $lines[] = '';
        $lines[] = 'TOTAL EXPENSES,' . self::fmt($total_expenses);
        $lines[] = '';
        
        // NET PROFIT
        $net = $total_revenue - $total_expenses;
        $lines[] = '================================================';
        $lines[] = ($net >= 0 ? 'NET PROFIT' : 'NET LOSS') . ',' . self::fmt($net);
        $lines[] = '================================================';
        
        return implode("\n", $lines);
    }
    
    private static function groupRevenue(array $items): array
    {
        $grouped = [
            'Sales - Services (4000-4099)' => 0,
            'Sales - Goods (4100-4199)' => 0,
            'Other Income (4200-4999)' => 0,
        ];
        
        foreach ($items as $item) {
            $num = intval($item['code']);
            if ($num >= 4000 && $num <= 4099) {
                $grouped['Sales - Services (4000-4099)'] += $item['amount'];
            } elseif ($num >= 4100 && $num <= 4199) {
                $grouped['Sales - Goods (4100-4199)'] += $item['amount'];
            } elseif ($num >= 4200 && $num <= 4999) {
                $grouped['Other Income (4200-4999)'] += $item['amount'];
            }
        }
        
        return array_filter($grouped, fn($v) => $v != 0);
    }
    
    private static function groupExpenses(array $items): array
    {
        $grouped = [
            'Cost of Sales (5000-5099)' => 0,
            'Materials (5100-5199)' => 0,
            'Subcontractors (5200-5299)' => 0,
            'Other Direct Costs (5300-5999)' => 0,
            'Rent & Rates (6000-6049)' => 0,
            'Insurance (6050-6099)' => 0,
            'Repairs & Maintenance (6100-6149)' => 0,
            'Professional Fees (6300-6399)' => 0,
            'Office Costs (6400-6499)' => 0,
            'Travel & Subsistence (6500-6599)' => 0,
            'Marketing (6600-6699)' => 0,
            'Subscriptions (6700-6799)' => 0,
            'Other Overheads (6800-6999)' => 0,
            'Wages & Salaries (7000-7009)' => 0,
            'Employer NI (7010-7019)' => 0,
            'Pension Costs (7020-7099)' => 0,
            'Other Staff Costs (7100-7999)' => 0,
            'Depreciation (8000-8019)' => 0,
            'Gain/Loss on Disposal (8020)' => 0,
            'Interest Paid (8050-8059)' => 0,
            'Interest Received (8100-8109)' => 0,
            'Bank Charges (8800-8899)' => 0,
        ];
        
        foreach ($items as $item) {
            $num = intval($item['code']);
            $amt = $item['amount'];
            
            if ($num >= 5000 && $num <= 5099) $grouped['Cost of Sales (5000-5099)'] += $amt;
            elseif ($num >= 5100 && $num <= 5199) $grouped['Materials (5100-5199)'] += $amt;
            elseif ($num >= 5200 && $num <= 5299) $grouped['Subcontractors (5200-5299)'] += $amt;
            elseif ($num >= 5300 && $num <= 5999) $grouped['Other Direct Costs (5300-5999)'] += $amt;
            elseif ($num >= 6000 && $num <= 6049) $grouped['Rent & Rates (6000-6049)'] += $amt;
            elseif ($num >= 6050 && $num <= 6099) $grouped['Insurance (6050-6099)'] += $amt;
            elseif ($num >= 6100 && $num <= 6149) $grouped['Repairs & Maintenance (6100-6149)'] += $amt;
            elseif ($num >= 6300 && $num <= 6399) $grouped['Professional Fees (6300-6399)'] += $amt;
            elseif ($num >= 6400 && $num <= 6499) $grouped['Office Costs (6400-6499)'] += $amt;
            elseif ($num >= 6500 && $num <= 6599) $grouped['Travel & Subsistence (6500-6599)'] += $amt;
            elseif ($num >= 6600 && $num <= 6699) $grouped['Marketing (6600-6699)'] += $amt;
            elseif ($num >= 6700 && $num <= 6799) $grouped['Subscriptions (6700-6799)'] += $amt;
            elseif ($num >= 6800 && $num <= 6999) $grouped['Other Overheads (6800-6999)'] += $amt;
            elseif ($num >= 7000 && $num <= 7009) $grouped['Wages & Salaries (7000-7009)'] += $amt;
            elseif ($num >= 7010 && $num <= 7019) $grouped['Employer NI (7010-7019)'] += $amt;
            elseif ($num >= 7020 && $num <= 7099) $grouped['Pension Costs (7020-7099)'] += $amt;
            elseif ($num >= 7100 && $num <= 7999) $grouped['Other Staff Costs (7100-7999)'] += $amt;
            elseif ($num >= 8000 && $num <= 8019) $grouped['Depreciation (8000-8019)'] += $amt;
            elseif ($num == 8020) $grouped['Gain/Loss on Disposal (8020)'] += $amt;
            elseif ($num >= 8050 && $num <= 8059) $grouped['Interest Paid (8050-8059)'] += $amt;
            elseif ($num >= 8100 && $num <= 8109) $grouped['Interest Received (8100-8109)'] += $amt;
            elseif ($num >= 8800 && $num <= 8899) $grouped['Bank Charges (8800-8899)'] += $amt;
        }
        
        return array_filter($grouped, fn($v) => $v != 0);
    }
    
    private static function fmt(float $amount): string
    {
        return '£' . number_format($amount, 2, '.', ',');
    }
}
