<?php
header('Content-Type: application/json');
$response = ['success' => false, 'logs' => [], 'pagination' => null, 'message' => 'Gagal memuat data log saldo.'];

require_once __DIR__ . '/../../../config/config.php';
require_once __DIR__ . '/../../../includes/session.php';
require_once __DIR__ . '/../../../lib/Auth.php';
require_once __DIR__ . '/../../../includes/functions.php';

if (!Auth::isLoggedIn() || $_SESSION['user_role'] !== 'admin') {
    http_response_code(403);
    $response['message'] = 'Akses ditolak.';
    echo json_encode($response);
    exit;
}

if (!isset($pdo) || !$pdo instanceof PDO) {
    http_response_code(500);
    error_log("PDO object not available in get_admin_balance_logs.php");
    $response['message'] = 'Koneksi database gagal.';
    echo json_encode($response);
    exit;
}

try {
    $limit = filter_input(INPUT_GET, 'limit', FILTER_VALIDATE_INT, ['options' => ['default' => 15, 'min_range' => 5, 'max_range' => 100]]);
    $page = filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT, ['options' => ['default' => 1, 'min_range' => 1]]);
    $type = $_GET['type'] ?? 'all';
    $category = $_GET['category'] ?? 'all';
    $source = $_GET['source'] ?? 'all';
    $userIdFilter = filter_input(INPUT_GET, 'user_id', FILTER_VALIDATE_INT);
    $sortBy = $_GET['sort_by'] ?? 'bl.created_at';
    $sortType = $_GET['sort_type'] ?? 'DESC';
    $searchColumn = $_GET['search_column'] ?? 'bl.id';
    $searchKeyword = filter_input(INPUT_GET, 'search_keyword', FILTER_SANITIZE_SPECIAL_CHARS) ?? '';

    $offset = ($page - 1) * $limit;

    $allowedSortColumns = ['bl.created_at', 'bl.id', 'u.username', 'bl.type', 'bl.category', 'bl.amount'];
    $allowedSortTypes = ['ASC', 'DESC'];
    if (!in_array($sortBy, $allowedSortColumns)) { $sortBy = 'bl.created_at'; }
    if (!in_array(strtoupper($sortType), $allowedSortTypes)) { $sortType = 'DESC'; }

    $allowedSearchColumns = ['bl.id', 'u.username', 'bl.description', 'bl.reference_id'];
     if (!in_array($searchColumn, $allowedSearchColumns)) { $searchColumn = 'bl.id'; }


    $sqlSelect = "SELECT bl.id, bl.user_id, u.username, bl.type, bl.category, bl.amount, bl.balance_before, bl.balance_after, bl.description, bl.reference_id, bl.source, bl.created_at ";
    $sqlFrom = "FROM balance_logs bl JOIN users u ON bl.user_id = u.id ";
    $sqlWhereBase = "WHERE 1=1 ";
    $params = [];
    $whereClauses = [];

    if ($type !== 'all' && in_array($type, ['credit', 'debit'])) {
        $whereClauses[] = "bl.type = :type";
        $params[':type'] = $type;
    }
    if ($category !== 'all' && in_array($category, ['deposit', 'order_placement', 'order_refund', 'admin_adjustment', 'other'])) {
        $whereClauses[] = "bl.category = :category";
        $params[':category'] = $category;
    }
    if ($source !== 'all' && in_array($source, ['web', 'api', 'cron', 'admin', 'callback'])) {
        $whereClauses[] = "bl.source = :source";
        $params[':source'] = $source;
    }
    if ($userIdFilter) {
        $whereClauses[] = "bl.user_id = :user_id_filter";
        $params[':user_id_filter'] = $userIdFilter;
    }

    if (!empty($searchKeyword)) {
        if ($searchColumn === 'bl.id' || $searchColumn === 'bl.reference_id') {
            if (is_numeric($searchKeyword) || strpos($searchKeyword, 'INV') === 0 || strpos($searchKeyword, 'TKT') === 0 ) {
                 $whereClauses[] = $searchColumn . " = :search_keyword_exact";
                 $params[':search_keyword_exact'] = $searchKeyword;
            } else {
                 $whereClauses[] = "1=0"; // No result if not numeric for ID
            }
        } else {
            $whereClauses[] = $searchColumn . " LIKE :search_keyword_like";
            $params[':search_keyword_like'] = '%' . $searchKeyword . '%';
        }
    }


    $sqlWhere = $sqlWhereBase . (!empty($whereClauses) ? " AND " . implode(" AND ", $whereClauses) : "");

    $totalItems = 0;
    $totalPages = 1;
    $sqlCount = "SELECT COUNT(bl.id) " . $sqlFrom . $sqlWhere;
    $stmtCount = $pdo->prepare($sqlCount);
    $stmtCount->execute($params);
    $totalItems = (int)$stmtCount->fetchColumn();
    $totalPages = $totalItems > 0 ? ceil($totalItems / $limit) : 1;

    if ($page > $totalPages && $totalPages > 0) {
        $page = $totalPages;
        $offset = ($page - 1) * $limit;
    } elseif ($page < 1) {
        $page = 1;
        $offset = 0;
    }

    $logs = [];
    $sqlData = $sqlSelect . $sqlFrom . $sqlWhere . " ORDER BY {$sortBy} {$sortType} LIMIT :limit OFFSET :offset";
    $stmtData = $pdo->prepare($sqlData);

    foreach ($params as $key => &$value) { // Bind by reference for type hinting
        if ($key === ':user_id_filter') {
            $stmtData->bindValue($key, $value, PDO::PARAM_INT);
        } else {
            $stmtData->bindValue($key, $value);
        }
    }
    unset($value); // Unset reference

    $stmtData->bindParam(':limit', $limit, PDO::PARAM_INT);
    $stmtData->bindParam(':offset', $offset, PDO::PARAM_INT);
    $stmtData->execute();
    $logs = $stmtData->fetchAll(PDO::FETCH_ASSOC);

    $response['success'] = true;
    $response['logs'] = $logs;
    $response['pagination'] = [
        'totalItems' => $totalItems,
        'totalPages' => $totalPages,
        'currentPage' => $page,
        'limit' => $limit,
        'offset' => $offset
    ];
    unset($response['message']);

} catch (\PDOException $e) {
    error_log("Admin Get Balance Logs DB Error: " . $e->getMessage());
    $response['message'] = "Terjadi kesalahan database.";
    http_response_code(500);
} catch (\Throwable $e) {
    error_log("Admin Get Balance Logs General Error: " . $e->getMessage());
    $response['message'] = "Terjadi kesalahan internal server.";
    if (defined('DEBUG_MODE') && DEBUG_MODE === true) { $response['debug_php'] = $e->getMessage(); }
    http_response_code(500);
}

echo json_encode($response);
exit;
?>
