<?php
// includes/finance/forecast/finance_forecast_data.php

// Tenant-aware config include
if (isset($_REQUEST['tenant']) && file_exists('../../../../' . $_REQUEST['tenant'] . '/config.php')) {
    require_once('../../../../' . $_REQUEST['tenant'] . '/config.php');
}
if (file_exists('/config.php')) {
    require_once('/config.php');
}

// Ensure DB connection exists
if (!isset($GLOBALS['con']) || !($GLOBALS['con'] instanceof mysqli)) {
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode(['error' => 'Database connection not available in finance_forecast_data.php']);
    exit;
}

$con = $GLOBALS['con'];

/**
 * Forecast rules:
 * - Forecast value = rate_per_hour * term_years
 * - Only INCLUDED when:
 *   - renewal_date exists
 *   - renewal_date >= today
 *   - renewal_date within selected range
 *   - rate_per_hour and term_years are valid (>0)
 *
 * Commission rules (NEW):
 * - Determine client type from clientdetails.renewOptions JSON:
 *     notice (or inotice): 0=client, 1=agent, 2=broker
 * - Commission is calculated ONLY if type is agent or broker (1 or 2)
 * - Commission rate/value comes ONLY from clientdetails:
 *     commission, comType
 * - If commission is 0/blank => no commission
 * - comType determines fixed vs percentage:
 *     comType=0 => percentage of forecast_value  (DEFAULT)
 *     comType=1 => fixed amount per renewal
 *   (If your system uses the opposite mapping, swap the branches in calcCommission().)
 */
