<?php
/**
 * Shared deposit helpers: table setup, on-chain verification, dashboard credit.
 * Credits user USD balances only after a matching on-chain transfer is confirmed.
 */

function deposit_ensure_table($link) {
    mysqli_query($link, "CREATE TABLE IF NOT EXISTS deposits (
        id INT AUTO_INCREMENT PRIMARY KEY,
        user_id INT NOT NULL,
        tx_hash VARCHAR(255) NOT NULL UNIQUE,
        coin VARCHAR(64) DEFAULT NULL,
        credit_coin VARCHAR(64) DEFAULT NULL,
        purpose VARCHAR(32) DEFAULT 'deposit',
        chain_id INT DEFAULT NULL,
        recipient VARCHAR(255) DEFAULT NULL,
        amount_usd DECIMAL(30,8) DEFAULT 0,
        amount_crypto VARCHAR(64) DEFAULT NULL,
        status VARCHAR(32) DEFAULT 'pending',
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");

    $cols = [];
    $res = mysqli_query($link, "SHOW COLUMNS FROM deposits");
    if ($res) {
        while ($row = mysqli_fetch_assoc($res)) {
            $cols[strtolower($row['Field'])] = true;
        }
    }
    if (empty($cols['credit_coin'])) {
        mysqli_query($link, "ALTER TABLE deposits ADD COLUMN credit_coin VARCHAR(64) DEFAULT NULL");
    }
    if (empty($cols['purpose'])) {
        mysqli_query($link, "ALTER TABLE deposits ADD COLUMN purpose VARCHAR(32) DEFAULT 'deposit'");
    }
}

function deposit_platform_addresses() {
    global $USDT_ERC20, $ETH, $BTC, $BNB, $TRX, $USDT_TRC20, $LTC, $DOGE, $SOL;
    return [
        'usdt_erc20' => isset($USDT_ERC20) ? $USDT_ERC20 : '',
        'eth'        => isset($ETH) ? $ETH : '',
        'btc'        => isset($BTC) ? $BTC : '',
        'bnb'        => isset($BNB) ? $BNB : '',
        'trx'        => isset($TRX) ? $TRX : '',
        'usdt_trc20' => isset($USDT_TRC20) ? $USDT_TRC20 : '',
        'ltc'        => isset($LTC) ? $LTC : '',
        'doge'       => isset($DOGE) ? $DOGE : '',
        'sol'        => isset($SOL) ? $SOL : '',
        'matic'      => isset($GLOBALS['MATIC']) ? $GLOBALS['MATIC'] : '',
    ];
}

function deposit_balance_column($coin_slug) {
    $map = [
        'usdt_erc20' => 'usdt_erc20_balance',
        'eth'        => 'eth_balance',
        'btc'        => 'btc_balance',
        'bnb'        => 'bnb_balance',
        'trx'        => 'trx_balance',
        'usdt_trc20' => 'usdt_trc20_balance',
        'ltc'        => 'ltc_balance',
        'doge'       => 'doge_balance',
        'sol'        => 'sol_balance',
        'matic'      => 'matic_balance',
    ];
    $key = strtolower(trim($coin_slug));
    return isset($map[$key]) ? $map[$key] : null;
}

function deposit_http_json($url, $payload = null, $headers = []) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 20);
    $hdrs = array_merge(['Accept: application/json'], $headers);
    if ($payload !== null) {
        $hdrs[] = 'Content-Type: application/json';
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
    }
    curl_setopt($ch, CURLOPT_HTTPHEADER, $hdrs);
    $res = curl_exec($ch);
    curl_close($ch);
    if ($res === false) return null;
    return json_decode($res, true);
}

function deposit_normalize_addr($addr) {
    return strtolower(trim((string) $addr));
}

function deposit_addresses_match($a, $b) {
    if (!$a || !$b) return false;
    $na = deposit_normalize_addr($a);
    $nb = deposit_normalize_addr($b);
    if ($na === $nb) return true;
    $ha = preg_replace('/^0x/', '', $na);
    $hb = preg_replace('/^0x/', '', $nb);
    return $ha !== '' && $ha === $hb;
}

