<?php
require_once __DIR__ . '/../app/bootstrap.php';

use App\Core\Auth;
use App\Core\Database;
use App\Core\Response;
use App\Core\Security;
use App\Core\WalletService;

Auth::requireLogin('public/login.php');
if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !verify_csrf()) {
    Response::json(['ok' => false, 'message' => 'Invalid request.'], 419);
}
if (!Security::rateLimit('withdraw-request:' . Auth::id(), 8, 3600)) {
    Response::json(['ok' => false, 'message' => 'Too many withdrawal requests. Try again later.'], 429);
}

$data = request_data();
$amount = round((float)($data['amount'] ?? 0), 2);
$type = strtolower((string)($data['wallet_type'] ?? 'cash'));
$method = strtolower(trim((string)($data['method'] ?? '')));
$details = mb_substr(trim((string)($data['account_details'] ?? '')), 0, 500);
$minimum = max(0, (float)setting('minimum_withdraw', '500'));
$allowedWallets = ['cash', 'commission', 'royalty', 'bonus'];
$allowedMethods = ['bkash', 'nagad', 'rocket', 'bank', 'cash'];

if (!is_finite($amount) || $amount < $minimum || $amount <= 0) {
    Response::json(['ok' => false, 'message' => 'Minimum withdrawal is ' . money($minimum) . '.'], 422);
}
if (!in_array($type, $allowedWallets, true)) {
    Response::json(['ok' => false, 'message' => 'This wallet cannot be withdrawn.'], 422);
}
if (!in_array($method, $allowedMethods, true) || $details === '') {
    Response::json(['ok' => false, 'message' => 'Select a valid payment method and enter account details.'], 422);
}

$user = Database::safeFetchOne('SELECT transaction_pin_hash FROM users WHERE id=?', [Auth::id()]);
if (!empty($user['transaction_pin_hash']) && !password_verify((string)($data['pin'] ?? ''), (string)$user['transaction_pin_hash'])) {
    Security::logActivity(Auth::id(), 'withdrawal_pin_failed', ['wallet_type' => $type]);
    Response::json(['ok' => false, 'message' => 'Invalid transaction PIN.'], 422);
}
$net = WalletService::withdrawNet($amount);
if ((float)$net['net'] <= 0) {
    Response::json(['ok' => false, 'message' => 'Withdrawal amount is too small after fees.'], 422);
}

try {
    $requestId = Database::transaction(function () use ($type, $amount, $method, $details, $net): int {
        if (!WalletService::debit((int)Auth::id(), $type, $amount, 'Withdrawal request')) {
            throw new RuntimeException('Insufficient wallet balance.');
        }
        WalletService::credit((int)Auth::id(), 'withdraw', $amount, 'Withdrawal amount on hold');
        Database::execute(
            'INSERT INTO withdraw_requests (user_id,wallet_type,amount,fee,net_amount,method,account_details,status,created_at,updated_at) VALUES (?,?,?,?,?,?,?,"pending",NOW(),NOW())',
            [Auth::id(), $type, $amount, $net['fee'], $net['net'], $method, $details]
        );
        return Database::lastInsertId();
    });
    Security::logActivity(Auth::id(), 'withdrawal_requested', ['request_id' => $requestId, 'wallet_type' => $type, 'amount' => $amount, 'method' => $method]);
    Response::json(['ok' => true, 'request_id' => $requestId, 'withdrawal' => $net, 'message' => 'Withdrawal request submitted.']);
} catch (Throwable $exception) {
    error_log('Withdrawal request failed: ' . $exception->getMessage());
    Response::json(['ok' => false, 'message' => $exception instanceof RuntimeException ? $exception->getMessage() : 'Could not submit the withdrawal request.'], 422);
}