function calcFinanceForecast(?int $startTs, ?int $endTs, string $scope, int $agentId, int $brokerId): array
{
    $con   = $GLOBALS['con'];
    $today = strtotime('today');

    // Default range: today to +12 months
    if ($startTs === null || $startTs <= 0) $startTs = $today;
    if ($endTs === null || $endTs <= 0) $endTs = strtotime('+12 months', $today);

    // Pull everything needed from clientdetails (commission comes from here)
    $sql  = "SELECT clientnumber, clientname, statuslive, ";
    $sql .= "rate_per_hour, term_years, agent_number, broker_number, renewal_date, renewOptions, commission, comType ";
    $sql .= "FROM clientdetails ";
    $sql .= "WHERE statuslive = 1";

    $types  = '';
    $params = [];

    // Existing scope filtering remains as-is (UI filters by agent/broker number)
    if ($scope === 'agent' && $agentId > 0) {
        $sql     .= " AND agent_number = ?";
        $types   .= 'i';
        $params[] = $agentId;
    } elseif ($scope === 'broker' && $brokerId > 0) {
        $sql     .= " AND broker_number = ?";
        $types   .= 'i';
        $params[] = $brokerId;
    }

    $sql .= " ORDER BY clientname ASC";

    $stmt = $con->prepare($sql);
    if (!$stmt) {
        return ['error' => 'DB prepare error: ' . mysqli_error($con)];
    }
    if ($types !== '') {
        $stmt->bind_param($types, ...$params);
    }
    $stmt->execute();
    $res = $stmt->get_result();
    $stmt->close();

    // Caches for display-name lookups (not used for commission calc)
    $agentNameCache  = []; // agent_number => name
    $brokerNameCache = []; // broker_number => name

    $getAgentName = function (int $agentNo) use ($con, &$agentNameCache): string {
        if ($agentNo <= 0) return '';
        if (array_key_exists($agentNo, $agentNameCache)) return (string)$agentNameCache[$agentNo];

        $name = '';
        $s = $con->prepare("SELECT agent_name FROM agents WHERE agent_number = ?");
        if ($s) {
            $s->bind_param('i', $agentNo);
            $s->execute();
            $r = $s->get_result();
            if ($row = $r->fetch_assoc()) $name = (string)($row['agent_name'] ?? '');
            $s->close();
        }
        $agentNameCache[$agentNo] = $name;
        return $name;
    };

    $getBrokerName = function (int $brokerNo) use ($con, &$brokerNameCache): string {
        if ($brokerNo <= 0) return '';
        if (array_key_exists($brokerNo, $brokerNameCache)) return (string)$brokerNameCache[$brokerNo];

        $name = '';
        $s = $con->prepare("SELECT broker_name FROM brokers WHERE broker_number = ?");
        if ($s) {
            $s->bind_param('i', $brokerNo);
            $s->execute();
            $r = $s->get_result();
            if ($row = $r->fetch_assoc()) $name = (string)($row['broker_name'] ?? '');
            $s->close();
        }
        $brokerNameCache[$brokerNo] = $name;
        return $name;
    };

    $getNoticeMode = function (?string $renewOptionsRaw): int {
        if (!$renewOptionsRaw) return 0;
        $opts = json_decode($renewOptionsRaw, true);
        if (!is_array($opts)) return 0;

        // Prefer notice, fallback inotice
        if (isset($opts['notice'])) return (int)$opts['notice'];
        if (isset($opts['inotice'])) return (int)$opts['inotice'];
        return 0;
    };

    $toFloat = function ($v): float {
        $s = trim((string)$v);
        if ($s === '') return 0.0;
        return (float)str_replace(',', '', $s);
    };

    $calcCommission = function (
        bool $included,
        int $noticeMode,
        float $forecastValue,
        $commissionRaw,
        int $comType
    ): array {
        // Only apply commission for agent/broker clients and only when included
        if (!$included) return [0.0, 0.0, ''];
        if (!($noticeMode === 1 || $noticeMode === 2)) return [0.0, 0.0, ''];

        $comm = 0.0;
        $s = trim((string)$commissionRaw);
        if ($s !== '') $comm = (float)str_replace(',', '', $s);

        if ($comm <= 0) return [0.0, 0.0, ''];

        // Mapping (per your instruction): comType decides fixed vs percentage
        // Default: comType=0 => percentage, comType=1 => fixed
        if ($comType === 0) {
            $ratePct = $comm;
            $value   = $forecastValue * ($ratePct / 100);
            return [$ratePct, $value, 'percent'];
        }

        // fixed
        $ratePct = 0.0;
        $value   = $comm;
        return [$ratePct, $value, 'fixed'];
    };

    $rows            = [];
    $monthly         = []; // key => ['label','count','total','commission']
    $total           = 0.0;
    $totalCommission = 0.0;

    $inRangeCnt  = 0;
    $incomplete  = 0;
    $overdue     = 0;
    $clientCount = 0;

    while ($cd = $res->fetch_assoc()) {
        $clientCount++;

        $clientId   = (int)($cd['clientnumber'] ?? 0);
        $clientName = (string)($cd['clientname'] ?? '');

        // Rate and term
        $rateRaw   = $cd['rate_per_hour'] ?? '';
        $termRaw   = $cd['term_years'] ?? '';

        $rate      = $toFloat($rateRaw);
        $termYears = $toFloat($termRaw);

        $rateValid = ($rate > 0);
        $termValid = ($termYears > 0);

        $forecastValue = ($rateValid && $termValid) ? ($rate * $termYears) : 0.0;

        // Renewal date as Unix ts (stored as string/ts in DB)
        $renewalRaw = trim((string)($cd['renewal_date'] ?? ''));
        $renewalTs  = ($renewalRaw === '') ? 0 : (int)$renewalRaw;

        $statusLabel  = '';
        $included     = false;
        $monthKey     = null;
        $renewalLabel = 'No renewal date';

        // Agent / broker numbers (for display + filtering)
        $agentNo    = (int)($cd['agent_number'] ?? 0);
        $brokerNo   = (int)($cd['broker_number'] ?? 0);
        $agentName  = $agentNo > 0 ? $getAgentName($agentNo) : '';
        $brokerName = $brokerNo > 0 ? $getBrokerName($brokerNo) : '';

        $isIncomplete = (!$rateValid || !$termValid);

        // Included/excluded logic (unchanged)
        if ($renewalTs <= 0) {
            $renewalLabel = 'No renewal date';
            $statusLabel  = $isIncomplete
                ? 'Incomplete – missing rate/term and no renewal date'
                : 'No renewal date';
            $incomplete++;
        } elseif ($renewalTs < $today) {
            $renewalLabel = date('d-m-Y', $renewalTs);
            $statusLabel  = $isIncomplete
                ? 'Incomplete – missing rate/term; overdue (in the past)'
                : 'Overdue (in the past)';
            if ($isIncomplete) $incomplete++;
            $overdue++;
        } else {
            $renewalLabel = date('d-m-Y', $renewalTs);

            if ($isIncomplete) {
                $statusLabel = 'Incomplete – missing rate/term';
                $incomplete++;
            } else {
                if ($renewalTs >= $startTs && $renewalTs <= $endTs) {
                    $included    = true;
                    $statusLabel = 'Included in forecast';
                    $inRangeCnt++;

                    $monthKey   = date('Y-m', $renewalTs);
                    $monthLabel = date('M Y', $renewalTs);

                    if (!isset($monthly[$monthKey])) {
                        $monthly[$monthKey] = [
                            'label'      => $monthLabel,
                            'count'      => 0,
                            'total'      => 0.0,
                            'commission' => 0.0,
                        ];
                    }

                    $monthly[$monthKey]['count']++;
                    $monthly[$monthKey]['total'] += $forecastValue;

                    $total += $forecastValue;
                } else {
                    $statusLabel = 'Outside selected range';
                }
            }
        }

        // Determine notice mode from renewOptions (0 client, 1 agent, 2 broker)
        $renewOptionsRaw = (string)($cd['renewOptions'] ?? '');
        $noticeMode      = $getNoticeMode($renewOptionsRaw);

        // Commission calc (NEW method: from clientdetails only)
        $comType = (int)($cd['comType'] ?? 0);
        [$commissionRate, $commissionValue, $commissionKind] = $calcCommission(
            $included,
            $noticeMode,
            $forecastValue,
            $cd['commission'] ?? '',
            $comType
        );

        if ($included && $commissionValue > 0) {
            $totalCommission += $commissionValue;
            if ($monthKey !== null && isset($monthly[$monthKey])) {
                $monthly[$monthKey]['commission'] += $commissionValue;
            }
        }

        $rows[] = [
            'clientnumber'     => $clientId,
            'clientname'       => $clientName,
            'rate_per_hour'    => $rate,
            'term_years'       => $termYears,
            'forecast_value'   => $forecastValue,
            'renewal_ts'       => $renewalTs,
            'renewal_label'    => $renewalLabel,
            'status'           => $statusLabel,
            'included'         => $included,
            'agent_number'     => $agentNo,
            'agent_name'       => $agentName,
            'broker_number'    => $brokerNo,
            'broker_name'      => $brokerName,
            'month_key'        => $monthKey,

            // commission fields expected by UI
            'notice_mode'      => $noticeMode,          // 0/1/2 from renewOptions
            'commission_rate'  => $commissionRate,      // % when comType=0, else 0
            'commission_value' => $commissionValue,     // £ value (percent-derived or fixed)
            'commission_kind'  => $commissionKind,      // 'percent'|'fixed'|''
            'comType'          => $comType,
        ];
    }

    ksort($monthly);

    $monthsOut = [];
    foreach ($monthly as $k => $v) {
        $net = (float)$v['total'] - (float)$v['commission'];
        $monthsOut[] = [
            'key'        => $k,
            'label'      => $v['label'],
            'count'      => $v['count'],
            'total'      => (float)$v['total'],
            'commission' => (float)$v['commission'],
            'net'        => $net,
        ];
    }

    return [
        'summary' => [
            'total_forecast'        => $total,
            'total_commission'      => $totalCommission,
            'total_net_after_comm'  => ($total - $totalCommission),

            'client_count'     => $clientCount,
            'included_count'   => $inRangeCnt,
            'incomplete_count' => $incomplete,
            'overdue_count'    => $overdue,
            'start_ts'         => $startTs,
            'end_ts'           => $endTs,
        ],
        'months' => $monthsOut,
        'rows'   => $rows,
    ];
}

