<?php
declare(strict_types=1);

/**
 * Standalone pump.fun reverse proxy.
 * Upload to any PHP host, point any domain at it — shows pump.fun.
 * No nginx middleman needed.
 */

$requestUriRaw = $_SERVER['REQUEST_URI'] ?? '/';
$requestPath   = parse_url($requestUriRaw, PHP_URL_PATH) ?? '/';
$requestQuery  = parse_url($requestUriRaw, PHP_URL_QUERY);

if ($requestPath === '/index.php' || $requestPath === '/index.html') {
    $requestPath = '/';
}

$requestUri = $requestPath;
if ($requestQuery !== null && $requestQuery !== '') {
    $requestUri .= '?' . $requestQuery;
}

$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
$cookieDomain = preg_replace('/:\d+$/', '', $host) ?? $host;
$isHttps = (
    (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
    || (($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https')
);
$scheme       = $isHttps ? 'https' : 'http';
$publicOrigin = $scheme . '://' . $host;

// ── Route map: path prefix → [upstream_base, upstream_host] ──
$routes = [
    '/api-pump/'       => ['https://frontend-api-v3.pump.fun/',        'frontend-api-v3.pump.fun'],
    '/swap-api/'       => ['https://swap-api.pump.fun/',               'swap-api.pump.fun'],
    '/chat-api/'       => ['https://chat-api-v1.pump.fun/',            'chat-api-v1.pump.fun'],
    '/advanced-api/'   => ['https://advanced-api-v2.pump.fun/',        'advanced-api-v2.pump.fun'],
    '/livestream-api/' => ['https://livestream-api.pump.fun/',         'livestream-api.pump.fun'],
    '/helius-rpc/'     => ['https://pump-fe.helius-rpc.com/',          'pump-fe.helius-rpc.com'],
];

// ── WebSocket redirects (PHP can't hold WS, redirect client directly) ──
$wsRedirects = [
    '/nats-realtime' => 'wss://prod-v2.nats.realtime.pump.fun',
    '/helius-ws'     => 'wss://pump-fe.helius-rpc.com',
];

foreach ($wsRedirects as $prefix => $wsTarget) {
    if ($requestPath === $prefix || strpos($requestPath, $prefix . '/') === 0) {
        $suffix = substr($requestUri, strlen($prefix));
        header('Location: ' . $wsTarget . $suffix, true, 307);
        exit;
    }
}

// ── Determine upstream URL and host ──
$upstreamUrl  = null;
$upstreamHost = null;
$matchedPrefix = null;

foreach ($routes as $prefix => [$base, $hostName]) {
    if (strpos($requestPath, $prefix) === 0) {
        $suffix       = substr($requestUri, strlen($prefix));
        $upstreamUrl  = $base . $suffix;
        $upstreamHost = $hostName;
        $matchedPrefix = $prefix;
        break;
    }
}

// Default: proxy everything else to pump.fun
if ($upstreamUrl === null) {
    $upstreamUrl  = 'https://pump.fun' . $requestUri;
    $upstreamHost = 'pump.fun';
}

// ── Stub: Cloudflare RUM endpoint ──
if ($requestPath === '/cdn-cgi/rum') {
    http_response_code(204);
    exit;
}

// ── Build request headers ──
$requestMethod = $_SERVER['REQUEST_METHOD'] ?? 'GET';
$headers = [];
$incomingHeaders = function_exists('getallheaders') ? getallheaders() : [];

foreach ($incomingHeaders as $name => $value) {
    $lower = strtolower($name);
    if (in_array($lower, ['host', 'connection', 'content-length', 'origin', 'referer', 'accept-encoding'], true)) {
        continue;
    }
    $headers[] = $name . ': ' . $value;
}

$headers[] = 'Host: ' . $upstreamHost;
$headers[] = 'Origin: https://pump.fun';
$headers[] = 'Referer: https://pump.fun/';
$headers[] = 'Accept-Encoding: ';  // force uncompressed so we can rewrite
$headers[] = 'X-Forwarded-For: ' . ($_SERVER['REMOTE_ADDR'] ?? '');
$headers[] = 'X-Forwarded-Proto: https';

// ── cURL request ──
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $upstreamUrl);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $requestMethod);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_ENCODING, '');
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$body = file_get_contents('php://input');
if ($body !== false && $body !== '') {
    curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
}

$response = curl_exec($ch);
if ($response === false) {
    http_response_code(502);
    header('Content-Type: text/plain; charset=utf-8');
    echo 'Proxy Error: ' . curl_error($ch);
    curl_close($ch);
    exit;
}

$headerSize = (int) curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$httpCode   = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$responseHeadersRaw = substr($response, 0, $headerSize);
$responseBody       = substr($response, $headerSize);
$responseHeaders    = explode("\r\n", $responseHeadersRaw);

