<?php
// =============================================================
//  GET /api/v1/audit_logs/list
//
//  Mirrors app/audit_logs.php's own page-data query: a UNION across
//  the two possible audit tables (audit_log — a simple general-action
//  log, not present in every deployment; permission_audit_logs — the
//  structured resource-level change log this app already writes to
//  from every admin_* endpoint's own logAudit() call), paginated,
//  filterable, with today/this-week counts. Gated on
//  'manage_permissions', the same permission the desktop page uses.
//
//  Query params (all optional): q, user_filter, source_filter,
//  date_from, date_to, page (default 1, 50 rows/page — same as desktop).
//
//  User display names are resolved server-side across all three
//  account tables (users/rotation_nurses/clinical_students), exactly
//  as the desktop page does — including its own known quirk of
//  showing "User #0" for a login-action row whose user_id is NULL
//  (the desktop stores the acting account's id in resource_id instead
//  for that action type, but never actually resolves it back to a
//  name either) — ported faithfully rather than silently improved,
//  since fixing display-name resolution for one action type here
//  without also fixing the desktop page would create a visible
//  mobile/desktop discrepancy for no documented reason.
// =============================================================

require_once __DIR__ . '/../_bootstrap.php';

if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
    Api::error(405, 'MethodNotAllowed', 'Use GET');
}

api_authenticate();
api_require_permission('manage_permissions');

function api_audit_table_exists(mysqli $db, string $table): bool {
    $safe = $db->real_escape_string($table);
    $r = $db->query("SHOW TABLES LIKE '$safe'");
    return $r && $r->num_rows > 0;
}

$hasAuditLog  = api_audit_table_exists($conn, 'audit_log');
$hasPermAudit = api_audit_table_exists($conn, 'permission_audit_logs');

$fSearch = trim((string)($_GET['q'] ?? ''));
$fUser   = (int)($_GET['user_filter'] ?? 0);
$fSource = trim((string)($_GET['source_filter'] ?? '')); // 'audit_log' | 'permission_audit_logs' | ''
$fFrom   = trim((string)($_GET['date_from'] ?? ''));
$fTo     = trim((string)($_GET['date_to'] ?? ''));
$page    = max(1, (int)($_GET['page'] ?? 1));
$perPage = 50;

$logs = [];
$totalCount = 0;
$todayCount = 0;
$weekCount  = 0;
$totalPages = 1;

if ($hasAuditLog || $hasPermAudit) {
    $parts  = [];
    $params = [];
    $types  = '';

    if ($hasAuditLog && (!$fSource || $fSource === 'audit_log')) {
        $where = ['1=1'];
        if ($fUser)   { $where[] = 'al.user_id = ?'; $params[] = $fUser; $types .= 'i'; }
        if ($fFrom)   { $where[] = 'al.created_at >= ?'; $params[] = $fFrom . ' 00:00:00'; $types .= 's'; }
        if ($fTo)     { $where[] = 'al.created_at <= ?'; $params[] = $fTo . ' 23:59:59'; $types .= 's'; }
        if ($fSearch) { $where[] = '(al.action LIKE ? OR al.details LIKE ?)'; $params[] = "%$fSearch%"; $params[] = "%$fSearch%"; $types .= 'ss'; }
        $w = implode(' AND ', $where);
        $parts[] = "
            SELECT al.id, al.user_id, al.action,
                   al.details AS detail_text, NULL AS resource_type, NULL AS resource_id,
                   NULL AS new_value, al.ip_address, NULL AS user_agent,
                   al.created_at, 'audit_log' AS source
            FROM audit_log al
            WHERE $w
        ";
    }

    if ($hasPermAudit && (!$fSource || $fSource === 'permission_audit_logs')) {
        $where = ['1=1'];
        if ($fUser)   { $where[] = 'pal.user_id = ?'; $params[] = $fUser; $types .= 'i'; }
        if ($fFrom)   { $where[] = 'pal.created_at >= ?'; $params[] = $fFrom . ' 00:00:00'; $types .= 's'; }
        if ($fTo)     { $where[] = 'pal.created_at <= ?'; $params[] = $fTo . ' 23:59:59'; $types .= 's'; }
        if ($fSearch) { $where[] = '(pal.action LIKE ? OR pal.resource_type LIKE ? OR pal.new_value LIKE ?)'; $params[] = "%$fSearch%"; $params[] = "%$fSearch%"; $params[] = "%$fSearch%"; $types .= 'sss'; }
        $w = implode(' AND ', $where);
        $parts[] = "
            SELECT pal.id, pal.user_id, pal.action,
                   NULL AS detail_text, pal.resource_type, pal.resource_id,
                   pal.new_value, pal.ip_address, pal.user_agent,
                   pal.created_at, 'permission_audit_logs' AS source
            FROM permission_audit_logs pal
            WHERE $w
        ";
    }

    if (!empty($parts)) {
        $unionSql = '(' . implode(') UNION ALL (', $parts) . ')';

        $countStmt = $conn->prepare("SELECT COUNT(*) AS cnt FROM ($unionSql) t");
        if (!empty($params)) $countStmt->bind_param($types, ...$params);
        $countStmt->execute();
        $totalCount = (int)$countStmt->get_result()->fetch_assoc()['cnt'];
        $countStmt->close();

        $offset = ($page - 1) * $perPage;
        $listTypes  = $types . 'ii';
        $listParams = array_merge($params, [$perPage, $offset]);
        $listStmt = $conn->prepare("SELECT * FROM ($unionSql) t ORDER BY t.created_at DESC LIMIT ? OFFSET ?");
        $listStmt->bind_param($listTypes, ...$listParams);
        $listStmt->execute();
        $logs = $listStmt->get_result()->fetch_all(MYSQLI_ASSOC);
        $listStmt->close();

        $todayStmt = $conn->prepare("SELECT COUNT(*) AS cnt FROM ($unionSql) t WHERE DATE(t.created_at) = CURDATE()");
        if (!empty($params)) $todayStmt->bind_param($types, ...$params);
        $todayStmt->execute();
        $todayCount = (int)$todayStmt->get_result()->fetch_assoc()['cnt'];
        $todayStmt->close();

        $weekStmt = $conn->prepare("SELECT COUNT(*) AS cnt FROM ($unionSql) t WHERE t.created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)");
        if (!empty($params)) $weekStmt->bind_param($types, ...$params);
        $weekStmt->execute();
        $weekCount = (int)$weekStmt->get_result()->fetch_assoc()['cnt'];
        $weekStmt->close();

        $totalPages = $totalCount > 0 ? (int)ceil($totalCount / $perPage) : 1;
    }
}

