<?php

require_once __DIR__ . '/../../functions/logging.php';

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

function enrep_log_display_category($value): string
{
    $label = str_replace('_', ' ', trim((string)$value));
    return $label === '' ? '' : ucfirst($label);
}

function enrep_log_request_filters(): array
{
    $get = $_GET + $_POST;

    return [
        'category' => trim((string)($get['category'] ?? '')),
        'action' => trim((string)($get['action'] ?? '')),
        'actor' => trim((string)($get['actor'] ?? '')),
        'date_from' => trim((string)($get['date_from'] ?? '')),
        'date_to' => trim((string)($get['date_to'] ?? '')),
        'search' => trim((string)($get['search'] ?? '')),
    ];
}

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

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

    $time = strtotime($value . ($endOfDay ? ' 23:59:59' : ' 00:00:00'));
    return $time === false ? null : $time;
}

function enrep_log_display_date(string $value): string
{
    $time = enrep_log_parse_date($value);
    return $time === null ? '' : date('d-m-Y', $time);
}

function enrep_log_filter_query(array $filters, string $prefix = '?'): string
{
    $params = [];
    foreach ($filters as $key => $value) {
        if ($value !== '' && $value !== null) {
            $params[$key] = $value;
        }
    }

    return $prefix . http_build_query($params);
}

function enrep_log_build_where(array $filters, array &$params, string &$types): string
{
    $where = [];

    if ($filters['category'] !== '') {
        $where[] = '`category` = ?';
        $types .= 's';
        $params[] = $filters['category'];
    }

    if ($filters['action'] !== '') {
        $where[] = '`action` = ?';
        $types .= 's';
        $params[] = $filters['action'];
    }

    if ($filters['actor'] !== '') {
        $where[] = '(`actor_name` LIKE ? OR CAST(`actor_id` AS CHAR) = ?)';
        $types .= 'ss';
        $params[] = '%' . $filters['actor'] . '%';
        $params[] = $filters['actor'];
    }

    if ($filters['date_from'] !== '') {
        $from = enrep_log_parse_date($filters['date_from']);
        if ($from !== null) {
            $where[] = '`created_at` >= ?';
            $types .= 'i';
            $params[] = $from;
        }
    }

    if ($filters['date_to'] !== '') {
        $to = enrep_log_parse_date($filters['date_to'], true);
        if ($to !== null) {
            $where[] = '`created_at` <= ?';
            $types .= 'i';
            $params[] = $to;
        }
    }

    if ($filters['search'] !== '') {
        $where[] = '(`message` LIKE ? OR `subject` LIKE ? OR `entity_id` LIKE ?)';
        $types .= 'sss';
        $like = '%' . $filters['search'] . '%';
        $params[] = $like;
        $params[] = $like;
        $params[] = $like;
    }

    return empty($where) ? '' : ' WHERE ' . implode(' AND ', $where);
}

function enrep_log_bind(mysqli_stmt $stmt, string $types, array &$params): void
{
    if ($types === '') {
        return;
    }

    $refs = [$types];
    foreach ($params as $key => &$value) {
        $refs[] = &$value;
    }
    call_user_func_array([$stmt, 'bind_param'], $refs);
}

function enrep_log_fetch(array $filters, int $limit = 500, int $offset = 0): array
{
    $params = [];
    $types = '';
    $where = enrep_log_build_where($filters, $params, $types);

    $sql = "SELECT * FROM `log`" . $where . " ORDER BY `created_at` DESC, `id` DESC LIMIT ? OFFSET ?";
    $types .= 'ii';
    $params[] = $limit;
    $params[] = $offset;

    $stmt = $GLOBALS['con']->prepare($sql);
    if (!$stmt) {
        return [];
    }

    enrep_log_bind($stmt, $types, $params);
    $stmt->execute();
    $res = $stmt->get_result();
    $rows = $res ? $res->fetch_all(MYSQLI_ASSOC) : [];
    $stmt->close();

    return $rows;
}

function enrep_log_count(array $filters): int
{
    $params = [];
    $types = '';
    $where = enrep_log_build_where($filters, $params, $types);

    $stmt = $GLOBALS['con']->prepare("SELECT COUNT(*) AS total FROM `log`" . $where);
    if (!$stmt) {
        return 0;
    }

    enrep_log_bind($stmt, $types, $params);
    $stmt->execute();
    $res = $stmt->get_result();
    $row = $res ? $res->fetch_assoc() : ['total' => 0];
    $stmt->close();

    return (int)($row['total'] ?? 0);
}

function enrep_log_distinct(string $column): array
{
    $allowed = ['category', 'action', 'actor_name'];
    if (!in_array($column, $allowed, true)) {
        return [];
    }

    $res = $GLOBALS['con']->query("SELECT DISTINCT `$column` AS value FROM `log` WHERE `$column` IS NOT NULL AND `$column` <> '' ORDER BY `$column` ASC");
    if (!$res) {
        return [];
    }

    $values = [];
    while ($row = $res->fetch_assoc()) {
        $values[] = (string)$row['value'];
    }

    return $values;
}

