<?php
// PhonePe PG V2 backend – AstroSidhi (UAT MODE)

// Version header for deploy verification
define('BUILD_VERSION', 'v2025-09-30_14:30_UAT');
header('X-App-Build: '.BUILD_VERSION);
error_log('[PG] BUILD='.BUILD_VERSION);

// ---------- routes ----------
$script = $_SERVER['SCRIPT_NAME'] ?? '';
$requestUri = $_SERVER['REQUEST_URI'] ?? '';
$path   = parse_url($requestUri, PHP_URL_PATH);
$route  = str_replace($script, '', $path);
if ($route === '') $route = '/';
if (strpos($path, '/webhook') !== false) $route = '/webhook';

// Set headers for all requests
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
if (($_SERVER['REQUEST_METHOD'] ?? '') === 'OPTIONS') exit(0);

// ---- UAT Mode credentials (for testing) ----
$MERCHANT_ID    = 'M23N011JX7ZSO';
$SALT_KEY       = 'ZTI5YjIzYzAtZTFhOC00MWNiLTk4YjAtMDdjYzNhYTdhNDk3';
$SALT_INDEX     = '1';

// ---- UAT endpoints (for testing) ----
$AUTH_URL        = 'https://api-preprod.phonepe.com/apis/pg-sandbox/v1/oauth/token';
$PAY_URL         = 'https://api-preprod.phonepe.com/apis/pg-sandbox/checkout/v1/pay';
$STATUS_URL_BASE = 'https://api-preprod.phonepe.com/apis/pg-sandbox/checkout/v1/order/';

// ---------- helpers ----------
function http_post_json($url, $payload, $headers = [], $timeout = 15) {
    $ch = curl_init($url);
  $finalHeaders = array_merge(['Content-Type: application/json'], $headers);
  
  curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => $finalHeaders,
    CURLOPT_POSTFIELDS     => json_encode($payload, JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE),
    CURLOPT_TIMEOUT        => $timeout,
    CURLOPT_CONNECTTIMEOUT => 10,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_MAXREDIRS      => 3,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_SSL_VERIFYHOST => false,
  ]);
  $res  = curl_exec($ch);
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  $err  = $res === false ? curl_error($ch) : null;
  curl_close($ch);
  return [json_decode($res, true), $code, $err];
}

function http_post_form($url, $fields, $timeout = 15) {
  $ch = curl_init($url);
  curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/x-www-form-urlencoded'],
    CURLOPT_POSTFIELDS     => http_build_query($fields),
    CURLOPT_TIMEOUT        => $timeout,
    CURLOPT_CONNECTTIMEOUT => 10,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_MAXREDIRS      => 3,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_SSL_VERIFYHOST => false,
  ]);
  $res  = curl_exec($ch);
  $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  $err  = $res === false ? curl_error($ch) : null;
    curl_close($ch);
  return [json_decode($res, true), $code, $err];
}

function http_get_json($url, $headers = [], $timeout = 15) {
    $ch = curl_init($url);
  curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => $headers,
    CURLOPT_TIMEOUT        => $timeout,
    CURLOPT_CONNECTTIMEOUT => 10,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_MAXREDIRS      => 3,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_SSL_VERIFYHOST => false,
  ]);
  $res  = curl_exec($ch);
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  $err  = $res === false ? curl_error($ch) : null;
  curl_close($ch);
  return [json_decode($res, true), $code, $err];
}

// ---------- Generate checksum for UAT ----------
function generate_checksum($payload, $endpoint) {
  global $SALT_KEY, $SALT_INDEX;
  
  $base64Payload = base64_encode($payload);
  $stringToHash = $base64Payload . $endpoint . $SALT_KEY;
  $checksum = hash('sha256', $stringToHash) . '###' . $SALT_INDEX;
  
  return $checksum;
}