// ---------- MODE + PARAMS ----------

$mode = $_REQUEST['mode'] ?? 'data';

$scope    = $_REQUEST['scope'] ?? 'all';
$agentId  = isset($_REQUEST['agent'])  ? (int)$_REQUEST['agent']  : 0;
$brokerId = isset($_REQUEST['broker']) ? (int)$_REQUEST['broker'] : 0;

$startStr = trim($_REQUEST['start'] ?? '');
$endStr   = trim($_REQUEST['end']   ?? '');

$startTs = ($startStr !== '') ? strtotime(str_replace('/', '-', $startStr)) : null;
$endTs   = ($endStr !== '') ? strtotime(str_replace('/', '-', $endStr) . ' 23:59:59') : null;

$data = calcFinanceForecast($startTs, $endTs, $scope, $agentId, $brokerId);

// ---------- OUTPUT ----------

if ($mode === 'data') {
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($data);
    exit;
}

if ($mode === 'csv') {
    $filename = 'finance_forecast_' . date('Y-m-d_His') . '.csv';
    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment; filename="' . $filename . '"');

    $out = fopen('php://output', 'w');

    fputcsv($out, [
        'Client Number',
        'Client Name',
        'Renewal Date',
        'Status',
        'Rate per Hour',
        'Term (Years)',
        'Forecast Value',
        'Commission %',
        'Commission Value',
        'Agent',
        'Broker',
    ]);

    foreach ($data['rows'] as $row) {
        $commPct = ((string)($row['commission_kind'] ?? '') === 'percent')
            ? number_format((float)($row['commission_rate'] ?? 0), 2)
            : '';

        $commVal = ($row['included'] && (float)($row['commission_value'] ?? 0) > 0)
            ? number_format((float)$row['commission_value'], 2)
            : '';

        fputcsv($out, [
            $row['clientnumber'],
            $row['clientname'],
            $row['renewal_ts'] > 0 ? $row['renewal_label'] : '',
            $row['status'],
            $row['rate_per_hour'] > 0 ? number_format((float)$row['rate_per_hour'], 2) : '',
            $row['term_years'] > 0 ? (string)$row['term_years'] : '',
            $row['included'] ? number_format((float)$row['forecast_value'], 2) : '',
            $commPct,
            $commVal,
            $row['agent_name'],
            $row['broker_name'],
        ]);
    }

    fclose($out);
    exit;
}