// ── Resolve user display names across all three account tables ──────
$userIds = [];
foreach ($logs as $l) {
    $uid = (int)($l['user_id'] ?? 0);
    if ($uid) $userIds[$uid] = true;
}
$userIds = array_keys($userIds);

$userNames = [];
if (!empty($userIds)) {
    $ph     = implode(',', array_fill(0, count($userIds), '?'));
    $typesU = str_repeat('i', count($userIds));

    $uStmt = $conn->prepare("SELECT id, firstname, surname, usertype FROM users WHERE id IN ($ph)");
    $uStmt->bind_param($typesU, ...$userIds);
    $uStmt->execute();
    $r = $uStmt->get_result();
    while ($row = $r->fetch_assoc()) {
        $userNames[(int)$row['id']] = trim($row['firstname'] . ' ' . $row['surname']) . ' (' . str_replace('_', ' ', $row['usertype']) . ')';
    }
    $uStmt->close();

    $rnStmt = $conn->prepare("SELECT id, firstname, surname FROM rotation_nurses WHERE id IN ($ph)");
    $rnStmt->bind_param($typesU, ...$userIds);
    $rnStmt->execute();
    $r = $rnStmt->get_result();
    while ($row = $r->fetch_assoc()) {
        $key = (int)$row['id'];
        if (!isset($userNames[$key])) $userNames[$key] = trim($row['firstname'] . ' ' . $row['surname']) . ' (Rotation Nurse)';
    }
    $rnStmt->close();

    $csStmt = $conn->prepare("SELECT id, firstname, surname FROM clinical_students WHERE id IN ($ph)");
    $csStmt->bind_param($typesU, ...$userIds);
    $csStmt->execute();
    $r = $csStmt->get_result();
    while ($row = $r->fetch_assoc()) {
        $key = (int)$row['id'];
        if (!isset($userNames[$key])) $userNames[$key] = trim($row['firstname'] . ' ' . $row['surname']) . ' (Clinical Student)';
    }
    $csStmt->close();
}

foreach ($logs as &$log) {
    $log['id']          = (int)$log['id'];
    $log['user_id']     = $log['user_id'] !== null ? (int)$log['user_id'] : null;
    $log['resource_id'] = $log['resource_id'] !== null ? (int)$log['resource_id'] : null;
    $uid = (int)($log['user_id'] ?? 0);
    $log['user_display'] = $userNames[$uid] ?? ('User #' . $uid);
}
unset($log);

$staff = $conn->query("SELECT id, firstname, surname, usertype FROM users ORDER BY firstname")->fetch_all(MYSQLI_ASSOC);
foreach ($staff as &$s) {
    $s['id']   = (int)$s['id'];
    $s['name'] = trim($s['firstname'] . ' ' . $s['surname']);
}
unset($s);

Api::success([
    'logs'         => $logs,
    'total_count'  => $totalCount,
    'today_count'  => $todayCount,
    'week_count'   => $weekCount,
    'page'         => $page,
    'total_pages'  => $totalPages,
    'staff'        => $staff,
    'has_audit_log'  => $hasAuditLog,
    'has_perm_audit' => $hasPermAudit,
]);