// ---------- OAuth token with cache ----------
function get_oauth_token($AUTH_URL, $CLIENT_ID, $CLIENT_VERSION, $CLIENT_SECRET) {
  $cache = sys_get_temp_dir() . '/phonepe_oauth_token.json';
  
  if (file_exists($cache)) {
    $saved = json_decode(file_get_contents($cache), true);
    if (!empty($saved['access_token']) && $saved['expires_at'] > time() + 60) {
      return $saved['access_token'];
    }
  }
  
  list($resp, $code, $err) = http_post_form($AUTH_URL, [
    'client_id'      => $CLIENT_ID,
    'client_version' => $CLIENT_VERSION,
    'client_secret'  => $CLIENT_SECRET,
    'grant_type'     => 'client_credentials',
  ]);
  
  // Debug logging
  error_log("OAuth Request: URL=$AUTH_URL, CLIENT_ID=$CLIENT_ID");
  error_log("OAuth Response: code=$code, err=$err, resp=" . json_encode($resp));
  
  // Check OAuth response for environment indicators
  if (isset($resp['access_token'])) {
    error_log("OAuth Token Type: " . ($resp['token_type'] ?? 'unknown'));
    error_log("OAuth Expires In: " . ($resp['expires_in'] ?? 'unknown'));
    error_log("OAuth Full Response: " . json_encode($resp));
  }
  
  // If OAuth fails, return detailed error
  if ($err || $code < 200 || $code >= 300) {
    http_response_code(502);
    echo json_encode(['success'=>false,'step'=>'oauth','code'=>$code,'error'=>$err,'resp'=>$resp]); exit;
  }
  
  if (empty($resp['access_token'])) {
    http_response_code(502);
    echo json_encode(['success'=>false,'step'=>'oauth','code'=>$code,'error'=>'No access token','resp'=>$resp]); exit;
  }


  // Debug: Log successful token
  error_log("OAuth Token Generated Successfully: " . substr($resp['access_token'], 0, 20) . "...");

  $resp['expires_at'] = time() + (isset($resp['expires_in']) ? intval($resp['expires_in']) : 3600);
  @file_put_contents($cache, json_encode($resp));
  
  // Return the token with debug info
  error_log("Returning OAuth Token: " . substr($resp['access_token'], 0, 20) . "...");
  return $resp['access_token'];
}