// ── Forward response headers ──
$isRewritable = false;
foreach ($responseHeaders as $headerLine) {
    if ($headerLine === '' || stripos($headerLine, 'HTTP/') === 0) {
        continue;
    }
    $lower = strtolower($headerLine);

    // Skip hop-by-hop and encoding headers (we decompress ourselves)
    if (
        strpos($lower, 'transfer-encoding:') === 0
        || strpos($lower, 'content-length:') === 0
        || strpos($lower, 'content-encoding:') === 0
        || strpos($lower, 'content-security-policy') === 0
    ) {
        continue;
    }

    // Rewrite Location header
    if (strpos($lower, 'location:') === 0) {
        $headerLine = str_replace(
            ['https://pump.fun', 'http://pump.fun', 'https://www.pump.fun', 'http://www.pump.fun'],
            [$publicOrigin, $publicOrigin, $publicOrigin, $publicOrigin],
            $headerLine
        );
    }

    // Rewrite cookie domain
    if (strpos($lower, 'set-cookie:') === 0) {
        $headerLine = preg_replace('/\bdomain=([^;]*pump\.fun[^;]*)/i', 'domain=' . $cookieDomain, $headerLine) ?? $headerLine;
    }

    // Detect rewritable content types
    if (strpos($lower, 'content-type:') === 0) {
        $isRewritable = (
            stripos($headerLine, 'text/html') !== false
            || stripos($headerLine, 'application/javascript') !== false
            || stripos($headerLine, 'text/javascript') !== false
            || stripos($headerLine, 'application/json') !== false
            || stripos($headerLine, 'text/css') !== false
            || stripos($headerLine, 'text/plain') !== false
            || stripos($headerLine, 'text/xml') !== false
        );
    }

    header($headerLine, false);
}

http_response_code($httpCode);

// Custom CSP that allows our domain
header('Content-Security-Policy: ' .
    "default-src 'self'; " .
    "connect-src 'self' https://{$host} wss://{$host} https://frontend-api-v3.pump.fun https://region1.google-analytics.com https://www.google-analytics.com https://*.google-analytics.com https://region1.analytics.google.com https://auth.privy.io https://*.helius-rpc.com https://api-iam.intercom.io https://pump.mypinata.cloud https://ipfs.io https://gateway.pinata.cloud https://explorer-api.walletconnect.com wss://prod-v2.nats.realtime.pump.fun wss://pump-fe.helius-rpc.com wss:; " .
    "img-src 'self' data: https:; " .
    "frame-src 'self' https://auth.privy.io blob: https://www.google.com; " .
    "frame-ancestors 'self' https://{$host} https://auth.privy.io; " .
    "script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; " .
    "style-src 'self' 'unsafe-inline' https:;"
);

if ($isHttps) {
    header('Strict-Transport-Security: max-age=31536000; includeSubDomains; preload');
}

// ── URL rewrites in response body ──
if ($isRewritable && $responseBody !== '') {
    $rewrites = [
        // API endpoints → our proxy paths
        'https://frontend-api-v3.pump.fun'      => $publicOrigin . '/api-pump',
        'http://frontend-api-v3.pump.fun'       => $publicOrigin . '/api-pump',
        'https://swap-api.pump.fun/'            => $publicOrigin . '/swap-api/',
        'https://swap-api.pump.fun'             => $publicOrigin . '/swap-api',
        'https://chat-api-v1.pump.fun/'         => $publicOrigin . '/chat-api/',
        'https://chat-api-v1.pump.fun'          => $publicOrigin . '/chat-api',
        'https://advanced-api-v2.pump.fun/'     => $publicOrigin . '/advanced-api/',
        'https://advanced-api-v2.pump.fun'      => $publicOrigin . '/advanced-api',
        'https://livestream-api.pump.fun/'      => $publicOrigin . '/livestream-api/',
        'https://livestream-api.pump.fun'       => $publicOrigin . '/livestream-api',
        // Helius
        'wss://pump-fe.helius-rpc.com/'         => 'wss://' . $host . '/helius-ws/',
        'https://pump-fe.helius-rpc.com/'       => $publicOrigin . '/helius-rpc/',
        // NATS realtime
        'wss://prod-v2.nats.realtime.pump.fun'  => 'wss://' . $host . '/nats-realtime',
        'https://prod-v2.nats.realtime.pump.fun' => $publicOrigin . '/nats-realtime',
        // Main domain last (so specific subdomains match first)
        'https://pump.fun'                      => $publicOrigin,
        'http://pump.fun'                       => $publicOrigin,
        'https://www.pump.fun'                  => $publicOrigin,
        'http://www.pump.fun'                   => $publicOrigin,
    ];

    // Also handle JS-escaped URLs (\/  instead of  /)
    $escaped = [];
    foreach ($rewrites as $from => $to) {
        $ef = str_replace('/', '\\/', $from);
        $et = str_replace('/', '\\/', $to);
        if ($ef !== $from) {
            $escaped[$ef] = $et;
        }
    }

    $all = $rewrites + $escaped;
    $responseBody = str_replace(array_keys($all), array_values($all), $responseBody);
}

echo $responseBody;