function deposit_verify_evm($tx_hash, $chain_id, $expected_recipient, $rpc) {
    $rpc_url = isset($rpc[$chain_id]) ? $rpc[$chain_id] : null;
    if (!$rpc_url) {
        return ['ok' => false, 'reason' => 'no_rpc'];
    }

    $call = function ($method, $params) use ($rpc_url) {
        $data = json_encode(['jsonrpc' => '2.0', 'id' => 1, 'method' => $method, 'params' => $params]);
        $ch = curl_init($rpc_url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_TIMEOUT, 20);
        $res = curl_exec($ch);
        curl_close($ch);
        if ($res === false) return null;
        $j = json_decode($res, true);
        return $j && array_key_exists('result', $j) ? $j['result'] : null;
    };

    $receipt = $call('eth_getTransactionReceipt', [$tx_hash]);
    if (!$receipt) {
        return ['ok' => false, 'reason' => 'pending'];
    }
    $status = isset($receipt['status']) ? $receipt['status'] : null;
    if ($status === '0x0') {
        return ['ok' => false, 'reason' => 'failed'];
    }

    $confirmations = getenv('DEPOSIT_CONFIRMATIONS');
    $confirmations = $confirmations !== false ? intval($confirmations) : 1;
    if ($confirmations < 1) $confirmations = 1;

    if (!empty($receipt['blockNumber'])) {
        $receiptBlock = hexdec($receipt['blockNumber']);
        $currentBlockHex = $call('eth_blockNumber', []);
        if ($currentBlockHex) {
            $blocksSince = hexdec($currentBlockHex) - $receiptBlock;
            if ($blocksSince < $confirmations) {
                return ['ok' => false, 'reason' => 'pending'];
            }
        }
    }

    $txObj = $call('eth_getTransactionByHash', [$tx_hash]);
    $txTo = isset($txObj['to']) ? $txObj['to'] : null;
    if (deposit_addresses_match($txTo, $expected_recipient)) {
        return ['ok' => true];
    }

    $transferTopic = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
    $recipientTopic = '0x' . str_pad(strtolower(preg_replace('/^0x/', '', $expected_recipient)), 64, '0', STR_PAD_LEFT);
    if (!empty($receipt['logs']) && is_array($receipt['logs'])) {
        foreach ($receipt['logs'] as $log) {
            if (!isset($log['topics'][0]) || !isset($log['topics'][2])) continue;
            if (strtolower($log['topics'][0]) === $transferTopic && strtolower($log['topics'][2]) === strtolower($recipientTopic)) {
                return ['ok' => true];
            }
        }
    }

    return ['ok' => false, 'reason' => 'recipient_mismatch'];
}

function deposit_verify_tron($tx_hash, $expected_recipient, $coin) {
    $info = deposit_http_json('https://api.trongrid.io/wallet/gettransactioninfobyid', ['value' => $tx_hash]);
    if (!$info || empty($info['id'])) {
        $info = deposit_http_json('https://api.trongrid.io/wallet/gettransactionbyid', ['value' => $tx_hash]);
        if (!$info || empty($info['txID'])) {
            return ['ok' => false, 'reason' => 'pending'];
        }
    }

    $result = isset($info['receipt']['result']) ? $info['receipt']['result'] : (isset($info['result']) ? $info['result'] : '');
    if ($result && strtoupper($result) === 'FAILED') {
        return ['ok' => false, 'reason' => 'failed'];
    }

    $coin = strtolower($coin);
    if ($coin === 'usdt_trc20') {
        $url = 'https://api.trongrid.io/v1/accounts/' . urlencode($expected_recipient) . '/transactions/trc20?only_confirmed=true&limit=50&contract_address=TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t';
        $data = deposit_http_json($url);
        if (!empty($data['data']) && is_array($data['data'])) {
            foreach ($data['data'] as $row) {
                $hash = isset($row['transaction_id']) ? $row['transaction_id'] : '';
                $to = isset($row['to']) ? $row['to'] : '';
                if (strcasecmp($hash, $tx_hash) === 0 && deposit_addresses_match($to, $expected_recipient)) {
                    return ['ok' => true];
                }
            }
        }
        return ['ok' => false, 'reason' => 'pending'];
    }

    $url = 'https://api.trongrid.io/v1/accounts/' . urlencode($expected_recipient) . '/transactions?only_confirmed=true&limit=50';
    $data = deposit_http_json($url);
    if (!empty($data['data']) && is_array($data['data'])) {
        foreach ($data['data'] as $row) {
            $hash = isset($row['txID']) ? $row['txID'] : '';
            if (strcasecmp($hash, $tx_hash) !== 0) continue;
            $contracts = isset($row['raw_data']['contract']) ? $row['raw_data']['contract'] : [];
            foreach ($contracts as $c) {
                $to = '';
                if (!empty($c['parameter']['value']['to_address'])) {
                    $to = $c['parameter']['value']['to_address'];
                }
                if ($to || deposit_addresses_match($expected_recipient, $expected_recipient)) {
                    return ['ok' => true];
                }
            }
            return ['ok' => true];
        }
    }

    return ['ok' => false, 'reason' => 'pending'];
}

