<?php
if (file_exists('../../../' . ($_REQUEST['tenant'] ?? '') . '/config.php')) {
    require_once('../../../' . $_REQUEST['tenant'] . '/config.php');
}

if (file_exists('/config.php')) {
    require_once('/config.php');
}

require('finance_functions.php');

function enrep_statement_h(string $value): string
{
    return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
}

function enrep_statement_date_to_range(string $date, bool $endOfDay = false): ?int
{
    $date = trim($date);
    if ($date === '') {
        return null;
    }

    $formats = ['d-m-Y', 'd/m/Y', 'Y-m-d'];
    foreach ($formats as $format) {
        $dt = DateTime::createFromFormat($format, $date);
        if ($dt instanceof DateTime && $dt->format($format) === $date) {
            $dt->setTime($endOfDay ? 23 : 0, $endOfDay ? 59 : 0, $endOfDay ? 59 : 0);
            return $dt->getTimestamp();
        }
    }

    $ts = strtotime($date);
    if ($ts === false) {
        return null;
    }

    return $endOfDay ? strtotime('23:59:59', $ts) : strtotime('00:00:00', $ts);
}

function enrep_statement_money_from_totals(?string $totals): array
{
    $parts = explode('|', (string)$totals);
    $net = (float)str_replace(',', '', $parts[0] ?? '0');
    $vat = (float)str_replace(',', '', $parts[1] ?? '0');

    return [
        'net' => $net,
        'vat' => $vat,
        'gross' => $net + $vat,
    ];
}

function enrep_statement_status_label(int $status, int $dueDate): string
{
    if ($status === 3) {
        return '<span class="badge bg-success">Paid</span>';
    }
    if ($status === 1 && $dueDate > 0 && $dueDate < time()) {
        return '<span class="badge bg-danger">Overdue</span>';
    }
    if ($status === 1) {
        return '<span class="badge bg-warning text-dark">Unpaid</span>';
    }
    if ($status === 2) {
        return '<span class="badge bg-info text-dark">Reminder</span>';
    }

    return '<span class="badge bg-secondary">Status ' . $status . '</span>';
}

function enrep_statement_account_details(string $target, int $accountNumber): array
{
    if ($target === 'broker') {
        $stmt = $GLOBALS['con']->prepare("SELECT broker_name AS name, billing_name, billing_email, billing_phone, email FROM brokers WHERE broker_number=? LIMIT 1");
    } elseif ($target === 'agent') {
        $stmt = $GLOBALS['con']->prepare("SELECT agent_name AS name, billing_name, billing_email, billing_phone, email FROM agents WHERE agent_number=? LIMIT 1");
    } else {
        $stmt = $GLOBALS['con']->prepare("SELECT clientname AS name, billing_name, billing_email, email FROM clientdetails WHERE clientnumber=? LIMIT 1");
    }

    if (!$stmt) {
        return ['name' => 'Unknown account', 'billing_name' => '', 'billing_email' => '', 'billing_phone' => '', 'email' => ''];
    }

    $stmt->bind_param('i', $accountNumber);
    $stmt->execute();
    $result = $stmt->get_result();
    $stmt->close();
    $row = $result ? mysqli_fetch_assoc($result) : null;

    if (!$row) {
        return ['name' => 'All clients', 'billing_name' => '', 'billing_email' => '', 'billing_phone' => '', 'email' => ''];
    }

    return $row;
}

function enrep_statement_bind(mysqli_stmt $stmt, string $types, array &$params): void
{
    $refs = [&$types];
    foreach ($params as $key => $value) {
        $refs[] = &$params[$key];
    }
    call_user_func_array([$stmt, 'bind_param'], $refs);
}

function enrep_statement_error(string $message): void
{
    echo '<div class="alert alert-warning mb-0">' . enrep_statement_h($message) . '</div>';
}

