<?php
ini_set('display_errors', 1);
error_reporting(E_ALL & ~E_NOTICE);

require 'koneksi.php';
header('Content-Type: application/json');

/* ===============================
   METHOD CHECK
=============================== */
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode([
        'status' => 'fail',
        'msg'    => 'METHOD NOT ALLOWED'
    ], JSON_PRETTY_PRINT);
    exit;
}

/* ===============================
   RESPONSE DEFAULT
=============================== */
$res = ['status' => 'fail', 'msg' => 'DEFAULT ERROR'];

/* ===============================
   REQUIRED PARAMS
=============================== */
$required = ['signature','user_member','amount','type'];

foreach ($required as $p) {
    if (!isset($_POST[$p]) || trim($_POST[$p]) === '') {
        echo json_encode([
            'status' => 'fail',
            'msg'    => "MISSING PARAM: $p"
        ], JSON_PRETTY_PRINT);
        exit;
    }
}

if (empty($_POST['user_agent']) && empty($_POST['agent_name'])) {
    echo json_encode([
        'status' => 'fail',
        'msg'    => 'MISSING PARAM: user_agent'
    ], JSON_PRETTY_PRINT);
    exit;
}

/* ===============================
   INPUT
=============================== */
$agent_name = mysqli_real_escape_string($call, trim($_POST['user_agent'] ?? ($_POST['agent_name'] ?? '')));
$secret_key = mysqli_real_escape_string($call, trim($_POST['signature']));
$username   = mysqli_real_escape_string($call, trim($_POST['user_member']));
$amount     = trim($_POST['amount']);
$type       = strtolower(trim($_POST['type']));
$client_ip = getClientIP();

$username = htmlspecialchars($username, ENT_QUOTES, 'UTF-8');

/* ===============================
   VALIDASI AMOUNT
=============================== */
if (!is_numeric($amount)) {
    echo json_encode(['status'=>'fail','msg'=>'INVALID AMOUNT'], JSON_PRETTY_PRINT);
    exit;
}

if ($amount[0] === '-' || $amount[0] === '+') {
    echo json_encode(['status'=>'fail','msg'=>'AMOUNT NOT SUPPORT'], JSON_PRETTY_PRINT);
    exit;
}

$amount = (float)$amount;

if (!is_finite($amount) || $amount <= 0) {
    echo json_encode(['status'=>'fail','msg'=>'INVALID AMOUNT'], JSON_PRETTY_PRINT);
    exit;
}

/* ===============================
   CEK AGENT & USER
=============================== */
$data_op = agent_find_by_name($call, $agent_name, $secret_key);

if ($data_op === null) {
    echo json_encode(['status'=>'fail','msg'=>'INVALID AGENT'], JSON_PRETTY_PRINT);
    exit;
}

$agent_ref = mysqli_real_escape_string($call, agent_public_name($data_op));
$agent_row_name = mysqli_real_escape_string($call, agent_public_name($data_op));
$agent_user_where = agent_reference_condition($call, 'agent_code', $data_op);

$qUser = mysqli_query(
    $call,
    "SELECT * FROM tb_user
     WHERE extUser='$username'
       AND $agent_user_where
     LIMIT 1"
);

if (!$qUser || mysqli_num_rows($qUser) === 0) {
    echo json_encode(['status'=>'fail','msg'=>'MEMBER NOT FOUND'], JSON_PRETTY_PRINT);
    exit;
}

$data_user = mysqli_fetch_assoc($qUser);

/* ===============================
   IP WHITELIST
=============================== */
$whitelisted_ips = array_filter(
    array_map('trim', explode(',', $data_op['agent_IP1'] ?? ''))
);

if (!in_array($client_ip, $whitelisted_ips, true)) {
    echo json_encode([
        'status'=>'fail',
        'msg'=>"IP $client_ip Tidak Diizinkan"
    ], JSON_PRETTY_PRINT);
    exit;
}

if ($data_op['agent_status'] === 'blocked') {
    echo json_encode(['status'=>'fail','msg'=>'AGENT STATUS INACTIVE'], JSON_PRETTY_PRINT);
    exit;
}