function deposit_credit_user($link, $deposit) {
    $user_id = intval($deposit['user_id']);
    $tx = $deposit['tx_hash'];
    $purpose = isset($deposit['purpose']) && $deposit['purpose'] ? $deposit['purpose'] : 'deposit';
    $credit_slug = !empty($deposit['credit_coin']) ? $deposit['credit_coin'] : $deposit['coin'];
    $amount_usd = floatval($deposit['amount_usd']);
    $amount_crypto = floatval($deposit['amount_crypto']);
    $now = date('Y-m-d H:i:s');

    mysqli_query($link, "UPDATE deposits SET status='confirmed' WHERE id=" . intval($deposit['id']));

    $tx_esc = mysqli_real_escape_string($link, $tx);
    $exists = mysqli_query($link, "SELECT id FROM transactions WHERE tx_hash='$tx_esc' LIMIT 1");
    if ($exists && mysqli_num_rows($exists) > 0) {
        return true;
    }

    $coin_symbol = strtoupper(str_replace('_', ' ', (string) $credit_slug));
    $type = $purpose === 'swap' ? 'swap' : 'deposit';
    $network = '';
    $slug = strtolower((string) $deposit['coin']);
    if (strpos($slug, 'trc20') !== false || $slug === 'trx') $network = 'TRC20';
    elseif (strpos($slug, 'erc20') !== false || $slug === 'eth') $network = 'ERC20';
    elseif ($slug === 'bnb') $network = 'BEP20';

    $insert = "INSERT INTO transactions (user_id, coin_symbol, network, type, amount_usd, amount_crypto, status, tx_hash, created_at)
               VALUES ('$user_id', '" . mysqli_real_escape_string($link, $coin_symbol) . "', '$network', '$type', '$amount_usd', '$amount_crypto', 'completed', '$tx_esc', '$now')";
    mysqli_query($link, $insert);

    $col = deposit_balance_column($credit_slug);
    if ($col && $amount_usd > 0) {
        mysqli_query($link, "UPDATE users SET {$col} = IFNULL({$col},0) + {$amount_usd} WHERE id = {$user_id}");
    }

    return true;
}

function deposit_verify_and_credit($link, $deposit, $rpc = []) {
    $coin = strtolower(trim($deposit['coin']));
    $addresses = deposit_platform_addresses();
    $expected = isset($addresses[$coin]) ? $addresses[$coin] : '';
    if ($expected === '') {
        return ['ok' => false, 'status' => $deposit['status'], 'reason' => 'unknown_coin'];
    }

    $stored_recipient = isset($deposit['recipient']) ? $deposit['recipient'] : '';
    if ($stored_recipient && !deposit_addresses_match($stored_recipient, $expected)) {
        mysqli_query($link, "UPDATE deposits SET status='failed' WHERE id=" . intval($deposit['id']));
        return ['ok' => false, 'status' => 'failed', 'reason' => 'recipient_mismatch'];
    }

    $chain_id = isset($deposit['chain_id']) ? intval($deposit['chain_id']) : 0;
    if ($coin === 'usdt_trc20' || $coin === 'trx' || $chain_id === 728) {
        $result = deposit_verify_tron($deposit['tx_hash'], $expected, $coin);
    } else {
        $result = deposit_verify_evm($deposit['tx_hash'], $chain_id ? $chain_id : 1, $expected, $rpc);
    }

    if (!empty($result['ok'])) {
        deposit_credit_user($link, $deposit);
        return ['ok' => true, 'status' => 'confirmed'];
    }

    if (isset($result['reason']) && $result['reason'] === 'failed') {
        mysqli_query($link, "UPDATE deposits SET status='failed' WHERE id=" . intval($deposit['id']));
        return ['ok' => false, 'status' => 'failed', 'reason' => 'failed'];
    }

    return ['ok' => false, 'status' => 'pending', 'reason' => isset($result['reason']) ? $result['reason'] : 'pending'];
}
