<?php
/**
 * request_withdrawal.php
 * 
 * Handles user withdrawal requests
 * Creates a pending withdrawal transaction that requires admin approval
 * Part of the Ton Sui Mining investment lifecycle
 */

header('Content-Type: application/json');
// Critical: Add cache control headers
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
// CRITICAL: Allow origin with credentials
$allowed_origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '*';
header("Access-Control-Allow-Origin: $allowed_origin");
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
header('Access-Control-Allow-Credentials: true');
header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: DENY');
header('X-XSS-Protection: 1; mode=block');

// Handle preflight OPTIONS request
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit;
}

// Define TONSUI_LOADED constant to prevent direct access to session_init.php
define('TONSUI_LOADED', true);

// Include centralized session initialization
require_once __DIR__ . '/session_init.php';

// Require user authentication
requireLogin(true);

require_once 'config.php';
require_once 'db.php';

// Validate request method
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode(['success' => false, 'message' => 'Method not allowed']);
    exit;
}

// Get and validate POST data
$json_data = file_get_contents('php://input');
$data = json_decode($json_data, true);

if (!$data || !isset($data['amount']) || !isset($data['payment_method_id']) || !isset($data['withdrawal_address'])) {
    http_response_code(400);
    echo json_encode(['success' => false, 'message' => 'Missing required fields']);
    exit;
}

// If pin is required for this user, the pin must be provided
$withdrawal_pin = isset($data['withdrawal_pin']) ? trim($data['withdrawal_pin']) : null;

$amount = floatval($data['amount']);
$payment_method_id = intval($data['payment_method_id']);
$withdrawal_address = htmlspecialchars(trim($data['withdrawal_address']), ENT_QUOTES, 'UTF-8');
$notes = isset($data['notes']) ? htmlspecialchars(trim($data['notes']), ENT_QUOTES, 'UTF-8') : '';

