database = $database; $this->session = $session; } public function log(string $action, string $table, int $recordId, array $oldValue = null, array $newValue = null): void { $userId = $this->session->getUserId(); if (!$userId) { return; // Skip logging if no user } $data = [ 'user_id' => $userId, 'action' => $action, 'table_name' => $table, 'record_id' => $recordId, 'old_value' => $oldValue ? json_encode($oldValue) : null, 'new_value' => $newValue ? json_encode($newValue) : null, 'created_at' => date('Y-m-d H:i:s') ]; try { $this->database->insert('audit_log', $data); } catch (\Exception $e) { error_log('Audit logging failed: ' . $e->getMessage()); } } public function getAuditLog(string $table = null, int $recordId = null, int $limit = 100): array { $sql = "SELECT al.*, u.name as user_name FROM audit_log al LEFT JOIN users u ON al.user_id = u.id WHERE 1=1"; $params = []; if ($table) { $sql .= " AND al.table_name = :table"; $params['table'] = $table; } if ($recordId) { $sql .= " AND al.record_id = :record_id"; $params['record_id'] = $recordId; } $sql .= " ORDER BY al.created_at DESC LIMIT :limit"; $params['limit'] = $limit; return $this->database->fetchAll($sql, $params); } public function getAssetHistory(int $assetId): array { return $this->getAuditLog('assets', $assetId); } public function getUserActivity(int $userId, int $limit = 50): array { $sql = "SELECT al.*, u.name as user_name FROM audit_log al LEFT JOIN users u ON al.user_id = u.id WHERE al.user_id = :user_id ORDER BY al.created_at DESC LIMIT :limit"; return $this->database->fetchAll($sql, [ 'user_id' => $userId, 'limit' => $limit ]); } public function getRecentActivity(int $limit = 20): array { $sql = "SELECT al.*, u.name as user_name FROM audit_log al LEFT JOIN users u ON al.user_id = u.id ORDER BY al.created_at DESC LIMIT :limit"; return $this->database->fetchAll($sql, ['limit' => $limit]); } public function getActivityByDateRange(string $startDate, string $endDate): array { $sql = "SELECT al.*, u.name as user_name FROM audit_log al LEFT JOIN users u ON al.user_id = u.id WHERE DATE(al.created_at) BETWEEN :start_date AND :end_date ORDER BY al.created_at DESC"; return $this->database->fetchAll($sql, [ 'start_date' => $startDate, 'end_date' => $endDate ]); } public function getActivityByAction(string $action, int $limit = 100): array { $sql = "SELECT al.*, u.name as user_name FROM audit_log al LEFT JOIN users u ON al.user_id = u.id WHERE al.action = :action ORDER BY al.created_at DESC LIMIT :limit"; return $this->database->fetchAll($sql, [ 'action' => $action, 'limit' => $limit ]); } public function getAssetChanges(int $assetId): array { $sql = "SELECT al.*, u.name as user_name FROM audit_log al LEFT JOIN users u ON al.user_id = u.id WHERE al.table_name = 'assets' AND al.record_id = :asset_id AND al.action IN ('update', 'delete') ORDER BY al.created_at DESC"; return $this->database->fetchAll($sql, ['asset_id' => $assetId]); } public function getInventoryActivity(int $inventoryId): array { $sql = "SELECT al.*, u.name as user_name FROM audit_log al LEFT JOIN users u ON al.user_id = u.id WHERE al.table_name = 'inventories' AND al.record_id = :inventory_id ORDER BY al.created_at DESC"; return $this->database->fetchAll($sql, ['inventory_id' => $inventoryId]); } public function cleanupOldLogs(int $daysToKeep = 365): int { $sql = "DELETE FROM audit_log WHERE created_at < DATE_SUB(NOW(), INTERVAL :days DAY)"; return $this->database->query($sql, ['days' => $daysToKeep])->rowCount(); } public function getAuditSummary(): array { $sql = "SELECT COUNT(*) as total_entries, COUNT(DISTINCT user_id) as unique_users, COUNT(DISTINCT table_name) as tables_affected, MIN(created_at) as first_entry, MAX(created_at) as last_entry FROM audit_log"; return $this->database->fetch($sql) ?: []; } public function getTopUsers(int $limit = 10): array { $sql = "SELECT u.name as user_name, COUNT(*) as activity_count FROM audit_log al LEFT JOIN users u ON al.user_id = u.id GROUP BY al.user_id, u.name ORDER BY activity_count DESC LIMIT :limit"; return $this->database->fetchAll($sql, ['limit' => $limit]); } public function getMostActiveTables(int $limit = 10): array { $sql = "SELECT table_name, COUNT(*) as activity_count FROM audit_log GROUP BY table_name ORDER BY activity_count DESC LIMIT :limit"; return $this->database->fetchAll($sql, ['limit' => $limit]); } }