<?php
require_once __DIR__ . '/../config/config.php';
require_once __DIR__ . '/../includes/db_connect.php';
require_once __DIR__ . '/../includes/functions.php';

$logFile = APP_DIR . '/logs/paydisini_callback.log';
ini_set('log_errors', 1);
ini_set('error_log', $logFile);
error_reporting(E_ALL);

function log_callback_data($message) {
    $timestamp = date("Y-m-d H:i:s");
    error_log("[$timestamp] $message\n", 3, $GLOBALS['logFile']);
}

log_callback_data("Callback received. Raw POST data: " . file_get_contents('php://input'));
log_callback_data("POST array: " . print_r($_POST, true));

header('Content-Type: application/json');
$response = ['success' => false, 'message' => 'Invalid request.'];

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    log_callback_data("Invalid request method: " . $_SERVER['REQUEST_METHOD']);
    http_response_code(405);
    echo json_encode($response);
    exit;
}

if (!isset($pdo) || !$pdo instanceof PDO) {
    log_callback_data("Database connection failed.");
    http_response_code(500);
    $response['message'] = 'Internal server error (DB).';
    echo json_encode($response);
    exit;
}

$apiKey = PAYDISINI_API_KEY ?? null;
$uniqueCode = $_POST['unique_code'] ?? null;
$status = $_POST['status'] ?? null;
$receivedSignature = $_POST['signature'] ?? null;

log_callback_data("Received params: APIKey (config): $apiKey, UniqueCode: $uniqueCode, Status: $status, Signature: $receivedSignature");

if (empty($apiKey) || empty($uniqueCode) || empty($status) || empty($receivedSignature)) {
    log_callback_data("Missing required parameters.");
    http_response_code(400);
    $response['message'] = 'Missing parameters.';
    echo json_encode($response);
    exit;
}

$expectedSignature = md5($apiKey . $uniqueCode . 'CallbackStatus');

log_callback_data("Calculated signature: $expectedSignature");

if ($receivedSignature !== $expectedSignature) {
    log_callback_data("Signature mismatch. Expected: $expectedSignature, Received: $receivedSignature");
    http_response_code(401);
    $response['message'] = 'Invalid signature.';
    echo json_encode($response);
    exit;
}

$newStatus = strtolower($status);
$validStatuses = ['pending', 'success', 'failed', 'expired', 'canceled'];
if (!in_array($newStatus, $validStatuses)) {
    log_callback_data("Invalid status value received: $newStatus");
    http_response_code(400);
    $response['message'] = 'Invalid status value.';
    echo json_encode($response);
    exit;
}

try {
    $pdo->beginTransaction();

    $stmtGetDeposit = $pdo->prepare("
        SELECT d.id, d.user_id, d.deposit_id as deposit_unique_id, d.amount, d.bonus, d.received_amount, d.status as current_status, d.deposit_method_id, dm.name as method_name
        FROM deposits d
        JOIN deposit_methods dm ON d.deposit_method_id = dm.id
        WHERE d.paydisini_unique_code = :unique_code FOR UPDATE
    ");
    $stmtGetDeposit->bindParam(':unique_code', $uniqueCode);
    $stmtGetDeposit->execute();
    $deposit = $stmtGetDeposit->fetch(PDO::FETCH_ASSOC);

    if (!$deposit) {
        $pdo->rollBack();
        log_callback_data("Deposit not found for unique_code: $uniqueCode");
        http_response_code(404);
        $response['message'] = 'Transaction not found.';
        echo json_encode($response);
        exit;
    }

    log_callback_data("Deposit found: ID " . $deposit['id'] . ", Current Status: " . $deposit['current_status'] . ", New Status: $newStatus");

    if ($deposit['current_status'] === $newStatus) {
        $pdo->commit();
        log_callback_data("Status already updated for deposit ID " . $deposit['id'] . " to " . $newStatus);
        $response = ['success' => true, 'message' => 'Status already updated.'];
        http_response_code(200);
        echo json_encode($response);
        exit;
    }

    if ($deposit['current_status'] === 'success' && $newStatus !== 'success') {
        $pdo->commit();
        log_callback_data("Attempt to change status from 'success' to '$newStatus' for deposit ID " . $deposit['id'] . ". No change made.");
        $response = ['success' => true, 'message' => 'Transaction already completed. Status not changed.'];
        http_response_code(200);
        echo json_encode($response);
        exit;
    }


    $stmtUpdateDeposit = $pdo->prepare("UPDATE deposits SET status = :new_status, updated_at = NOW() WHERE id = :deposit_id");
    $stmtUpdateDeposit->bindParam(':new_status', $newStatus);
    $stmtUpdateDeposit->bindParam(':deposit_id', $deposit['id'], PDO::PARAM_INT);
    $stmtUpdateDeposit->execute();

    if ($newStatus === 'success' && $deposit['current_status'] !== 'success') {
        $balanceToAdd = (float)$deposit['received_amount'];

        $stmtUser = $pdo->prepare("SELECT balance FROM users WHERE id = :user_id FOR UPDATE");
        $stmtUser->bindParam(':user_id', $deposit['user_id'], PDO::PARAM_INT);
        $stmtUser->execute();
        $userBalanceBefore = (float)$stmtUser->fetchColumn();

        $newUserBalance = $userBalanceBefore + $balanceToAdd;

        $stmtUpdateUserBalance = $pdo->prepare("UPDATE users SET balance = :new_balance WHERE id = :user_id_bal");
        $stmtUpdateUserBalance->bindParam(':new_balance', $newUserBalance);
        $stmtUpdateUserBalance->bindParam(':user_id_bal', $deposit['user_id'], PDO::PARAM_INT);
        $stmtUpdateUserBalance->execute();

        $logDescription = "Deposit berhasil melalui {$deposit['method_name']} (ID Deposit: {$deposit['deposit_unique_id']})";

        log_balance_mutation(
            $pdo,
            $deposit['user_id'],
            'credit',
            'deposit',
            $balanceToAdd,
            $userBalanceBefore,
            $newUserBalance,
            $logDescription,
            $deposit['deposit_unique_id'],
            'callback'
        );

        log_callback_data("User ID " . $deposit['user_id'] . " balance updated by " . $balanceToAdd . " for deposit ID " . $deposit['id']);
    }

    $pdo->commit();
    log_callback_data("Successfully updated deposit ID " . $deposit['id'] . " to status " . $newStatus);
    $response = ['success' => true, 'message' => 'Callback processed successfully.'];
    http_response_code(200);
    echo json_encode($response);

} catch (PDOException $e) {
    if ($pdo->inTransaction()) {
        $pdo->rollBack();
    }
    log_callback_data("Database error: " . $e->getMessage());
    http_response_code(500);
    $response['message'] = 'Database error during callback processing.';
    echo json_encode($response);
} catch (Exception $e) {
    if ($pdo->inTransaction()) {
        $pdo->rollBack();
    }
    log_callback_data("General error: " . $e->getMessage());
    http_response_code(500);
    $response['message'] = 'General error during callback processing.';
    echo json_encode($response);
}
exit;
?>