try {
    // Begin transaction
    $pdo->beginTransaction();
    
    // **CRITICAL: Check KYC verification and account flags FIRST**
    $hasSusp = false; $hasTxSusp = false; $hasDormant = false;
    try { $hasSusp = $pdo->query("SHOW COLUMNS FROM users LIKE 'account_suspended'")->rowCount() > 0; } catch (Exception $e) {}
    try { $hasTxSusp = $pdo->query("SHOW COLUMNS FROM users LIKE 'transfers_suspended'")->rowCount() > 0; } catch (Exception $e) {}
    try { $hasDormant = $pdo->query("SHOW COLUMNS FROM users LIKE 'account_dormant'")->rowCount() > 0; } catch (Exception $e) {}

    // Determine KYC column across schemas
    $hasKycVerified = false; $hasKycStatus = false; $hasIsVerified = false;
    try { $hasKycVerified = $pdo->query("SHOW COLUMNS FROM users LIKE 'kyc_verified'")->rowCount() > 0; } catch (Exception $e) {}
    try { $hasKycStatus = $pdo->query("SHOW COLUMNS FROM users LIKE 'kycStatus'")->rowCount() > 0; } catch (Exception $e) {}
    try { $hasIsVerified = $pdo->query("SHOW COLUMNS FROM users LIKE 'is_verified'")->rowCount() > 0; } catch (Exception $e) {}

    if ($hasKycVerified) {
        $kycSelect = 'kyc_verified AS kyc_ok';
    } elseif ($hasKycStatus) {
        $kycSelect = "(CASE WHEN kycStatus='approved' THEN 1 ELSE 0 END) AS kyc_ok";
    } elseif ($hasIsVerified) {
        $kycSelect = 'is_verified AS kyc_ok';
    } else {
        // Fallback: if no KYC column exists, don't block (treat as verified)
        $kycSelect = '1 AS kyc_ok';
    }

    $selFlags = ($hasSusp ? ', account_suspended' : '') . ($hasTxSusp ? ', transfers_suspended' : '') . ($hasDormant ? ', account_dormant' : '');
    $userStmt = $pdo->prepare("SELECT balance, $kycSelect$selFlags FROM users WHERE id = ?");
    $userStmt->execute([isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 0]);
    $user = $userStmt->fetch(PDO::FETCH_ASSOC);
    
    if (!$user) {
        throw new Exception('User not found');
    }
    
    // Bypass KYC if disabled in config
    if (isset($config['kyc_required']) && $config['kyc_required'] === false) {
        $user['kyc_ok'] = 1;
    }
    $user['kyc_ok'] = 1;

    if (!isset($user['kyc_ok']) || intval($user['kyc_ok']) === 0) {
        http_response_code(403);
        echo json_encode([
            'success' => false, 
            'message' => 'KYC verification required',
            'error_code' => 'KYC_REQUIRED',
            'redirect' => '/dashboard/kyc'
        ]);
        $pdo->rollBack();
        exit;
    }

    // Enforce account restriction flags
    if ($hasSusp && intval($user['account_suspended'] ?? 0) === 1) {
        http_response_code(403);
        echo json_encode(['success'=>false,'message'=>'Account is suspended','error_code'=>'ACCOUNT_SUSPENDED']);
        $pdo->rollBack();
        exit;
    }
    if (($hasTxSusp && intval($user['transfers_suspended'] ?? 0) === 1) || ($hasDormant && intval($user['account_dormant'] ?? 0) === 1)) {
        http_response_code(403);
        echo json_encode(['success'=>false,'message'=>'Transfers are suspended for this account','error_code'=> ($hasDormant && intval($user['account_dormant'] ?? 0) === 1) ? 'ACCOUNT_DORMANT' : 'TRANSFERS_SUSPENDED']);
        $pdo->rollBack();
        exit;
    }
    
    // Validate amount
    if ($amount <= 0) {
        throw new Exception('Invalid withdrawal amount');
    }
    
    // Check if payment method exists and is active
    $methodStmt = $pdo->prepare("SELECT * FROM payment_methods WHERE id = ? AND status = 'active'");
    $methodStmt->execute([$payment_method_id]);
    $payment_method = $methodStmt->fetch(PDO::FETCH_ASSOC);
    
    if (!$payment_method) {
        throw new Exception('Invalid or inactive payment method');
    }
    
    // Validate recipient details based on payment method characteristics
    $pmType = strtolower($payment_method['type'] ?? '');
    $pmName = strtolower($payment_method['name'] ?? '');
    $isCrypto = ($pmType === 'crypto') || preg_match('/btc|eth|usdt|tron|ton|sui|wallet|address|crypto/', $pmName);
    if ($isCrypto) {
        // Crypto-like methods require longer address strings
        if (empty($withdrawal_address) || strlen($withdrawal_address) < 10) {
            throw new Exception('Invalid withdrawal address');
        }
    } else {
        // Bank/Wire/Other methods may be simple account holder or reference text
        if (empty($withdrawal_address) || strlen($withdrawal_address) < 2) {
            throw new Exception('Please enter your payout details (e.g., account holder name).');
        }
    }
    
    // **NEW LOGIC: Check if user HAS any active PINs**
    $used_pin_name = null;
    // If user has PINs → require PIN validation
    // If user has NO PINs → allow withdrawal without PIN (admin still approves)
    $has_status = false; $has_used = false; $has_expiry = false; $has_name = false; $has_updated = false; $has_used_at = false; $has_transaction = false;
    try {
        $cols = $pdo->query("SHOW COLUMNS FROM withdrawal_pins");
        while ($c = $cols->fetch(PDO::FETCH_ASSOC)) {
            $f = strtolower($c['Field'] ?? '');
            if ($f === 'status') $has_status = true;
            if ($f === 'used') $has_used = true;
            if ($f === 'expiry_date') $has_expiry = true;
            if ($f === 'name') $has_name = true;
            if ($f === 'updated_at') $has_updated = true;
            if ($f === 'used_at') $has_used_at = true;
            if ($f === 'transaction_id') $has_transaction = true;
        }
    } catch (Exception $e) { /* ignore */ }

    if ($has_status) {
        $sql = "SELECT COUNT(*) FROM withdrawal_pins WHERE user_id=? AND status='active'";
        if ($has_expiry) { $sql .= " AND (expiry_date IS NULL OR expiry_date > NOW())"; }
        $checkPinsStmt = $pdo->prepare($sql);
        $checkPinsStmt->execute([isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 0]);
        $active_pin_count = (int)$checkPinsStmt->fetchColumn();
    } elseif ($has_used) {
        $checkPinsStmt = $pdo->prepare("SELECT COUNT(*) FROM withdrawal_pins WHERE user_id=? AND (used=0 OR used IS NULL)");
        $checkPinsStmt->execute([isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 0]);
        $active_pin_count = (int)$checkPinsStmt->fetchColumn();
    } else {
        $active_pin_count = 0;
    }
    
    // User has active PINs → must provide valid PIN
    $user_has_pins = ($active_pin_count > 0);
    
    // If user has active PINs, they MUST provide one
    if ($user_has_pins) {
        if (!$withdrawal_pin) {
            throw new Exception('Withdrawal PIN is required for security reasons');
        }
        
        // Validate PIN is numeric only (security)
        if (!ctype_digit($withdrawal_pin)) {
            throw new Exception('Invalid PIN format. PIN must contain only numbers.');
        }
        
        // Verify that the user has this active pin (handle both schemas)
        if ($has_status) {
            $sql = "SELECT id, pin" . ($has_name ? ", name" : "") . ($has_expiry ? ", expiry_date" : "") .
                   " FROM withdrawal_pins WHERE user_id=? AND pin=? AND status='active'" .
                   ($has_expiry ? " AND (expiry_date IS NULL OR expiry_date > NOW())" : "") .
                   " LIMIT 1";
            $pinVerifyStmt = $pdo->prepare($sql);
            $pinVerifyStmt->execute([isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 0, $withdrawal_pin]);
            $existing_pin = $pinVerifyStmt->fetch(PDO::FETCH_ASSOC);
        } elseif ($has_used) {
            $pinVerifyStmt = $pdo->prepare("SELECT id, pin FROM withdrawal_pins WHERE user_id=? AND pin=? AND (used=0 OR used IS NULL) LIMIT 1");
            $pinVerifyStmt->execute([isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 0, $withdrawal_pin]);
            $existing_pin = $pinVerifyStmt->fetch(PDO::FETCH_ASSOC);
        } else {
            $existing_pin = false;
        }
        
        if (!$existing_pin) {
            throw new Exception('Invalid or expired withdrawal PIN. Please use a valid active PIN.');
        }
        if ($has_name && isset($existing_pin['name']) && $existing_pin['name'] !== '') { $used_pin_name = (string)$existing_pin['name']; }
        
        // Mark this pin as used (schema-aware)
        if ($has_status) {
            $sql = "UPDATE withdrawal_pins SET status='used'" . ($has_transaction ? ", transaction_id=NULL" : "") . ($has_updated ? ", updated_at=NOW()" : "") . " WHERE id=?";
            $pinUpdateStmt = $pdo->prepare($sql);
            $pinUpdateStmt->execute([$existing_pin['id']]);
        } elseif ($has_used) {
            $sql = "UPDATE withdrawal_pins SET used=1" . ($has_transaction ? ", transaction_id=NULL" : "") . ($has_used_at ? ", used_at=NOW()" : "") . " WHERE id=?";
            $pinUpdateStmt = $pdo->prepare($sql);
            $pinUpdateStmt->execute([$existing_pin['id']]);
        }
        // Delete the pin after it has been used
        try {
            $del = $pdo->prepare("DELETE FROM withdrawal_pins WHERE id = ?");
            $del->execute([$existing_pin['id']]);
        } catch (Exception $e) { /* ignore */ }
    }
    
    $user_balance = floatval($user['balance']);
    
    if ($user_balance < $amount) {
        throw new Exception('Insufficient balance for withdrawal');
    }
    
    // Check minimum withdrawal amount
    $min_withdrawal = floatval($payment_method['min_withdrawal'] ?? 0);
    if ($amount < $min_withdrawal) {
        throw new Exception("Minimum withdrawal amount is {$min_withdrawal} {$payment_method['currency']}");
    }
    
    // Check pending withdrawals (optional - limit concurrent pending withdrawals)
    $pendingStmt = $pdo->prepare("
        SELECT COUNT(*) FROM transactions 
        WHERE user_id = ? AND type = 'withdrawal' AND status = 'pending'
    ");
    
    $pendingStmt->execute([isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 0]);
    $pending_count = $pendingStmt->fetchColumn();
    
    $max_pending = 3; // Maximum allowed pending withdrawals
    if ($pending_count >= $max_pending) {
        throw new Exception("You have too many pending withdrawals. Please wait for your previous requests to be processed.");
    }
    
    // Generate reference code
    $reference = 'WD-' . strtoupper(substr(md5(uniqid()), 0, 8));
    
    // Create transaction details (include optional bank_details if provided)
    $details_arr = [
        'payment_method_id' => $payment_method_id,
        'payment_method_name' => $payment_method['name'],
        'payment_method_currency' => $payment_method['currency'],
        'withdrawal_address' => $withdrawal_address,
        'pin_required' => $user_has_pins,
        'pin_verified' => $user_has_pins ? true : null,
        'user_notes' => $notes
    ];

    if (isset($data['bank_details']) && is_array($data['bank_details'])) {
      $bd = $data['bank_details'];
      // Sanitize optional fields
      $bank_details = [];
      if (!empty($bd['account_name'])) {
        $bank_details['account_name'] = htmlspecialchars(trim($bd['account_name']), ENT_QUOTES, 'UTF-8');
      }
      if (!empty($bd['bank_name'])) {
        $bank_details['bank_name'] = htmlspecialchars(trim($bd['bank_name']), ENT_QUOTES, 'UTF-8');
      }
      if (!empty($bd['account_number'])) {
        $bank_details['account_number'] = htmlspecialchars(trim($bd['account_number']), ENT_QUOTES, 'UTF-8');
      }
      if (!empty($bd['routing_number'])) {
        $bank_details['routing_number'] = htmlspecialchars(trim($bd['routing_number']), ENT_QUOTES, 'UTF-8');
      }
      if (!empty($bd['iban'])) {
        $bank_details['iban'] = htmlspecialchars(trim($bd['iban']), ENT_QUOTES, 'UTF-8');
      }
      if (!empty($bd['swift'])) {
        $bank_details['swift'] = htmlspecialchars(trim($bd['swift']), ENT_QUOTES, 'UTF-8');
      }
      if (!empty($bd['country'])) {
        $bank_details['country'] = htmlspecialchars(trim($bd['country']), ENT_QUOTES, 'UTF-8');
      }
      if (!empty($bd['bank_address'])) {
        $bank_details['bank_address'] = htmlspecialchars(trim($bd['bank_address']), ENT_QUOTES, 'UTF-8');
      }
      if (!empty($bd['additional_details'])) {
        $bank_details['additional_details'] = htmlspecialchars(trim($bd['additional_details']), ENT_QUOTES, 'UTF-8');
      }
      if (!empty($bd['currency'])) {
        $bank_details['currency'] = strtoupper(trim($bd['currency']));
      }
      if (!empty($bank_details)) {
        $details_arr['bank_details'] = $bank_details;
      }
    }

    // details will be encoded after computing final currency

    // Determine currency priority: bank_details.currency > user's account_currency > payment_method.currency
    $finalCurrency = (string)($details_arr['bank_details']['currency'] ?? '');
    if ($finalCurrency === '' || $finalCurrency === null) {
        try {
            $hasAcctCurr = $pdo->query("SHOW COLUMNS FROM users LIKE 'account_currency'")->rowCount() > 0;
            if ($hasAcctCurr) {
                $cs = $pdo->prepare('SELECT account_currency FROM users WHERE id=? LIMIT 1');
                $cs->execute([ isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 0 ]);
                $rowc = $cs->fetch(PDO::FETCH_ASSOC);
                if ($rowc && !empty($rowc['account_currency'])) { $finalCurrency = strtoupper((string)$rowc['account_currency']); }
            }
        } catch (Exception $ie) { /* ignore */ }
    }
    if ($finalCurrency === '' || $finalCurrency === null) { $finalCurrency = (string)($payment_method['currency'] ?? 'EUR'); }
    // Persist the resolved final currency in transaction details for later approval emails
    $details_arr['final_currency'] = $finalCurrency;
    $details = json_encode($details_arr);
    
    // Deduct the amount from user's balance
    $updateBalanceStmt = $pdo->prepare("UPDATE users SET balance = balance - ? WHERE id = ?");
    $updateBalanceStmt->execute([$amount, isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 0]);
    
    // Create withdrawal transaction (schema-aware for created_at)
    $hasTxCreated = false;
    try { $hasTxCreated = $pdo->query("SHOW COLUMNS FROM transactions LIKE 'created_at'")->rowCount() > 0; } catch (Exception $e) {}
    if ($hasTxCreated) {
        $transStmt = $pdo->prepare("
            INSERT INTO transactions 
            (user_id, type, amount, status, details, reference, created_at)
            VALUES (?, 'withdrawal', ?, 'pending', ?, ?, NOW())
        ");
        $transStmt->execute([isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 0, $amount, $details, $reference]);
    } else {
        $transStmt = $pdo->prepare("
            INSERT INTO transactions 
            (user_id, type, amount, status, details, reference)
            VALUES (?, 'withdrawal', ?, 'pending', ?, ?)
        ");
        $transStmt->execute([isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 0, $amount, $details, $reference]);
    }
    $transaction_id = $pdo->lastInsertId();

    // Commit the transaction BEFORE logging (best effort logging)
    $pdo->commit();

    // Best-effort security log (schema-aware event column)
    try {
        $eventCol = 'action';
        try {
            $c = $pdo->query("SHOW COLUMNS FROM security_logs LIKE 'event_type'");
            if ($c && $c->rowCount() > 0) { $eventCol = 'event_type'; }
            else {
                $c2 = $pdo->query("SHOW COLUMNS FROM security_logs LIKE 'event'");
                if ($c2 && $c2->rowCount() > 0) { $eventCol = 'event'; }
                else { $eventCol = 'action'; }
            }
        } catch (Exception $ie) { /* ignore */ }

        $sql = "INSERT INTO security_logs ($eventCol, user_id, ip_address, user_agent, details, created_at) VALUES (?, ?, ?, ?, ?, NOW())";
        $payload = json_encode([
            'transaction_id' => $transaction_id,
            'amount' => $amount,
            'payment_method' => $payment_method['name'],
            'currency' => $finalCurrency
        ]);
        $pdo->prepare($sql)->execute([
            'withdrawal_request',
            isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 0,
            $_SERVER['REMOTE_ADDR'] ?? 'unknown',
            $_SERVER['HTTP_USER_AGENT'] ?? 'unknown',
            $payload
        ]);
    } catch (Exception $logErr) {
        error_log('Withdrawal log write failed: ' . $logErr->getMessage());
    }
    
    try {
        require_once __DIR__ . '/email_helper.php';
        $userEmail = null; $userName = null;
        try {
            $u = $pdo->prepare('SELECT email, username, name FROM users WHERE id=? LIMIT 1');
            $u->execute([isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 0]);
            $row = $u->fetch(PDO::FETCH_ASSOC);
            if ($row) { $userEmail = $row['email']; $userName = $row['name'] ?: $row['username']; }
        } catch (Exception $ie) { /* ignore */ }
        if ($userEmail) {
            // Optional account number
            $accountNumber = '';
            try {
                $cc = $pdo->query("SHOW COLUMNS FROM users LIKE 'account_number'");
                if ($cc && $cc->rowCount() > 0) {
                    $qa = $pdo->prepare('SELECT account_number FROM users WHERE id = ? LIMIT 1');
                    $qa->execute([ isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 0 ]);
                    $ra = $qa->fetch(PDO::FETCH_ASSOC);
                    if ($ra && !empty($ra['account_number'])) { $accountNumber = (string)$ra['account_number']; }
                }
            } catch (Exception $ie) { /* ignore */ }
            $availableBalance = number_format(max(0, (float)$user_balance - $amount), 2) . ' ' . $finalCurrency;
            @sendEmail($pdo, $userEmail, 'withdrawalRequest', [
                'user_name' => ($userName ?: 'User'),
                'amount' => number_format($amount, 2) . ' ' . $finalCurrency,
                'method' => ($payment_method['name']),
                'date' => date('Y-m-d H:i:s'),
                'withdrawal_address' => $withdrawal_address,
                'account_number' => $accountNumber,
                'available_balance' => $availableBalance,
                'currency' => $finalCurrency,
            ]);
            if (false && $user_has_pins) {
              $destName = '';
              $bankName = '';
              if (!empty($details_arr['bank_details'])) {
                $bd = $details_arr['bank_details'];
                $destName = (string)($bd['account_name'] ?? '');
                $bankName = (string)($bd['bank_name'] ?? '');
              }
              $scheme = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https://' : 'http://');
              $host = $_SERVER['HTTP_HOST'] ?? 'localhost:5173';
              $prefill = $scheme . $host . '/dashboard/transfers?amount=' . urlencode(number_format($amount,2,'.','')) . '&method=' . urlencode((string)$payment_method['name']) . '&destination=' . urlencode($withdrawal_address) . '&currency=' . urlencode($finalCurrency);

              // Fetch all active/unused PINs and send one email per PIN
              $pinNames = [];
              try {
                if ($has_status) {
                  $sql = "SELECT" . ($has_name ? " name" : " '' AS name") . " FROM withdrawal_pins WHERE user_id=? AND status='active'" . ($has_expiry ? " AND (expiry_date IS NULL OR expiry_date > NOW())" : "");
                  $ps = $pdo->prepare($sql);
                  $ps->execute([ isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 0 ]);
                  while ($r = $ps->fetch(PDO::FETCH_ASSOC)) { $pinNames[] = (string)($r['name'] ?: 'Security PIN'); }
                } elseif ($has_used) {
                  $sql = "SELECT" . ($has_name ? " name" : " '' AS name") . " FROM withdrawal_pins WHERE user_id=? AND (used=0 OR used IS NULL)";
                  $ps = $pdo->prepare($sql);
                  $ps->execute([ isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 0 ]);
                  while ($r = $ps->fetch(PDO::FETCH_ASSOC)) { $pinNames[] = (string)($r['name'] ?: 'Security PIN'); }
                }
              } catch (Exception $ie) { /* ignore */ }
              if (empty($pinNames)) { $pinNames = ['Security PIN']; }

              foreach ($pinNames as $pn) {
                @sendEmail($pdo, $userEmail, 'withdrawalPinPending', [
                  'user_name' => ($userName ?: 'User'),
                  'date' => date('Y-m-d H:i:s'),
                  'amount' => number_format($amount, 2),
                  'currency' => $finalCurrency,
                  'pin_name' => $pn,
                  'destination_name' => ($destName ?: 'Beneficiary'),
                  'withdrawal_address' => $withdrawal_address,
                  'account_number' => $accountNumber,
                  'bank_name' => $bankName,
                  'prefilled_link' => $prefill,
                ]);
              }
            }
        }
    } catch (Exception $mailErr) { /* ignore */ }
    
    // Return success response
    echo json_encode([
        'success' => true,
        'message' => 'Withdrawal request submitted successfully. It will be processed within 24 hours.',
        'transaction' => [
            'id' => $transaction_id,
            'reference' => $reference,
            'amount' => $amount,
            'status' => 'pending',
            'currency' => $finalCurrency,
            'created_at' => date('Y-m-d H:i:s')
        ],
        'pin_required' => $user_has_pins,
        'pin_verified' => $user_has_pins ? true : false
    ]);
    
} catch (PDOException $e) {
    // Rollback transaction if in progress
    if ($pdo->inTransaction()) {
        $pdo->rollBack();
    }
    
    error_log('Database error in withdrawal request: ' . $e->getMessage());
    
    http_response_code(500);
    echo json_encode([
        'success' => false, 
        'message' => 'Database error processing withdrawal request.'
    ]);
    
} catch (Exception $e) {
    // Rollback transaction if in progress
    if ($pdo->inTransaction()) {
        $pdo->rollBack();
    }
    
    http_response_code(400);
    echo json_encode([
        'success' => false, 
        'message' => $e->getMessage()
    ]);
}