/* ===============================
   PROCESS TRANSFER
=============================== */
if ($type === 'deposit' || $type === 'withdraw') {
    mysqli_begin_transaction($call);

    try {
        $agent_id = (int)$data_op['id'];
        $user_id = (int)$data_user['id'];

        $qAgentLock = mysqli_query(
            $call,
            "SELECT *
             FROM tb_agent
             WHERE id='$agent_id'
             LIMIT 1
             FOR UPDATE"
        );

        if (!$qAgentLock || mysqli_num_rows($qAgentLock) === 0) {
            throw new Exception('INVALID AGENT');
        }

        $locked_agent = mysqli_fetch_assoc($qAgentLock);

        if (($locked_agent['agent_status'] ?? '') === 'blocked') {
            throw new Exception('AGENT STATUS INACTIVE');
        }

        $locked_agent_where = agent_reference_condition($call, 'agent_code', $locked_agent);

        $qUserLock = mysqli_query(
            $call,
            "SELECT *
             FROM tb_user
             WHERE id='$user_id'
               AND $locked_agent_where
             LIMIT 1
             FOR UPDATE"
        );

        if (!$qUserLock || mysqli_num_rows($qUserLock) === 0) {
            throw new Exception('MEMBER NOT FOUND');
        }

        $locked_user = mysqli_fetch_assoc($qUserLock);
        $before_bal = (float)$locked_agent['agent_balance'];
        $user_balance = (float)$locked_user['balance'];

        if ($type === 'deposit' && $before_bal < $amount) {
            throw new Exception('INSUFFICIENT AGENT BALANCE');
        }

        if ($type === 'withdraw' && $user_balance < $amount) {
            throw new Exception('INSUFFICIENT USER BALANCE');
        }

        $after_bal = $type === 'deposit'
            ? $before_bal - $amount
            : $before_bal + $amount;

        $trxid = md5(microtime(true).$username.$amount.random_int(1000, 999999));
        $created = date('Y-m-d H:i:s');
        $int_user = mysqli_real_escape_string($call, (string)$locked_user['intUser']);
        $trx_agent_ref = mysqli_real_escape_string($call, agent_public_name($locked_agent));

        $insert = mysqli_query(
            $call,
            "INSERT INTO tb_transaction
                (trxid, intUser, extUser, type, amount, before_agent_balance, after_agent_balance, agent_code, created, provider)
             VALUES
                ('$trxid','$int_user','$username','$type','$amount','$before_bal','$after_bal','$trx_agent_ref','$created','CHAOSAPI')"
        );

        if (!$insert) {
            throw new Exception('TRANSACTION RECORD FAILED');
        }

        if ($type === 'deposit') {
            $ua = mysqli_query(
                $call,
                "UPDATE tb_agent
                 SET agent_balance = agent_balance - '$amount'
                 WHERE id='$agent_id'
                   AND agent_balance >= '$amount'"
            );
            $agent_affected = $ua ? mysqli_affected_rows($call) : 0;

            $uu = mysqli_query(
                $call,
                "UPDATE tb_user
                 SET balance = balance + '$amount'
                 WHERE id='$user_id'"
            );
            $user_affected = $uu ? mysqli_affected_rows($call) : 0;
        } else {
            $ua = mysqli_query(
                $call,
                "UPDATE tb_agent
                 SET agent_balance = agent_balance + '$amount'
                 WHERE id='$agent_id'"
            );
            $agent_affected = $ua ? mysqli_affected_rows($call) : 0;

            $uu = mysqli_query(
                $call,
                "UPDATE tb_user
                 SET balance = balance - '$amount'
                 WHERE id='$user_id'
                   AND balance >= '$amount'"
            );
            $user_affected = $uu ? mysqli_affected_rows($call) : 0;
        }

        if (!$ua || !$uu || $agent_affected < 1 || $user_affected < 1) {
            throw new Exception('UPDATE BALANCE FAILED');
        }

        mysqli_commit($call);

        $res = [
            'status' => 200,
            'message' => 'success',
            'data'   => [
                'username'       => $username,
                'action'         => strtoupper($type),
                'amount_balance' => $amount,
            ],
        ];
    } catch (Exception $e) {
        mysqli_rollback($call);
        $res = ['status'=>'fail','msg'=>$e->getMessage()];
    }
} else {
    $res = ['status'=>'fail','msg'=>'INVALID TYPE'];
}

echo json_encode($res, JSON_PRETTY_PRINT);
