<?php
require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../app/helpers/rbac.php';
require_once __DIR__ . '/../app/helpers/audit.php';
require_once __DIR__ . '/../app/helpers/api_security.php';

session_start();

if (!can('audit.view')) {
    respond(['status' => 'error', 'message' => 'Unauthorized']);
}

$action = $_GET['action'] ?? 'list';

try {
    switch ($action) {
        case 'list': handleList($pdo); break;
        case 'verify': handleVerify($pdo); break;
        case 'backfill': handleBackfill($pdo); break;
        case 'retention_policies': handleRetentionPolicies($pdo); break;
        case 'save_retention_policy': handleSaveRetentionPolicy($pdo); break;
        case 'delete_retention_policy': handleDeleteRetentionPolicy($pdo); break;
        case 'retention_run': handleRetentionRun($pdo); break;
        case 'retention_log': handleRetentionLog($pdo); break;
        case 'stats': handleStats($pdo); break;
        default: respond(['status' => 'error', 'message' => 'Unknown action']);
    }
} catch (Exception $e) {
    respond(['status' => 'error', 'message' => $e->getMessage()]);
}

function respond(array $payload): void { apiRespond($payload); }
function canVerify(): bool { return isAdmin() || can('audit.verify'); }
function canManageRetention(): bool { return isAdmin() || can('audit.retention.manage'); }
function canRunRetention(): bool { return isAdmin() || can('audit.retention.run'); }

