<?php
// public_html/assets/includes/logAuditTrail.php
declare(strict_types=1);

// Lusaka timezone
date_default_timezone_set('Africa/Lusaka');

if (!defined('APP_ROOT')) {
    define('APP_ROOT', realpath(__DIR__ . '/..' . '/..')); // /public_html
}
require_once APP_ROOT . '/assets/config/dbConnection.php';

// Action constants
if (!defined('ACTION_LOGIN')) define('ACTION_LOGIN', 'login');
if (!defined('ACTION_LOGOUT')) define('ACTION_LOGOUT', 'logout');
if (!defined('ACTION_UPDATE')) define('ACTION_UPDATE', 'update');
if (!defined('ACTION_DELETE')) define('ACTION_DELETE', 'delete');
if (!defined('ACTION_FAILED_LOGIN')) define('ACTION_FAILED_LOGIN', 'login_failed');

function audit_table_exists(mysqli $conn, string $table): bool {
    // ✅ Works everywhere (no SHOW TABLES with ?)
    $sql = "SELECT 1
            FROM information_schema.tables
            WHERE table_schema = DATABASE()
              AND table_name = ?
            LIMIT 1";
    $stmt = $conn->prepare($sql);
    if (!$stmt) return false;
    $stmt->bind_param('s', $table);
    $stmt->execute();
    $res = $stmt->get_result();
    $ok = $res && $res->num_rows > 0;
    $stmt->close();
    return $ok;
}

function audit_create_table_if_missing(mysqli $conn): void {
    $table = "audit_logs";
    if (audit_table_exists($conn, $table)) return;

    $sql = "
        CREATE TABLE audit_logs (
            id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
            user_id BIGINT UNSIGNED NOT NULL DEFAULT 0,
            username VARCHAR(120) NOT NULL,
            action_type VARCHAR(40) NOT NULL,
            table_name VARCHAR(120) NULL,
            record_id BIGINT NULL,
            old_data LONGTEXT NULL,
            new_data LONGTEXT NULL,
            ip_address VARCHAR(64) NULL,
            user_agent VARCHAR(255) NULL,
            timestamp DATETIME NOT NULL,
            INDEX idx_user (user_id),
            INDEX idx_action (action_type),
            INDEX idx_table (table_name),
            INDEX idx_time (timestamp)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    ";
    $conn->query($sql);
}

function audit_client_ip(): string {
    $keys = ['HTTP_CF_CONNECTING_IP','HTTP_X_FORWARDED_FOR','HTTP_CLIENT_IP','REMOTE_ADDR'];
    foreach ($keys as $k) {
        if (empty($_SERVER[$k])) continue;
        $val = (string)$_SERVER[$k];
        $parts = array_map('trim', explode(',', $val));
        $ip = $parts[0] ?? '';
        if ($ip !== '') return $ip;
    }
    return '';
}

// Keeps your same function signature (so existing calls won’t break)
function logAuditTrail($user_id, $username, $action_type, $table_name = null, $record_id = null, $old_data = null, $new_data = null): void {

    $allowed = [ACTION_LOGIN, ACTION_LOGOUT, ACTION_UPDATE, ACTION_DELETE, ACTION_FAILED_LOGIN];
    if (empty($username) || !in_array($action_type, $allowed, true)) {
        error_log("Invalid username or action type.");
        return;
    }

    $db = DatabaseConnection::getInstance();
    $conn = $db->getConnection();
    if (!$conn) {
        error_log("Audit trail: DB connection failed.");
        return;
    }
    $conn->set_charset('utf8mb4');

    // ✅ Ensure table exists without SHOW TABLES prepared
    audit_create_table_if_missing($conn);

    $user_ip = audit_client_ip();
    $user_agent = substr((string)($_SERVER['HTTP_USER_AGENT'] ?? ''), 0, 255);
    $timestamp = date('Y-m-d H:i:s');

    if ($user_id === null || $user_id === '') $user_id = 0;
    $user_id = (int)$user_id;

    $old_data = is_array($old_data) ? json_encode($old_data, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) : $old_data;
    $new_data = is_array($new_data) ? json_encode($new_data, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) : $new_data;

    $sql = "INSERT INTO audit_logs
        (user_id, username, action_type, table_name, record_id, old_data, new_data, ip_address, user_agent, timestamp)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

    $stmt = $conn->prepare($sql);
    if (!$stmt) {
        error_log("Audit trail prepare failed: " . $conn->error);
        return;
    }

    $record_id = ($record_id === null || $record_id === '') ? null : (int)$record_id;

    $stmt->bind_param(
        "isssisssss",
        $user_id,
        $username,
        $action_type,
        $table_name,
        $record_id,
        $old_data,
        $new_data,
        $user_ip,
        $user_agent,
        $timestamp
    );

    if (!$stmt->execute()) {
        error_log("Audit trail logging failed: " . $stmt->error);
    }
    $stmt->close();
}

function logUserLogout($user_id, $username): void {
    logAuditTrail($user_id, $username, ACTION_LOGOUT);
}