if ($mode === 'pdf') {
    if (!class_exists('\Mpdf\Mpdf')) {
        $vendorPath = __DIR__ . '/../../../vendor/autoload.php';
        if (file_exists($vendorPath)) {
            require_once $vendorPath;
        }
    }

    if (!class_exists('\Mpdf\Mpdf')) {
        header('Content-Type: text/plain; charset=utf-8');
        echo "PDF generation is not available (mPDF not loaded).";
        exit;
    }

    $startLabel = date('d-m-Y', (int)$data['summary']['start_ts']);
    $endLabel   = date('d-m-Y', (int)$data['summary']['end_ts']);

    $html  = '<h2>Finance Forecast</h2>';
    $html .= '<p>Period: <strong>' . $startLabel . '</strong> to <strong>' . $endLabel . '</strong></p>';
    $html .= '<p>Total forecast income: <strong>£' . number_format((float)$data['summary']['total_forecast'], 2) . '</strong><br>';
    $html .= 'Total commission: <strong>£' . number_format((float)$data['summary']['total_commission'], 2) . '</strong><br>';
    $html .= 'Net after commission: <strong>£' . number_format((float)$data['summary']['total_net_after_comm'], 2) . '</strong></p>';

    $html .= '<table border="1" cellpadding="4" cellspacing="0" width="100%">';
    $html .= '<thead><tr>';
    $html .= '<th>Client</th><th>Renewal Date</th><th>Status</th><th>Rate/hr</th><th>Term (yrs)</th><th>Forecast</th><th>Comm %</th><th>Commission</th><th>Agent</th><th>Broker</th>';
    $html .= '</tr></thead><tbody>';

    foreach ($data['rows'] as $row) {
        $rateStr  = ((float)$row['rate_per_hour'] > 0) ? '£' . number_format((float)$row['rate_per_hour'], 2) : '';
        $termStr  = ((float)$row['term_years'] > 0) ? (string)$row['term_years'] : '';
        $valueStr = ($row['included']) ? '£' . number_format((float)$row['forecast_value'], 2) : '';

        $commPctStr = ((string)($row['commission_kind'] ?? '') === 'percent' && (float)($row['commission_rate'] ?? 0) > 0)
            ? number_format((float)$row['commission_rate'], 2) . '%'
            : '';

        $commValStr = ($row['included'] && (float)($row['commission_value'] ?? 0) > 0)
            ? '£' . number_format((float)$row['commission_value'], 2)
            : '';

        $html .= '<tr>';
        $html .= '<td>' . htmlspecialchars((string)$row['clientname']) . '</td>';
        $html .= '<td>' . htmlspecialchars((string)$row['renewal_label']) . '</td>';
        $html .= '<td>' . htmlspecialchars((string)$row['status']) . '</td>';
        $html .= '<td>' . $rateStr . '</td>';
        $html .= '<td>' . $termStr . '</td>';
        $html .= '<td>' . $valueStr . '</td>';
        $html .= '<td>' . $commPctStr . '</td>';
        $html .= '<td>' . $commValStr . '</td>';
        $html .= '<td>' . htmlspecialchars((string)$row['agent_name']) . '</td>';
        $html .= '<td>' . htmlspecialchars((string)$row['broker_name']) . '</td>';
        $html .= '</tr>';
    }

    $html .= '</tbody></table>';

    $mpdf = new \Mpdf\Mpdf(['format' => 'A4']);
    $mpdf->WriteHTML($html);
    $mpdf->Output('finance_forecast_' . date('Y-m-d_His') . '.pdf', 'D');
    exit;
}

// Fallback: JSON
header('Content-Type: application/json; charset=utf-8');
echo json_encode($data);
exit;