if (($_REQUEST['mode'] ?? '') !== 'render') {
    enrep_statement_error('Statement mode was not supplied.');
    exit;
}

$target = (string)($_REQUEST['target'] ?? 'client');
if (!in_array($target, ['client', 'broker', 'agent'], true)) {
    enrep_statement_error('Unknown statement target.');
    exit;
}

$status = (string)($_REQUEST['status'] ?? 'both');
if (!in_array($status, ['paid', 'unpaid', 'both'], true)) {
    $status = 'both';
}

$startRaw = (string)($_REQUEST['start'] ?? '');
$endRaw = (string)($_REQUEST['end'] ?? '');
$start = enrep_statement_date_to_range($startRaw);
$end = enrep_statement_date_to_range($endRaw, true);
if ($start === null || $end === null || $start > $end) {
    enrep_statement_error('Please choose a valid statement date range.');
    exit;
}

$accountNumber = (int)($_REQUEST['account_number'] ?? 0);
$clientnumber = (int)($_REQUEST['clientnumber'] ?? 0);

if (($target === 'broker' || $target === 'agent') && $accountNumber <= 0) {
    enrep_statement_error('Please choose a ' . $target . ' for this statement.');
    exit;
}

$where = ['i.`date` BETWEEN ? AND ?', 'i.`target` = ?'];
$types = 'iis';
$params = [$start, $end, $target];

if ($status === 'paid') {
    $where[] = 'i.`status` = 3';
} elseif ($status === 'unpaid') {
    $where[] = 'i.`status` IN (1, 2)';
} else {
    $where[] = 'i.`status` IN (1, 2, 3)';
}

if ($target === 'client') {
    $accountNumber = $clientnumber;
    if ($clientnumber > 0) {
        $where[] = 'i.`client` = ?';
        $types .= 'i';
        $params[] = $clientnumber;
    }
} elseif ($target === 'broker') {
    $where[] = 'i.`broker` = ?';
    $types .= 'i';
    $params[] = $accountNumber;
    if ($clientnumber > 0) {
        $where[] = 'i.`client` = ?';
        $types .= 'i';
        $params[] = $clientnumber;
    }
} else {
    $where[] = 'i.`agent` = ?';
    $types .= 'i';
    $params[] = $accountNumber;
    if ($clientnumber > 0) {
        $where[] = 'i.`client` = ?';
        $types .= 'i';
        $params[] = $clientnumber;
    }
}

$sql = "
    SELECT
        i.invNo, i.client, i.agent, i.broker, i.address, i.totals, i.`date`, i.date_due, i.date_paid, i.`status`, i.`target`,
        cd.clientname, cd.billing_name AS client_billing_name,
        ag.agent_name, ag.billing_name AS agent_billing_name,
        br.broker_name, br.billing_name AS broker_billing_name
    FROM invoices i
    LEFT JOIN clientdetails cd ON cd.clientnumber = i.client
    LEFT JOIN agents ag ON ag.agent_number = i.agent
    LEFT JOIN brokers br ON br.broker_number = i.broker
    WHERE " . implode(' AND ', $where) . "
    ORDER BY i.`date` ASC, i.invNo ASC
";

$stmt = $GLOBALS['con']->prepare($sql);
if (!$stmt) {
    enrep_statement_error('Statement query could not be prepared.');
    exit;
}
enrep_statement_bind($stmt, $types, $params);
$stmt->execute();
$result = $stmt->get_result();
$stmt->close();

$rows = [];
$totalNet = 0.0;
$totalVat = 0.0;
$totalPaid = 0.0;
$totalUnpaid = 0.0;

while ($row = mysqli_fetch_assoc($result)) {
    $money = enrep_statement_money_from_totals($row['totals'] ?? '');
    $row['_net'] = $money['net'];
    $row['_vat'] = $money['vat'];
    $row['_gross'] = $money['gross'];
    $totalNet += $money['net'];
    $totalVat += $money['vat'];
    if ((int)$row['status'] === 3) {
        $totalPaid += $money['gross'];
    } else {
        $totalUnpaid += $money['gross'];
    }
    $rows[] = $row;
}

