<?php
include_once '../config/connect.php';
require_once '../config/topup.php';
include_once __DIR__ . '/../../../../vendor/autoload.php';
session_start();

function redirect_agent_balance(int $msg): void
{
    header('Location: ../index?page=ManagementAgent&msg=' . $msg);
    exit();
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['edit_agent_balance'])) {
    redirect_agent_balance(24);
}

$currentAgentName = agent_public_name((array)($_SESSION['admin'] ?? []));
$currentAgentRefs = agent_identity_values((array)($_SESSION['admin'] ?? []));
$currentAgentLevel = trim((string)($_SESSION['admin']['agent_level'] ?? ($_SESSION['agent_level'] ?? '')));

if ($currentAgentName === '' || !in_array($currentAgentLevel, ['admin', 'head_agent'], true)) {
    redirect_agent_balance(24);
}

$config = HTMLPurifier_Config::createDefault();
$purifier = new HTMLPurifier($config);

$agentIdentifier = trim((string)$purifier->purify($_POST['agent_identifier'] ?? ''));
$balanceRaw = trim((string)$purifier->purify($_POST['agent_balance'] ?? '0'));
$balanceAction = trim((string)$purifier->purify($_POST['balance_action'] ?? ''));

if ($agentIdentifier === '') {
    redirect_agent_balance(8);
}

$targetAgent = agent_find_by_identifier($call, $agentIdentifier);
$operatorAgent = agent_find_by_identifier($call, $currentAgentName);

if ($targetAgent === null || $operatorAgent === null) {
    redirect_agent_balance(8);
}

$targetAgentName = agent_public_name($targetAgent);
$targetAgentNameSql = mysqli_real_escape_string($call, $targetAgentName);
$operatorAgentName = agent_public_name($operatorAgent);
$operatorAgentNameSql = mysqli_real_escape_string($call, $operatorAgentName);
$targetRefs = agent_identity_values($targetAgent);

if (array_intersect($targetRefs, $currentAgentRefs) !== []) {
    redirect_agent_balance(24);
}

if (!preg_match('/^\d+$/', $balanceRaw)) {
    redirect_agent_balance(16);
}

$balance = (int)$balanceRaw;

if ($balance <= 0) {
    redirect_agent_balance(17);
}

if (!in_array($balanceAction, ['11', '12'], true)) {
    redirect_agent_balance(16);
}

if (
    $currentAgentLevel === 'head_agent'
    && (
        !in_array((string)($targetAgent['agent_upline'] ?? ''), $currentAgentRefs, true)
        || (string)($targetAgent['agent_level'] ?? '') !== 'agent'
    )
) {
    redirect_agent_balance(24);
}

$trxid = md5(uniqid((string)mt_rand(), true));
$created = date('Y-m-d H:i:s');

mysqli_begin_transaction($call);