function enrep_log_delete(int $id): bool
{
    $stmt = $GLOBALS['con']->prepare("DELETE FROM `log` WHERE `id`=? LIMIT 1");
    if (!$stmt) {
        return false;
    }

    $stmt->bind_param('i', $id);
    $ok = $stmt->execute();
    $stmt->close();

    return $ok;
}

function enrep_log_clear_category(string $category): bool
{
    if ($category === '') {
        return false;
    }

    $stmt = $GLOBALS['con']->prepare("DELETE FROM `log` WHERE `category`=?");
    if (!$stmt) {
        return false;
    }

    $stmt->bind_param('s', $category);
    $ok = $stmt->execute();
    $stmt->close();

    return $ok;
}

function enrep_log_is_super_admin(): bool
{
    return (string)($_SESSION['usertype'] ?? '') === 'admins' && (int)($_SESSION['access'] ?? 0) === 999;
}

function enrep_log_row_attachments(array $row): array
{
    $context = json_decode((string)($row['context_json'] ?? ''), true);
    if (!is_array($context) || empty($context['attachments']) || !is_array($context['attachments'])) {
        return [];
    }

    return $context['attachments'];
}

function enrep_log_render_table(array $rows, bool $actions = true): string
{
    $html = '<div class="table-responsive"><table class="table table-striped table-sm align-middle">';
    $html .= '<thead class="table-dark"><tr><th>Date</th><th>Category</th><th>Action</th><th>User</th><th>Subject</th><th>Message</th><th>Attachments</th>';
    if ($actions) {
        $html .= '<th class="text-end noprint no-print">Actions</th>';
    }
    $html .= '</tr></thead><tbody>';

    if (empty($rows)) {
        $colspan = $actions ? 8 : 7;
        $html .= '<tr><td colspan="' . $colspan . '" class="text-center text-muted">No log entries found.</td></tr>';
    }

    foreach ($rows as $row) {
        $attachments = enrep_log_row_attachments($row);
        $html .= '<tr id="logRow' . (int)$row['id'] . '">';
        $html .= '<td>' . enrep_log_h(date('d-m-Y H:i', (int)$row['created_at'])) . '</td>';
        $html .= '<td>' . enrep_log_h(enrep_log_display_category($row['category'])) . '</td>';
        $html .= '<td>' . enrep_log_h($row['action']) . '</td>';
        $html .= '<td>' . enrep_log_h($row['actor_name']) . '<br><small class="text-muted">' . enrep_log_h($row['actor_type'] . ' #' . $row['actor_id']) . '</small></td>';
        $html .= '<td>' . enrep_log_h($row['subject'] ?: $row['entity_type'] . ' ' . $row['entity_id']) . '</td>';
        $html .= '<td>' . nl2br(enrep_log_h($row['message'])) . '</td>';
        if (!empty($attachments)) {
            $html .= '<td><button type="button" class="btn btn-info btn-sm noprint no-print" onclick="openLogAttachments(' . (int)$row['id'] . ')"><i class="fad fa-paperclip me-1"></i>' . count($attachments) . '</button><span class="d-none d-print-inline">' . count($attachments) . ' attachment(s)</span></td>';
        } else {
            $html .= '<td class="text-muted">None</td>';
        }
        if ($actions) {
            $html .= '<td class="text-end noprint no-print">';
            if (enrep_log_is_super_admin()) {
                $html .= '<button type="button" class="btn btn-danger btn-sm" onclick="confirmDeleteLogEntry(' . (int)$row['id'] . ')"><i class="fad fa-trash"></i></button>';
            } else {
                $html .= '<span class="text-muted">Restricted</span>';
            }
            $html .= '</td>';
        }
        $html .= '</tr>';
    }

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

    return $html;
}

function enrep_log_export_csv(array $rows): void
{
    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment; filename="enrep-log-' . date('Ymd-His') . '.csv"');

    $out = fopen('php://output', 'w');
    fputcsv($out, ['Date', 'Category', 'Action', 'Person', 'Actor Type', 'Actor ID', 'Entity Type', 'Entity ID', 'Client', 'Site', 'Item', 'Subject', 'Message', 'Context']);
    foreach ($rows as $row) {
        fputcsv($out, [
            date('Y-m-d H:i:s', (int)$row['created_at']),
            $row['category'],
            $row['action'],
            $row['actor_name'],
            $row['actor_type'],
            $row['actor_id'],
            $row['entity_type'],
            $row['entity_id'],
            $row['clientnumber'],
            $row['locnumber'],
            $row['itemnumber'],
            $row['subject'],
            $row['message'],
            $row['context_json'],
        ]);
    }
    fclose($out);
    exit;
}

function enrep_log_export_pdf(array $rows, array $filters): void
{
    $title = 'EnRep Log Report';
    $html = '<h1>' . enrep_log_h($title) . '</h1>';
    $html .= '<p>Generated ' . date('d-m-Y H:i') . '</p>';
    $html .= enrep_log_render_table($rows, false);

    $autoload = __DIR__ . '/../../packages/mpd/vendor/autoload.php';
    if (is_file($autoload)) {
        require_once $autoload;
        $mpdf = new \Mpdf\Mpdf(['orientation' => 'L']);
        $mpdf->WriteHTML($html);
        $mpdf->Output('enrep-log-' . date('Ymd-His') . '.pdf', 'D');
        exit;
    }

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