$account = enrep_statement_account_details($target, $accountNumber);
$titleMap = [
    'client' => 'Client statement',
    'broker' => 'Broker statement',
    'agent' => 'Agent statement',
];
$statusMap = [
    'both' => 'Paid and unpaid invoices',
    'paid' => 'Paid invoices',
    'unpaid' => 'Unpaid invoices',
];
$statementTitle = $titleMap[$target];
$accountName = (string)($account['name'] ?? 'All clients');
$statementId = 'statementPrint_' . time();
$isPrint = (($_REQUEST['print'] ?? '') === '1');
$printQuery = http_build_query([
    'mode' => 'render',
    'print' => '1',
    'tenant' => (string)($_REQUEST['tenant'] ?? ''),
    'target' => $target,
    'account_number' => $accountNumber,
    'clientnumber' => $clientnumber,
    'status' => $status,
    'start' => $startRaw,
    'end' => $endRaw,
]);
$printScriptPath = 'includes/finance/statement_data.php?' . $printQuery;
$printHeader = $statementTitle . ' - ' . $accountName;
?>

<style>
.statement-summary-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: .75rem;
}
.statement-summary {
    border: 1px solid rgba(0, 0, 0, .08);
    border-radius: 8px;
    padding: .75rem;
    background: #f8fafc;
}
.statement-summary span {
    display: block;
    color: #6c757d;
    font-size: .78rem;
    text-transform: uppercase;
}
.statement-summary strong {
    font-size: 1.05rem;
}
.statement-print-head {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem 1.25rem;
    align-items: baseline;
    justify-content: space-between;
}
.statement-print-head h3 {
    font-size: 1rem;
    margin: 0;
}
.statement-print-line {
    display: flex;
    flex-wrap: wrap;
    gap: .35rem .9rem;
    align-items: baseline;
}
.statement-print-meta {
    justify-content: flex-end;
}
@media (max-width: 991px) {
    .statement-summary-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .statement-print-head {
        display: flex;
    }
}
@media (max-width: 575px) {
    .statement-summary-grid {
        grid-template-columns: 1fr;
    }
}
@media print {
    .noprint {
        display: none !important;
    }
}
</style>

<?php if (!$isPrint) { ?>
    <div class="d-flex flex-wrap justify-content-between gap-2 mb-3">
        <div>
            <h4 class="mb-1"><?= enrep_statement_h($statementTitle) ?></h4>
            <div class="text-muted"><?= enrep_statement_h($statusMap[$status]) ?> from <?= enrep_statement_h($startRaw) ?> to <?= enrep_statement_h($endRaw) ?></div>
        </div>
        <div class="d-flex gap-2">
            <button type="button" class="btn btn-outline-secondary btn-sm" onclick='enrepPrintStatement(<?= json_encode($printScriptPath, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_SLASHES) ?>, <?= json_encode($printHeader, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_SLASHES) ?>)'>
                <i class="fad fa-print me-1"></i> Print
            </button>
        </div>
    </div>
<?php } ?>