function handleList(PDO $pdo): void
{
    $page = max(1, (int)($_GET['page'] ?? 1));
    $limit = min(200, max(10, (int)($_GET['limit'] ?? 100)));
    $offset = ($page - 1) * $limit;
    $module = trim((string)($_GET['module'] ?? ''));
    $action = trim((string)($_GET['action_filter'] ?? ''));
    $search = trim((string)($_GET['search'] ?? ''));
    $userId = (int)($_GET['user_id'] ?? 0);

    $where = ['a.deleted_at IS NULL'];
    $params = [];

    if ($module !== '') { $where[] = 'a.module = :module'; $params['module'] = $module; }
    if ($action !== '') { $where[] = 'a.action = :action'; $params['action'] = $action; }
    if ($userId > 0) { $where[] = 'a.user_id = :user_id'; $params['user_id'] = $userId; }
    if ($search !== '') { $where[] = '(a.description LIKE :search OR a.module LIKE :search OR a.action LIKE :search)'; $params['search'] = "%{$search}%"; }

    $whereSql = 'WHERE ' . implode(' AND ', $where);

    $countStmt = $pdo->prepare("SELECT COUNT(*) FROM audit_logs a {$whereSql}");
    $countStmt->execute($params);
    $total = (int)$countStmt->fetchColumn();

    $stmt = $pdo->prepare("
        SELECT a.*, u.name AS user_name
        FROM audit_logs a
        LEFT JOIN users u ON u.id = a.user_id
        {$whereSql}
        ORDER BY a.id DESC
        LIMIT {$limit} OFFSET {$offset}
    ");
    $stmt->execute($params);
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

    $modules = $pdo->query("SELECT DISTINCT module FROM audit_logs WHERE deleted_at IS NULL ORDER BY module")->fetchAll(PDO::FETCH_COLUMN);
    $actions = $pdo->query("SELECT DISTINCT action FROM audit_logs WHERE deleted_at IS NULL ORDER BY action")->fetchAll(PDO::FETCH_COLUMN);
    $users = $pdo->query("SELECT DISTINCT a.user_id, u.name FROM audit_logs a JOIN users u ON u.id = a.user_id WHERE a.deleted_at IS NULL ORDER BY u.name")->fetchAll(PDO::FETCH_ASSOC);

    respond([
        'status' => 'success',
        'data' => $rows,
        'total' => $total,
        'page' => $page,
        'pages' => (int)ceil($total / $limit),
        'filters' => ['modules' => $modules, 'actions' => $actions, 'users' => $users]
    ]);
}

function handleVerify(PDO $pdo): void
{
    if (!canVerify()) respond(['status' => 'error', 'message' => 'Unauthorized']);

    enforceCsrfForUnsafeRequest();
    $sinceId = (int)($_GET['since_id'] ?? 0);
    $result = verifyAuditIntegrity($pdo, $sinceId ?: null);
    respond(['status' => 'success', 'data' => $result]);
}

function handleBackfill(PDO $pdo): void
{
    if (!canVerify()) respond(['status' => 'error', 'message' => 'Unauthorized']);
    enforceCsrfForUnsafeRequest();
    $result = backfillAuditHashes($pdo);
    respond(['status' => 'success', 'data' => $result]);
}

function handleRetentionPolicies(PDO $pdo): void
{
    $rows = $pdo->query("SELECT * FROM audit_retention_policies ORDER BY module, action")->fetchAll(PDO::FETCH_ASSOC);
    respond(['status' => 'success', 'data' => $rows]);
}

function handleSaveRetentionPolicy(PDO $pdo): void
{
    if (!canManageRetention()) respond(['status' => 'error', 'message' => 'Unauthorized']);
    enforceCsrfForUnsafeRequest();

    $id = (int)($_POST['id'] ?? 0);
    $module = trim((string)($_POST['module'] ?? ''));
    $action = trim((string)($_POST['action'] ?? ''));
    $retentionDays = (int)($_POST['retention_days'] ?? 365);
    $archiveAction = trim((string)($_POST['archive_action'] ?? 'delete'));

    if ($module === '') respond(['status' => 'error', 'message' => 'Module is required']);
    if ($retentionDays < 1) respond(['status' => 'error', 'message' => 'Retention days must be at least 1']);
    if (!in_array($archiveAction, ['delete', 'anonymize', 'archive'])) respond(['status' => 'error', 'message' => 'Invalid archive action']);

    $actionVal = $action ?: null;

    if ($id > 0) {
        $stmt = $pdo->prepare("UPDATE audit_retention_policies SET module = :module, action = :action, retention_days = :retention_days, archive_action = :archive_action WHERE id = :id");
        $stmt->execute(['module' => $module, 'action' => $actionVal, 'retention_days' => $retentionDays, 'archive_action' => $archiveAction, 'id' => $id]);
    } else {
        $stmt = $pdo->prepare("INSERT INTO audit_retention_policies (module, action, retention_days, archive_action) VALUES (:module, :action, :retention_days, :archive_action)");
        $stmt->execute(['module' => $module, 'action' => $actionVal, 'retention_days' => $retentionDays, 'archive_action' => $archiveAction]);
        $id = (int)$pdo->lastInsertId();
    }

    audit($pdo, (int)($_SESSION['user_id'] ?? 0), 'save', 'audit_retention_policy', $id, "Saved retention policy: module={$module}, days={$retentionDays}");
    respond(['status' => 'success', 'data' => ['id' => $id]]);
}

function handleDeleteRetentionPolicy(PDO $pdo): void
{
    if (!canManageRetention()) respond(['status' => 'error', 'message' => 'Unauthorized']);
    enforceCsrfForUnsafeRequest();
    $id = (int)($_POST['id'] ?? 0);
    if ($id <= 0) respond(['status' => 'error', 'message' => 'Invalid ID']);
    $pdo->prepare("DELETE FROM audit_retention_policies WHERE id = ?")->execute([$id]);
    respond(['status' => 'success']);
}

function handleRetentionRun(PDO $pdo): void
{
    if (!canRunRetention()) respond(['status' => 'error', 'message' => 'Unauthorized']);
    enforceCsrfForUnsafeRequest();
    $result = runRetentionCleanup($pdo);
    respond(['status' => 'success', 'data' => $result]);
}

function handleRetentionLog(PDO $pdo): void
{
    $rows = $pdo->query("SELECT * FROM audit_retention_log ORDER BY ran_at DESC LIMIT 50")->fetchAll(PDO::FETCH_ASSOC);
    respond(['status' => 'success', 'data' => $rows]);
}

function handleStats(PDO $pdo): void
{
    $total = (int)$pdo->query("SELECT COUNT(*) FROM audit_logs WHERE deleted_at IS NULL")->fetchColumn();
    $totalWithHashes = (int)$pdo->query("SELECT COUNT(*) FROM audit_logs WHERE hash IS NOT NULL AND deleted_at IS NULL")->fetchColumn();
    $totalDeleted = (int)$pdo->query("SELECT COUNT(*) FROM audit_logs WHERE deleted_at IS NOT NULL")->fetchColumn();
    $modules = $pdo->query("SELECT module, COUNT(*) AS cnt FROM audit_logs WHERE deleted_at IS NULL GROUP BY module ORDER BY cnt DESC")->fetchAll(PDO::FETCH_ASSOC);
    $lastRun = $pdo->query("SELECT * FROM audit_retention_log ORDER BY ran_at DESC LIMIT 1")->fetch(PDO::FETCH_ASSOC);

    respond([
        'status' => 'success',
        'data' => [
            'total' => $total,
            'hashed' => $totalWithHashes,
            'deleted' => $totalDeleted,
            'unhashed' => $total - $totalWithHashes,
            'modules' => $modules,
            'last_retention_run' => $lastRun
        ]
    ]);
}
