<?php

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

function enrep_inspection_report_date_timestamp($value, bool $endOfDay = false): ?int
{
    $timestamp = strtotime((string)$value);
    if ($timestamp === false) {
        return null;
    }

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

function enrep_inspection_report_frequency_months($value): float
{
    if (preg_match('/-?\d+(?:\.\d+)?/', (string)$value, $matches) !== 1) {
        return 0.0;
    }

    return max(0.0, (float)$matches[0]);
}

function enrep_inspection_report_add_frequency(int $timestamp, $frequencyMonths): int
{
    $frequencyMonths = enrep_inspection_report_frequency_months($frequencyMonths);
    if ($frequencyMonths <= 0) {
        return 0;
    }

    $months = (int)floor($frequencyMonths);
    $fraction = $frequencyMonths - $months;
    $date = new DateTime('@' . $timestamp);
    $date->setTimezone(new DateTimeZone(date_default_timezone_get()));

    if ($months > 0) {
        $date->modify('+' . $months . ' months');
    }

    if ($fraction > 0) {
        $date->modify('+' . max(1, (int)round($fraction * 30.436875)) . ' days');
    }

    return (int)$date->format('U');
}

function enrep_inspection_report_due_dates($firstDueDate, $frequencyMonths, int $startTs, int $endTs): array
{
    $dueDate = (int)$firstDueDate;
    if ($dueDate <= 0 || $dueDate > $endTs) {
        return [];
    }

    $frequencyMonths = enrep_inspection_report_frequency_months($frequencyMonths);
    if ($frequencyMonths <= 0) {
        return ($dueDate >= $startTs && $dueDate <= $endTs) ? [$dueDate] : [];
    }

    $dates = [];
    $guard = 0;
    while ($dueDate < $startTs && $guard < 1000) {
        $nextDueDate = enrep_inspection_report_add_frequency($dueDate, $frequencyMonths);
        if ($nextDueDate <= $dueDate) {
            break;
        }
        $dueDate = $nextDueDate;
        $guard++;
    }

    while ($dueDate <= $endTs && $guard < 1000) {
        if ($dueDate >= $startTs) {
            $dates[] = $dueDate;
        }

        $nextDueDate = enrep_inspection_report_add_frequency($dueDate, $frequencyMonths);
        if ($nextDueDate <= $dueDate) {
            break;
        }
        $dueDate = $nextDueDate;
        $guard++;
    }

    return $dates;
}

function enrep_inspection_report_context(array $request): array
{
    $startTs = enrep_inspection_report_date_timestamp($request['start'] ?? '');
    $endTs = enrep_inspection_report_date_timestamp($request['end'] ?? '', true);

    return [
        'start' => (string)($request['start'] ?? ''),
        'end' => (string)($request['end'] ?? ''),
        'startTs' => $startTs,
        'endTs' => $endTs,
        'mode' => (($request['mode'] ?? 'due') === 'done') ? 'done' : 'due',
        'clientnumber' => (int)($request['clientnumber'] ?? 0),
    ];
}

function enrep_inspection_report_client_rows(int $startTs, int $endTs, string $mode): array
{
    $dueCounts = [];
    $stmt = $GLOBALS['con']->prepare("
        SELECT a.clientnumber, a.duedate, COALESCE(dp.frequency, '') AS frequency
        FROM itemdetails a
        LEFT JOIN (SELECT code, MAX(frequency) AS frequency FROM dd_plant GROUP BY code) dp ON dp.code = a.code
        WHERE a.statuslive = '1'
          AND a.duedate IS NOT NULL
          AND a.duedate <> 0
          AND a.duedate <= ?
    ") or die(mysqli_error($GLOBALS['con']));
    $stmt->bind_param("i", $endTs);
    $stmt->execute();
    $dueAssets = $stmt->get_result();
    $stmt->close();

    while ($asset = mysqli_fetch_array($dueAssets)) {
        $clientnumber = (int)$asset['clientnumber'];
        $dueCounts[$clientnumber] = ($dueCounts[$clientnumber] ?? 0)
            + count(enrep_inspection_report_due_dates($asset['duedate'], $asset['frequency'], $startTs, $endTs));
    }

    $stmt = $GLOBALS['con']->prepare("
        SELECT
            c.clientnumber,
            c.clientname,
            COALESCE(active_assets.total_assets, 0) AS total_assets,
            COALESCE(done.inspections_done, 0) AS inspections_done
        FROM clientdetails c
        LEFT JOIN (
            SELECT clientnumber, COUNT(*) AS total_assets
            FROM itemdetails
            WHERE statuslive = '1'
            GROUP BY clientnumber
        ) active_assets ON active_assets.clientnumber = c.clientnumber
        LEFT JOIN (
            SELECT a.clientnumber, COUNT(*) AS inspections_done
            FROM reportitems a
            INNER JOIN itemdetails b ON b.itemnumber = a.itemnumber
            WHERE a.insdate BETWEEN ? AND ?
              AND b.statuslive = '1'
            GROUP BY a.clientnumber
        ) done ON done.clientnumber = c.clientnumber
        WHERE c.statuslive = '1'
        ORDER BY c.clientname ASC
    ") or die(mysqli_error($GLOBALS['con']));
    $stmt->bind_param("ii", $startTs, $endTs);
    $stmt->execute();
    $clientResults = $stmt->get_result();
    $stmt->close();

    $clients = [];
    while ($client = mysqli_fetch_array($clientResults)) {
        $clientnumber = (int)$client['clientnumber'];
        $client['inspections_due'] = $dueCounts[$clientnumber] ?? 0;

        if (($mode === 'done' && (int)$client['inspections_done'] > 0) || $mode === 'due') {
            $clients[] = $client;
        }
    }

    return $clients;
}

function enrep_inspection_report_item_rows(int $clientnumber, int $startTs, int $endTs, string $mode): array
{
    if ($mode === 'done') {
        $stmt = $GLOBALS['con']->prepare("
            SELECT a.insdate AS report_date, b.itemnumber, b.plantnumber, b.`desc` AS description, b.serialnumber
            FROM reportitems a
            INNER JOIN itemdetails b ON b.itemnumber = a.itemnumber
            WHERE a.clientnumber = ?
              AND a.insdate BETWEEN ? AND ?
              AND b.statuslive = '1'
            ORDER BY ABS(a.repitem) DESC
        ") or die(mysqli_error($GLOBALS['con']));
        $stmt->bind_param("iii", $clientnumber, $startTs, $endTs);
    } else {
        $stmt = $GLOBALS['con']->prepare("
            SELECT a.itemnumber, a.plantnumber, a.`desc` AS description, a.serialnumber, a.duedate, COALESCE(dp.frequency, '') AS frequency
            FROM itemdetails a
            LEFT JOIN (SELECT code, MAX(frequency) AS frequency FROM dd_plant GROUP BY code) dp ON dp.code = a.code
            WHERE a.clientnumber = ?
              AND a.statuslive = '1'
              AND a.duedate IS NOT NULL
              AND a.duedate <> 0
              AND a.duedate <= ?
            ORDER BY a.duedate ASC, a.`desc` ASC
        ") or die(mysqli_error($GLOBALS['con']));
        $stmt->bind_param("ii", $clientnumber, $endTs);
    }

    $stmt->execute();
    $items = $stmt->get_result();
    $stmt->close();

    $rows = [];
    while ($item = mysqli_fetch_array($items)) {
        $dueDates = ($mode === 'done')
            ? [(int)$item['report_date']]
            : enrep_inspection_report_due_dates($item['duedate'], $item['frequency'], $startTs, $endTs);

        foreach ($dueDates as $dateValue) {
            $item['report_date'] = $dateValue;
            $rows[] = $item;
        }
    }

    return $rows;
}

function enrep_inspection_report_client_totals(array $rows): array
{
    $totals = ['total_assets' => 0, 'inspections_done' => 0, 'inspections_due' => 0];
    foreach ($rows as $row) {
        $totals['total_assets'] += (int)$row['total_assets'];
        $totals['inspections_done'] += (int)$row['inspections_done'];
        $totals['inspections_due'] += (int)$row['inspections_due'];
    }
    return $totals;
}

function enrep_inspection_report_render_client_table(array $rows, string $mode = 'due', bool $actions = true): string
{
    $mode = $mode === 'done' ? 'done' : 'due';
    $totals = enrep_inspection_report_client_totals($rows);
    $html = '<div class="table-responsive"><table class="table table-striped table-sm table-bordered align-middle">';
    $html .= '<thead class="table-dark"><tr><th>Client</th><th>Active Assets</th><th>Inspections Done</th>';
    if ($mode === 'due') {
        $html .= '<th>Inspections To Do</th>';
    }
    if ($actions) {
        $html .= '<th class="text-end noprint no-print">Actions</th>';
    }
    $html .= '</tr></thead><tbody>';

    if (empty($rows)) {
        $colspan = 3 + ($mode === 'due' ? 1 : 0) + ($actions ? 1 : 0);
        $html .= '<tr><td colspan="' . $colspan . '" class="text-center text-muted">No clients found for this date range.</td></tr>';
    }

    foreach ($rows as $row) {
        $html .= '<tr>';
        $html .= '<td>' . enrep_inspection_report_h($row['clientname']) . '</td>';
        $html .= '<td>' . (int)$row['total_assets'] . '</td>';
        $html .= '<td>' . (int)$row['inspections_done'] . '</td>';
        if ($mode === 'due') {
            $html .= '<td>' . (int)$row['inspections_due'] . '</td>';
        }
        if ($actions) {
            $html .= '<td class="text-end noprint no-print"><a class="btn btn-secondary btn-sm" onclick="loadClient(\'' . (int)$row['clientnumber'] . '\')">Load Data</a></td>';
        }
        $html .= '</tr>';
    }

    $html .= '</tbody><tfoot class="table-dark"><tr><th>Total</th><th>' . (int)$totals['total_assets'] . '</th><th>' . (int)$totals['inspections_done'] . '</th>';
    if ($mode === 'due') {
        $html .= '<th>' . (int)$totals['inspections_due'] . '</th>';
    }
    if ($actions) {
        $html .= '<th class="noprint no-print"></th>';
    }
    $html .= '</tr></tfoot></table></div>';
    return $html;
}

function enrep_inspection_report_render_item_table(array $rows): string
{
    $html = '<div class="table-responsive"><table class="table table-striped table-sm table-bordered align-middle">';
    $html .= '<thead class="table-dark"><tr><th>Item</th><th>Plant Number</th><th>Serial Number</th><th>Location</th><th>Date</th></tr></thead><tbody>';

    if (empty($rows)) {
        $html .= '<tr><td colspan="5" class="text-center text-muted">No items found for this date range.</td></tr>';
    }

    foreach ($rows as $row) {
        $html .= '<tr>';
        $html .= '<td>' . enrep_inspection_report_h($row['description']) . '</td>';
        $html .= '<td>' . enrep_inspection_report_h($row['plantnumber']) . '</td>';
        $html .= '<td>' . enrep_inspection_report_h($row['serialnumber']) . '</td>';
        $html .= '<td>' . enrep_inspection_report_h(getItemLocation($row['itemnumber'], 'name') . ' - ' . getItemLocation($row['itemnumber'], 'postcode')) . '</td>';
        $html .= '<td>' . ((int)$row['report_date'] > 0 ? date('d-m-Y', (int)$row['report_date']) : '') . '</td>';
        $html .= '</tr>';
    }

    $html .= '</tbody><tfoot class="table-dark"><tr><th>Total</th><th>' . count($rows) . '</th><th></th><th></th><th></th></tr></tfoot></table></div>';
    return $html;
}

function enrep_inspection_report_export_csv(array $headers, array $rows, array $footer, string $filename): void
{
    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment; filename="' . $filename . '-' . date('Ymd-His') . '.csv"');

    $out = fopen('php://output', 'w');
    fputcsv($out, $headers);
    foreach ($rows as $row) {
        fputcsv($out, $row);
    }
    fputcsv($out, $footer);
    fclose($out);
    exit;
}

function enrep_inspection_report_export_pdf(string $html, string $filename): void
{
    $autoload = __DIR__ . '/../../packages/mpd/vendor/autoload.php';
    if (is_file($autoload)) {
        require_once $autoload;
        $mpdf = new \Mpdf\Mpdf([
            'orientation' => 'L',
            'margin_top' => 28,
            'margin_bottom' => 16,
            'margin_left' => 10,
            'margin_right' => 10,
        ]);

        $tenant = trim((string)(defined('TENANT_URL') ? TENANT_URL : ''), "/\\");
        $logoPath = $tenant !== '' ? __DIR__ . '/../../../' . $tenant . '/images/company/logo.jpg' : '';
        $logoHtml = is_file($logoPath)
            ? '<img src="' . enrep_inspection_report_h($logoPath) . '" style="height:45px;">'
            : '';

        $mpdf->SetHTMLHeader(
            '<table width="100%" style="border-bottom:1px solid #d9dde5; padding-bottom:6px;">
                <tr>
                    <td width="55%">' . $logoHtml . '</td>
                    <td width="45%" style="text-align:right; font-size:13px; font-weight:bold;">EnRep Reporting System</td>
                </tr>
            </table>'
        );
        $mpdf->SetHTMLFooter(
            '<table width="100%" style="border-top:1px solid #d9dde5; padding-top:4px; font-size:10px;">
                <tr>
                    <td>Generated by EnRep Reporting System: ' . date('d-m-Y') . '</td>
                    <td style="text-align:right;">Page {PAGENO} of {nbpg}</td>
                </tr>
            </table>'
        );

        $pdfHtml = '<style>
            body { font-family: sans-serif; font-size: 10px; color: #20242c; }
            h1 { font-size: 18px; margin: 0 0 6px 0; color: #20242c; }
            p { margin: 0 0 10px 0; }
            table { border-collapse: collapse; width: 100%; }
            th { background: #353b50; color: #ffffff; font-weight: bold; }
            th, td { border: 1px solid #cfd4dc; padding: 5px; text-align: left; }
            tfoot th { background: #353b50; color: #ffffff; }
        </style>' . $html;
        $mpdf->WriteHTML($pdfHtml);
        $mpdf->Output($filename . '-' . date('Ymd-His') . '.pdf', 'D');
        exit;
    }

    header('Content-Type: text/html; charset=utf-8');
    echo $html;
    exit;
}