<div id="<?= $statementId ?>">
    <div class="statement-print-head mb-3">
        <div class="statement-print-line">
            <h3><?= enrep_statement_h($statementTitle) ?></h3>
            <strong><?= enrep_statement_h($accountName) ?></strong>
            <?php if (!empty($account['billing_name'])) { ?><span><?= enrep_statement_h((string)$account['billing_name']) ?></span><?php } ?>
            <?php if (!empty($account['billing_email'])) { ?><span><?= enrep_statement_h((string)$account['billing_email']) ?></span><?php } ?>
        </div>
        <div class="statement-print-line statement-print-meta">
            <span><strong>Period</strong> <?= enrep_statement_h($startRaw) ?> to <?= enrep_statement_h($endRaw) ?></span>
            <span class="text-muted"><?= enrep_statement_h($statusMap[$status]) ?></span>
        </div>
    </div>

    <div class="statement-summary-grid noprint mb-3">
        <div class="statement-summary"><span>Invoices</span><strong><?= count($rows) ?></strong></div>
        <div class="statement-summary"><span>Paid</span><strong>&pound;<?= number_format($totalPaid, 2) ?></strong></div>
        <div class="statement-summary"><span>Outstanding</span><strong>&pound;<?= number_format($totalUnpaid, 2) ?></strong></div>
        <div class="statement-summary"><span>Total value</span><strong>&pound;<?= number_format($totalPaid + $totalUnpaid, 2) ?></strong></div>
    </div>

    <?php if (empty($rows)) { ?>
        <div class="alert alert-info mb-0">No invoices matched this statement selection.</div>
    <?php } else { ?>
        <div class="table-responsive">
            <table class="table table-sm table-striped align-middle">
                <thead>
                    <tr>
                        <th>Invoice</th>
                        <th>Invoice date</th>
                        <th>Client</th>
                        <?php if ($target !== 'agent') { ?><th>Agent</th><?php } ?>
                        <?php if ($target !== 'broker') { ?><th>Broker</th><?php } ?>
                        <th>Contract</th>
                        <th class="text-end">Net</th>
                        <th class="text-end">VAT</th>
                        <th class="text-end">Gross</th>
                        <th>Status</th>
                        <th>Paid date</th>
                    </tr>
                </thead>
                <tbody>
                    <?php foreach ($rows as $row) {
                        $address = @unserialize((string)($row['address'] ?? ''));
                        if (!is_array($address)) {
                            $address = [];
                        }
                        $invoiceDate = !empty($row['date']) ? date('d-m-Y', (int)$row['date']) : '';
                        $paidDate = !empty($row['date_paid']) ? date('d-m-Y', (int)$row['date_paid']) : '';
                        $contract = (string)($address['contract_number'] ?? '');
                    ?>
                        <tr>
                            <td><?= sprintf('%06d', (int)$row['invNo']) ?></td>
                            <td><?= enrep_statement_h($invoiceDate) ?></td>
                            <td><?= enrep_statement_h((string)($row['clientname'] ?? $address['client_name'] ?? '')) ?></td>
                            <?php if ($target !== 'agent') { ?><td><?= enrep_statement_h((string)($row['agent_name'] ?? $address['agent_name'] ?? '')) ?></td><?php } ?>
                            <?php if ($target !== 'broker') { ?><td><?= enrep_statement_h((string)($row['broker_name'] ?? $address['broker_name'] ?? '')) ?></td><?php } ?>
                            <td><?= enrep_statement_h($contract) ?></td>
                            <td class="text-end">&pound;<?= number_format((float)$row['_net'], 2) ?></td>
                            <td class="text-end">&pound;<?= number_format((float)$row['_vat'], 2) ?></td>
                            <td class="text-end">&pound;<?= number_format((float)$row['_gross'], 2) ?></td>
                            <td><?= enrep_statement_status_label((int)$row['status'], (int)($row['date_due'] ?? 0)) ?></td>
                            <td><?= enrep_statement_h($paidDate) ?></td>
                        </tr>
                    <?php } ?>
                </tbody>
                <tfoot>
                    <tr>
                        <th colspan="<?= $target === 'client' ? '6' : '5' ?>" class="text-end">Totals</th>
                        <th class="text-end">&pound;<?= number_format($totalNet, 2) ?></th>
                        <th class="text-end">&pound;<?= number_format($totalVat, 2) ?></th>
                        <th class="text-end">&pound;<?= number_format($totalNet + $totalVat, 2) ?></th>
                        <th colspan="2"></th>
                    </tr>
                </tfoot>
            </table>
        </div>
    <?php } ?>
</div>