// ---------- create payment ----------
if (($route === '/createPayment' || $route === '/') && ($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
  // Set JSON header for API response
  header('Content-Type: application/json; charset=utf-8');
  
  $rawInput = file_get_contents('php://input');
  $in = json_decode($rawInput, true);
  
  // Handle JSON parsing errors
  if (json_last_error() !== JSON_ERROR_NONE) {
    error_log("JSON Parse Error: " . json_last_error_msg());
    error_log("Raw Input: " . $rawInput);
    http_response_code(400);
    echo json_encode([
      'success' => false,
      'message' => 'Invalid JSON input: ' . json_last_error_msg(),
      'raw_input' => $rawInput
    ]);
    exit;
  }
  
  $in = $in ?: [];

  // Debug: Log incoming request
  error_log("=== PAYMENT REQUEST DEBUG ===");
  error_log("Raw Input: " . $rawInput);
  error_log("Parsed Input: " . json_encode($in));
  error_log("User Agent: " . ($_SERVER['HTTP_USER_AGENT'] ?? 'Unknown'));
  error_log("Request Source: " . ($_SERVER['HTTP_REFERER'] ?? 'Direct'));
  error_log("AmountPaise received: " . ($in['amountPaise'] ?? 'NOT_SET'));
  error_log("Amount received: " . ($in['amount'] ?? 'NOT_SET'));
  
  $merchantOrderId = $in['merchantTransactionId'] ?? $in['merchantOrderId'] ?? 'ASTRO-' . time() . '-' . random_int(1000, 9999);
  $amountPaise     = intval($in['amountPaise'] ?? $in['amount'] ?? 0);
  $webhookUrl      = $in['webhookUrl'] ?? 'https://astro.siddharthnahar.in/astro_admin/api/phonepe_v2_backend.php/webhook';
  
  error_log("Final amountPaise: $amountPaise");
  
  if ($amountPaise < 100) {
        http_response_code(400);
    echo json_encode(['success'=>false,'message'=>'amount (>=100 paise) required', 'received_amount'=>$amountPaise, 'input_data'=>$in]); exit;
  }

  // For UAT, we don't need OAuth token, use direct payment creation
  global $MERCHANT_ID, $SALT_KEY, $SALT_INDEX;
  
  // Create payment payload for UAT
  $payload = [
    'merchantId' => $MERCHANT_ID,
    'merchantTransactionId' => $merchantOrderId,
    'merchantUserId' => 'USER_' . time(),
    'amount' => $amountPaise,
    'redirectUrl' => 'https://astro.siddharthnahar.in/phonepe_success.php',
    'redirectMode' => 'POST',
    'callbackUrl' => 'https://astro.siddharthnahar.in/phonepe_success.php',
    'mobileNumber' => $in['customerMobile'] ?? $in['mobileNumber'] ?? '9876543210',
    'paymentInstrument' => [
      'type' => 'PAY_PAGE'
    ]
  ];
  
  // Generate checksum
  $payloadString = json_encode($payload);
  $checksum = generate_checksum($payloadString, '/checkout/v1/pay');
  
  // Create final payment data
  $paymentData = [
    'body' => $payloadString,
    'checksum' => $checksum
  ];
  
  // Debug logging
  error_log("UAT Payment Data: " . json_encode($paymentData));
  
  // Generate PhonePe payment URL directly
  $phonePeUrl = 'https://mercury-t2.phonepe.com/transact/pgv3?token=' . urlencode($paymentData['body']);
  error_log("Generated PhonePe URL: $phonePeUrl");
  
  // Return payment data for SDK
  $response = [
    'success' => true,
    'message' => 'Payment created successfully',
    'data' => [
      'transactionId' => $merchantOrderId,
      'amount' => $amountPaise / 100,
      'paymentData' => $paymentData,
      'redirectUrl' => 'https://astro.siddharthnahar.in/phonepe_success.php',
      'paymentUrl' => $phonePeUrl
    ]
  ];
  
  // Ensure proper JSON encoding
  $jsonResponse = json_encode($response, JSON_PRETTY_PRINT);
  if (json_last_error() !== JSON_ERROR_NONE) {
    error_log("JSON Encoding Error: " . json_last_error_msg());
    http_response_code(500);
    echo json_encode([
      'success' => false,
      'message' => 'Response encoding error: ' . json_last_error_msg()
    ]);
    exit;
  }
  
  echo $jsonResponse;
  exit;
}

// ---------- status ----------
if ($route === '/status' && $_SERVER['REQUEST_METHOD'] === 'POST') {
  // Set JSON header for API response
  header('Content-Type: application/json; charset=utf-8');
  
  $in = json_decode(file_get_contents('php://input'), true) ?: [];
  $orderId = $in['merchantOrderId'] ?? '';
  if ($orderId === '') { http_response_code(400); echo json_encode(['success'=>false,'message'=>'orderId required']); exit; }

  // For UAT, return mock status
  echo json_encode([
    'success' => true,
    'status' => 'PENDING',
    'message' => 'UAT status check - payment pending',
    'orderId' => $orderId
  ]); exit;
}

// ---------- URLs log ----------
if ($route === '/urls' && ($_SERVER['REQUEST_METHOD'] ?? '') === 'GET') {
    $logFile = 'phonepe_urls_log.txt';
    if (file_exists($logFile)) {
        header('Content-Type: text/plain');
        echo file_get_contents($logFile);
    } else {
        header('Content-Type: text/plain');
        echo "No URLs logged yet.\n";
    }
    exit;
}

// ---------- webhook ----------
if ($route === '/webhook') {
  // Set JSON header for API response
  header('Content-Type: application/json; charset=utf-8');
  
  error_log("UAT Webhook called");
  
  // Process webhook data
  $raw = file_get_contents('php://input');
  $webhookData = json_decode($raw, true);
  $transactionId = $webhookData['transactionId'] ?? '';
  $amount = $webhookData['amount'] ?? '';
  $status = $webhookData['status'] ?? '';
  
  error_log("UAT Webhook Data: transactionId=$transactionId, amount=$amount, status=$status");
  
  // Only process successful payments
  if ($status === 'SUCCESS') {
    try {
      // Database connection
      $host = 'localhost';
      $dbname = 'astro_admin';
      $username = 'root';
      $password = '';
      
      $pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $username, $password);
      $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
      
      // Start transaction
      $pdo->beginTransaction();
      
      // Check if already processed
      $stmt = $pdo->prepare("SELECT id FROM phonepe_payments WHERE transaction_id = ? AND status = 'SUCCESS'");
      $stmt->execute([$transactionId]);
      
      if ($stmt->rowCount() > 0) {
        $pdo->rollBack();
        echo json_encode(['success' => false, 'message' => 'Transaction already processed']);
        exit;
      }
      
      // Update payment status
      $stmt = $pdo->prepare("UPDATE phonepe_payments SET status = 'SUCCESS', updated_at = NOW() WHERE transaction_id = ?");
      $stmt->execute([$transactionId]);
      
      // Get payment record
      $stmt = $pdo->prepare("SELECT * FROM phonepe_payments WHERE transaction_id = ?");
      $stmt->execute([$transactionId]);
      $payment = $stmt->fetch(PDO::FETCH_ASSOC);
      
      if ($payment) {
        $userId = $payment['user_id'] ?? 1;
        
        // Add user payment record
        $stmt = $pdo->prepare("
          INSERT INTO user_payments (user_id, payment_id, amount, status, payment_method, transaction_id, created_at) 
          VALUES (?, ?, ?, 'completed', 'phonepe', ?, NOW())
          ON DUPLICATE KEY UPDATE 
          amount = VALUES(amount), 
          status = 'completed', 
          updated_at = NOW()
        ");
        $stmt->execute([$userId, $payment['id'], $amount, $transactionId]);
        
        // Update user to premium
        $stmt = $pdo->prepare("
          UPDATE users 
          SET is_premium = 1, 
              premium_expires_at = DATE_ADD(NOW(), INTERVAL 1 YEAR),
              updated_at = NOW()
          WHERE id = ?
        ");
        $stmt->execute([$userId]);
      }
      
      $pdo->commit();
      
      error_log("UAT Webhook: Payment processed successfully for transaction: $transactionId");
      
      echo json_encode([
        'success' => true,
        'message' => 'Payment processed successfully',
        'data' => [
          'transactionId' => $transactionId,
          'amount' => $amount,
          'status' => $status
        ]
      ]);
      
    } catch (Exception $e) {
      $pdo->rollBack();
      error_log("UAT Webhook Error: " . $e->getMessage());
      echo json_encode(['success' => false, 'message' => 'Webhook processing failed: ' . $e->getMessage()]);
    }
  } else {
    echo json_encode(['success' => false, 'message' => 'Payment not successful']);
  }
  
  exit;
}

// ---------- Default route (for browser testing) ----------
if ($route === '/' && ($_SERVER['REQUEST_METHOD'] ?? '') === 'GET') {
    // Set HTML header for browser interface
    header('Content-Type: text/html; charset=utf-8');
    ?>
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>PhonePe Main Backend Test</title>
        <style>
            body { 
                font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 
                margin: 0; 
                padding: 20px; 
                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                min-height: 100vh;
            }
            .container { 
                max-width: 800px; 
                margin: 0 auto; 
                background: white; 
                padding: 30px; 
                border-radius: 15px; 
                box-shadow: 0 10px 30px rgba(0,0,0,0.2);
            }
            .header { 
                text-align: center; 
                color: #333; 
                margin-bottom: 30px; 
                border-bottom: 2px solid #f0f0f0;
                padding-bottom: 20px;
            }
            .form-group { 
                margin-bottom: 20px; 
            }
            label { 
                display: block; 
                margin-bottom: 8px; 
                font-weight: 600; 
                color: #2c3e50;
                font-size: 14px;
            }
            input, select { 
                width: 100%; 
                padding: 12px 15px; 
                border: 2px solid #e1e8ed; 
                border-radius: 8px; 
                font-size: 16px; 
                transition: all 0.3s ease;
                box-sizing: border-box;
            }
            input:focus, select:focus {
                border-color: #3498db;
                outline: none;
                box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);
            }
            button { 
                background: linear-gradient(45deg, #3498db, #2980b9);
                color: white; 
                padding: 15px 25px; 
                border: none; 
                border-radius: 8px; 
                cursor: pointer; 
                font-size: 16px; 
                font-weight: 600;
                margin-right: 15px; 
                margin-bottom: 10px;
                transition: all 0.3s ease;
                box-shadow: 0 4px 15px rgba(52, 152, 219, 0.3);
            }
            button:hover { 
                background: linear-gradient(45deg, #2980b9, #1f618d);
                transform: translateY(-2px);
                box-shadow: 0 6px 20px rgba(52, 152, 219, 0.4);
            }
            .result { 
                margin-top: 25px; 
                padding: 20px; 
                background: #f8f9fa; 
                border-radius: 10px; 
                border-left: 5px solid #3498db;
                box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            }
            .error { 
                border-left-color: #e74c3c; 
                background: #fdf2f2; 
            }
            .success { 
                border-left-color: #27ae60; 
                background: #f0f9f0; 
            }
            .info {
                border-left-color: #f39c12;
                background: #fefbf0;
            }
            pre { 
                background: #2c3e50; 
                color: #ecf0f1;
                padding: 15px; 
                border-radius: 8px; 
                overflow-x: auto; 
                font-size: 14px;
                margin: 10px 0;
            }
            .url-box { 
                background: #ecf0f1; 
                padding: 15px; 
                border-radius: 8px; 
                word-break: break-all; 
                font-family: 'Courier New', monospace;
                font-size: 14px;
                border: 1px solid #bdc3c7;
                margin: 10px 0;
            }
            .form-row {
                display: flex;
                gap: 15px;
            }
            .form-row .form-group {
                flex: 1;
            }
        .status-badge {
            display: inline-block;
            padding: 5px 12px;
            border-radius: 20px;
            font-size: 12px;
            font-weight: 600;
            text-transform: uppercase;
        }
        .status-pending { background: #fff3cd; color: #856404; }
        .status-success { background: #d4edda; color: #155724; }
        .status-failed { background: #f8d7da; color: #721c24; }
        .detail-row {
            display: flex;
            justify-content: space-between;
            margin-bottom: 10px;
            padding: 8px 0;
            border-bottom: 1px solid #eee;
        }
        .detail-label {
            font-weight: 600;
            color: #2c3e50;
        }
        .detail-value {
            color: #7f8c8d;
        }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="header">
                <h1>🔧 PhonePe Link Generator</h1>
                <p>Generate PhonePe payment links for mobile app</p>
            </div>
            
            <form id="paymentForm">
                <div class="form-row">
                    <div class="form-group">
                        <label for="amount">Amount (₹)</label>
                        <input type="number" id="amount" value="500" min="1" step="0.01" required>
                    </div>
                    <div class="form-group">
                        <label for="mobile">Mobile Number</label>
                        <input type="tel" id="mobile" value="9999999999" required>
                    </div>
                </div>
                
                <div class="form-group">
                    <label for="appointmentId">Appointment ID</label>
                    <input type="number" id="appointmentId" value="1" min="1" required>
                </div>
                
                <button type="button" onclick="generatePaymentLink()">🚀 Generate PhonePe Link</button>
                <button type="button" onclick="clearResults()">🗑️ Clear</button>
            </form>
            
            <div id="result"></div>
        </div>
        
        <script>
            async function generatePaymentLink() {
                const amount = document.getElementById('amount').value;
                const mobile = document.getElementById('mobile').value;
                const appointmentId = document.getElementById('appointmentId').value;
                
                if (!amount || !mobile || !appointmentId) {
                    showResult('<h3>❌ Error</h3><p>Please fill all fields</p>', 'error');
                    return;
                }
                
                const data = {
                    amount: parseFloat(amount),
                    mobile: mobile,
                    appointmentId: parseInt(appointmentId)
                };
                
                showResult('Generating PhonePe payment link...', 'info');
                
                try {
                    const response = await fetch(window.location.pathname + '/createPayment', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                        },
                        body: JSON.stringify(data)
                    });
                    
                    const result = await response.json();
                    
                    if (response.ok && result.success && result.data) {
                        showResult(`
                            <h3>✅ Payment Link Generated Successfully!</h3>
                            <div class="detail-row">
                                <span class="detail-label">Transaction ID:</span>
                                <span class="detail-value">${result.data.transactionId}</span>
                            </div>
                            <div class="detail-row">
                                <span class="detail-label">Amount:</span>
                                <span class="detail-value">₹${result.data.amount}</span>
                            </div>
                            <div class="detail-row">
                                <span class="detail-label">Status:</span>
                                <span class="status-badge status-pending">READY</span>
                            </div>
                            <p><strong>Payment URL:</strong></p>
                            <div class="url-box">${result.data.paymentUrl || result.data.redirectUrl}</div>
                            <br>
                            <button onclick="window.open('${result.data.paymentUrl || result.data.redirectUrl}', '_blank')">🌐 Open Payment Page</button>
                            <button onclick="copyToClipboard('${result.data.paymentUrl || result.data.redirectUrl}')">📋 Copy URL</button>
                            <button onclick="testMobileAppFlow('${result.data.paymentUrl || result.data.redirectUrl}', '${result.data.transactionId}')">📱 Test Mobile App Flow</button>
                        `, 'success');
                    } else {
                        showResult(`
                            <h3>❌ Payment Link Generation Failed</h3>
                            <p><strong>Error:</strong> ${result.message || 'Unknown error'}</p>
                            <pre>${JSON.stringify(result, null, 2)}</pre>
                        `, 'error');
                    }
                } catch (error) {
                    showResult(`
                        <h3>❌ Error</h3>
                        <p>${error.message}</p>
                    `, 'error');
                }
            }
            
            function testMobileAppFlow(paymentUrl, transactionId) {
                showResult(`
                    <h3>📱 Mobile App Flow Test</h3>
                    <p>This simulates what happens in the mobile app:</p>
                    <ol>
                        <li>✅ App calls backend and gets payment URL</li>
                        <li>✅ App opens payment URL in external browser</li>
                        <li>🔄 User completes payment in PhonePe</li>
                        <li>🔄 PhonePe redirects to success/failure page</li>
                        <li>🔄 App polls for payment status</li>
                        <li>🔄 On success, appointment is confirmed</li>
                    </ol>
                    <p><strong>Current Status:</strong> Payment link generated and ready</p>
                    <p><strong>Transaction ID:</strong> ${transactionId}</p>
                    <p><strong>Next Step:</strong> Click "Open Payment Page" to test the full flow</p>
                `, 'info');
            }
            
            function showResult(content, type) {
                const resultDiv = document.getElementById('result');
                resultDiv.innerHTML = content;
                resultDiv.className = `result ${type}`;
            }
            
            function clearResults() {
                document.getElementById('result').innerHTML = '';
                document.getElementById('result').className = 'result';
            }
            
            function copyToClipboard(text) {
                navigator.clipboard.writeText(text).then(() => {
                    alert('URL copied to clipboard!');
                }).catch(err => {
                    console.error('Failed to copy: ', err);
                });
            }
        </script>
    </body>
    </html>
    <?php
  exit;
}

// ---------- Default response for unknown routes ----------
http_response_code(404);
header('Content-Type: application/json; charset=utf-8');
echo json_encode(['error'=>'Endpoint not found']);
?>