try {
    $operatorQuery = mysqli_query(
        $call,
        "SELECT agent_balance FROM tb_agent WHERE agent_name = '$operatorAgentNameSql' LIMIT 1 FOR UPDATE"
    );
    $lockedTargetQuery = mysqli_query(
        $call,
        "SELECT agent_balance FROM tb_agent WHERE agent_name = '$targetAgentNameSql' LIMIT 1 FOR UPDATE"
    );

    if (
        !$operatorQuery
        || !$lockedTargetQuery
        || mysqli_num_rows($operatorQuery) === 0
        || mysqli_num_rows($lockedTargetQuery) === 0
    ) {
        throw new RuntimeException('Agent balance lock failed.');
    }

    $operatorData = mysqli_fetch_assoc($operatorQuery) ?: ['agent_balance' => 0];
    $targetBalanceData = mysqli_fetch_assoc($lockedTargetQuery) ?: ['agent_balance' => 0];

    $operatorBalanceBefore = (int)($operatorData['agent_balance'] ?? 0);
    $targetBalanceBefore = (int)($targetBalanceData['agent_balance'] ?? 0);

    if ($balanceAction === '12') {
        if ($operatorBalanceBefore < $balance) {
            mysqli_rollback($call);
            redirect_agent_balance(18);
        }

        $operatorBalanceAfter = $operatorBalanceBefore - $balance;

        if (!mysqli_query($call, "UPDATE tb_agent SET agent_balance = agent_balance + '$balance' WHERE agent_name = '$targetAgentNameSql'")) {
            throw new RuntimeException('Failed to add target balance.');
        }

        if (!mysqli_query($call, "UPDATE tb_agent SET agent_balance = agent_balance - '$balance' WHERE agent_name = '$operatorAgentNameSql'")) {
            throw new RuntimeException('Failed to deduct operator balance.');
        }

        if (!mysqli_query(
            $call,
            "INSERT INTO tb_transfer VALUES (
                NULL,
                '$trxid',
                '" . mysqli_real_escape_string($call, $targetAgentName) . "',
                '" . mysqli_real_escape_string($call, $operatorAgentName) . "',
                'deposit',
                '$balance',
                '$operatorBalanceBefore',
                '$operatorBalanceAfter',
                'Transfer Out',
                '$created'
            )"
        )) {
            throw new RuntimeException('Failed to log transfer.');
        }

        if ($currentAgentLevel === 'admin') {
            $rateCoin = topup_get_agent_rate($call, $targetAgentName);
            $totalHarga = $rateCoin > 0 ? (int)floor($balance / $rateCoin) : 0;

            if (!mysqli_query(
                $call,
                "INSERT INTO tb_topup (
                    agent_code,
                    amount,
                    harga,
                    metode,
                    nama_rekening,
                    nomor_rekening,
                    tanggal,
                    status
                ) VALUES (
                    '" . mysqli_real_escape_string($call, $targetAgentName) . "',
                    '$balance',
                    '$totalHarga',
                    'INJECTED',
                    'INJECTED',
                    '0',
                    NOW(),
                    'Success'
                )"
            )) {
                throw new RuntimeException('Failed to log topup.');
            }
        }

        mysqli_commit($call);
        $_SESSION['admin']['agent_balance'] = $operatorBalanceAfter;
        $_SESSION['agent_level'] = $currentAgentLevel;
        redirect_agent_balance(19);
    }

    if ($targetBalanceBefore < $balance) {
        mysqli_rollback($call);
        redirect_agent_balance(18);
    }

    $operatorBalanceAfter = $operatorBalanceBefore + $balance;

    if (!mysqli_query($call, "UPDATE tb_agent SET agent_balance = agent_balance - '$balance' WHERE agent_name = '$targetAgentNameSql'")) {
        throw new RuntimeException('Failed to reduce target balance.');
    }

    if (!mysqli_query($call, "UPDATE tb_agent SET agent_balance = agent_balance + '$balance' WHERE agent_name = '$operatorAgentNameSql'")) {
        throw new RuntimeException('Failed to increase operator balance.');
    }

    if (!mysqli_query(
        $call,
        "INSERT INTO tb_transfer VALUES (
            NULL,
            '$trxid',
            '" . mysqli_real_escape_string($call, $targetAgentName) . "',
            '" . mysqli_real_escape_string($call, $operatorAgentName) . "',
            'withdraw',
            '$balance',
            '$operatorBalanceBefore',
            '$operatorBalanceAfter',
            'Transfer In',
            '$created'
        )"
    )) {
        throw new RuntimeException('Failed to log transfer.');
    }

    mysqli_commit($call);
    $_SESSION['admin']['agent_balance'] = $operatorBalanceAfter;
    $_SESSION['agent_level'] = $currentAgentLevel;
    redirect_agent_balance(21);
} catch (Throwable $exception) {
    mysqli_rollback($call);
    redirect_agent_balance($balanceAction === '12' ? 20 : 22);
}
