<?php
function validateAndFollowUrl($url) {
    $output = [];
    $returnVal = 0;
    
    exec('/usr/bin/python3 fixurl.py ' . escapeshellarg($url) . ' ' . escapeshellarg($ip), $output, $returnVal);
    
    if ($returnVal !== 0) {
        return ['error' => 'URL validation failed'];
    }
    
    $result = json_decode($output[0], true);
    
    if (!$result['success']) {
        return ['error' => $result['error']];
    }
    
    return $result;
}

function validateDomain($domain) {
    return filter_var($domain, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME);
}

function validateIP($ip) {
    return filter_var($ip, FILTER_VALIDATE_IP);
}

function testConfig($configPath) {
    exec('sudo /usr/local/bin/angie-tempurl test 2>&1', $output, $testStatus);
    error_log("Angie config test output: " . implode("\n", $output));
    
    if ($testStatus !== 0) {
        if (file_exists($configPath)) {
            unlink($configPath);
        }
        error_log("Angie config test failed for $configPath");
        return false;
    }
    return true;
}

function reloadAngie() {
    exec('sudo /usr/local/bin/angie-tempurl reload 2>&1', $output, $reloadStatus);
    error_log("Angie reload output: " . implode("\n", $output));
    
    if ($reloadStatus !== 0) {
        error_log("Angie reload failed");
        return false;
    }
    return true;
}

function checkRateLimit($ip, $limit = 10, $period = 600) {
    $rateFile = sys_get_temp_dir() . "/ratelimit_" . md5($ip);
    
    if (file_exists($rateFile)) {
        $data = json_decode(file_get_contents($rateFile), true);
        if (time() - $data['start'] > $period) {
            $data = ['count' => 1, 'start' => time()];
        } else if ($data['count'] >= $limit) {
            return false;
        } else {
            $data['count']++;
        }
    } else {
        $data = ['count' => 1, 'start' => time()];
    }
    
    file_put_contents($rateFile, json_encode($data));
    return true;
}

$domain = $_POST['domain'] ?? $_GET['domain'] ?? '';
$ip = $_POST['ip'] ?? $_GET['ip'] ?? '';
$response = '';

if (!empty($domain) && !empty($ip)) {
    if (!checkRateLimit($_SERVER['REMOTE_ADDR'])) {
        $response = "Rate limit exceeded. Please try again later.";
        if ($_SERVER["REQUEST_METHOD"] == "POST") {
            echo $response;
            exit;
        }
    }
    
    if (validateDomain($domain) && validateIP($ip)) {
        $urlResponse = validateAndFollowUrl($domain);
        if (isset($urlResponse['error'])) {
            $response = "URL error: " . $urlResponse['error'];
        } else {
            $finalDomain = $urlResponse['final_domain'];
            $tempUrl = $urlResponse['temp_url'];
            $needsSpecialHandling = $urlResponse['needs_special_handling'] ?? false;

            if ($needsSpecialHandling) {
                $configTemplate = <<<CONFIG
server {
    listen 443 ssl;
    server_name {$tempUrl};

    ssl_certificate /home/nginx/ssl/angie.crt;
    ssl_certificate_key /home/nginx/ssl/angie.key;

    large_client_header_buffers 4 32k;
    client_header_buffer_size 16k;
    proxy_buffer_size 16k;
    proxy_buffers 8 16k;
    proxy_busy_buffers_size 32k;

    location / {
        add_header X-Robots-Tag "noindex, nofollow";
        proxy_pass http://{$ip};
        proxy_buffering on;
        proxy_buffers 16 4k;
        proxy_set_header Host {$finalDomain};
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-Port 443;
        proxy_set_header X-Forwarded-Ssl on;
        proxy_ssl_verify off;
        proxy_ssl_server_name on;
        proxy_set_header Accept-Encoding "";
        proxy_redirect ~^http://(.*)$ https://{$tempUrl};
        proxy_redirect ~^https://(.*)$ https://{$tempUrl};
    }
    
    sub_filter '{$finalDomain}' '{$tempUrl}';
    sub_filter_once off;
    sub_filter_types *;
}
CONFIG;
            } else {
                $configTemplate = <<<CONFIG
server {
    listen 443 ssl;
    server_name {$tempUrl};

    ssl_certificate /home/nginx/ssl/angie.crt;
    ssl_certificate_key /home/nginx/ssl/angie.key;

    large_client_header_buffers 4 32k;
    client_header_buffer_size 16k;
    proxy_buffer_size 16k;
    proxy_buffers 8 16k;
    proxy_busy_buffers_size 32k;

    location / {
        add_header X-Robots-Tag "noindex, nofollow";
        proxy_pass https://{$ip};
        proxy_buffering on;
        proxy_buffers 16 4k;
        proxy_set_header Host {$finalDomain};
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto \$scheme;
        proxy_ssl_verify off;
        proxy_ssl_server_name on;
        proxy_set_header Accept-Encoding "";
        proxy_redirect https://{$finalDomain} https://{$tempUrl};
    }
    
    sub_filter '{$finalDomain}' '{$tempUrl}';
    sub_filter_once off;
    sub_filter_types *;
}
CONFIG;
            }

            $configPath = "/home/nginx/tempurl/{$tempUrl}.conf";

            if (file_put_contents($configPath, $configTemplate) === false) {
                $response = "Failed to write configuration file.";
            } else {
                if (!testConfig($configPath)) {
                    $response = "No. Try again.";
                } else {
                    if (!reloadAngie()) {
                        unlink($configPath);
                        $response = "Failed to reload Angie configuration.";
                    } else {
                        if ($_SERVER['REQUEST_METHOD'] === 'GET' && !empty($_GET['domain']) && !empty($_GET['ip'])) {
                            if (strpos($_SERVER['HTTP_USER_AGENT'], 'curl') !== false) {
                                echo "https://{$tempUrl}\n";
                                exit;
                            } else {
                                header("Location: https://{$tempUrl}");
                                exit;
                            }
                        }
                        $response = "<a href='https://{$tempUrl}' target='_blank'>https://{$tempUrl}</a>";
                    }
                }
            }
        }
    } else {
        $response = "Invalid domain or IP. Please provide a valid domain and IP address.";
    }
} else if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $response = "Please provide both domain and IP address.";
}

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    echo $response;
    exit;
}
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Create a temporary URL</title>
    <meta name="description" content="Create a temporary URL with tempurl.cc for easy DNS testing. Simplify your web development and troubleshooting with fast and secure temporary URLs.">
    <link rel="icon" type="image/x-icon" href="favicon.png">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous">
    <style>
        :root {
            --bg: #f5f5f4;
            --card: #ffffff;
            --text: #1f2937;
            --text-muted: #6b7280;
            --text-faint: #9ca3af;
            --border: #e5e7eb;
            --border-hover: #d1d5db;
            --primary: #1f2937;
            --primary-hover: #0f172a;
            --primary-disabled: #94a3b8;
            --success-bg: #e1f5ee;
            --success-text: #0f6e56;
            --success-border: rgba(15,110,86,0.25);
            --warn-bg: #faeeda;
            --warn-text: #854f0b;
            --warn-border: rgba(133,79,11,0.25);
            --error-bg: #fceaea;
            --error-text: #a32d2d;
            --code-bg: #f1efe8;
        }

        * { box-sizing: border-box; }

        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
            background-color: var(--bg);
            color: var(--text);
            margin: 0;
            min-height: 100vh;
            padding: 40px 16px 24px;
        }

        .container {
            background-color: var(--card);
            padding: 32px 36px;
            border-radius: 12px;
            border: 1px solid var(--border);
            max-width: 640px;
            margin: 0 auto;
        }

        .brand {
            display: flex;
            align-items: center;
            gap: 10px;
            margin-bottom: 6px;
        }

        .brand-icon {
            width: 32px;
            height: 32px;
            border-radius: 8px;
            background: var(--primary);
            color: #fff;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 16px;
        }

        .brand-name {
            font-size: 13px;
            font-weight: 600;
            letter-spacing: 0.5px;
            color: var(--text-muted);
        }

        h1 {
            font-size: 22px;
            font-weight: 600;
            margin: 0 0 4px 0;
            color: var(--text);
        }

        .subtitle {
            font-size: 14px;
            color: var(--text-muted);
            margin: 0 0 24px 0;
            line-height: 1.5;
        }

        form {
            display: flex;
            flex-direction: column;
            gap: 14px;
        }

        .field label {
            display: block;
            font-size: 13px;
            font-weight: 500;
            color: var(--text-muted);
            margin-bottom: 6px;
        }

        .input-wrap {
            position: relative;
        }

        .input-wrap i {
            position: absolute;
            left: 12px;
            top: 50%;
            transform: translateY(-50%);
            font-size: 14px;
            color: var(--text-faint);
        }

        input[type="text"] {
            width: 100%;
            padding: 10px 12px 10px 36px;
            border: 1px solid var(--border);
            border-radius: 8px;
            background: var(--card);
            font-family: inherit;
            font-size: 14px;
            color: var(--text);
            transition: border-color 0.15s ease, box-shadow 0.15s ease;
        }

        input[type="text"]:hover {
            border-color: var(--border-hover);
        }

        input[type="text"]:focus {
            outline: none;
            border-color: var(--primary);
            box-shadow: 0 0 0 3px rgba(31,41,55,0.12);
        }

        input[type="submit"] {
            background: var(--primary);
            color: #fff;
            border: none;
            padding: 11px 14px;
            border-radius: 8px;
            font-family: inherit;
            font-size: 14px;
            font-weight: 500;
            cursor: pointer;
            margin-top: 6px;
            transition: background 0.15s ease, opacity 0.15s ease;
        }

        input[type="submit"]:hover:not(:disabled) {
            background: var(--primary-hover);
        }

        input[type="submit"]:disabled {
            background: var(--primary-disabled);
            cursor: not-allowed;
        }

        #loading {
            display: none;
            margin-top: 18px;
            font-size: 14px;
            color: var(--text-muted);
            text-align: center;
        }

        #loading img {
            display: block;
            margin: 8px auto 0;
        }

        #output {
            margin-top: 18px;
        }

        #output:empty {
            display: none;
        }

        /* Result block (server returns an <a> tag, we wrap & restyle) */
        .result {
            padding: 12px 14px;
            background: var(--success-bg);
            border: 1px solid var(--success-border);
            border-radius: 8px;
            display: flex;
            align-items: center;
            gap: 10px;
        }

        .result i.result-icon {
            font-size: 16px;
            color: var(--success-text);
            flex-shrink: 0;
        }

        .result a {
            color: var(--success-text);
            font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
            font-size: 13px;
            text-decoration: none;
            flex: 1;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        .result a:hover {
            text-decoration: underline;
        }

        #copyIcon {
            cursor: pointer;
            background: transparent;
            border: 1px solid var(--success-border);
            padding: 5px 10px;
            border-radius: 6px;
            font-size: 12px;
            font-weight: 500;
            color: var(--success-text);
            display: inline-flex;
            align-items: center;
            gap: 5px;
            width: auto;
            height: auto;
            transition: background 0.15s ease;
            flex-shrink: 0;
        }

        #copyIcon:hover {
            background: rgba(15,110,86,0.08);
        }

        /* Cooldown / spam message */
        .cooldown {
            padding: 11px 14px;
            background: var(--warn-bg);
            border: 1px solid var(--warn-border);
            border-radius: 8px;
            display: flex;
            align-items: center;
            gap: 10px;
            font-size: 13px;
            color: var(--warn-text);
        }

        .cooldown i {
            font-size: 16px;
            flex-shrink: 0;
        }

        .cooldown strong {
            font-weight: 600;
        }

        .cooldown .countdown-num {
            font-weight: 600;
            font-variant-numeric: tabular-nums;
        }

        /* Error message */
        .error-msg {
            padding: 11px 14px;
            background: var(--error-bg);
            border-radius: 8px;
            color: var(--error-text);
            font-size: 13px;
        }

        /* Terminal hint */
        .terminal-hint {
            margin-top: 24px;
            padding-top: 20px;
            border-top: 1px solid var(--border);
        }

        .terminal-hint-label {
            display: flex;
            align-items: center;
            gap: 6px;
            font-size: 12px;
            font-weight: 500;
            color: var(--text-muted);
            margin-bottom: 8px;
        }

        .terminal-hint pre {
            margin: 0;
            padding: 10px 12px;
            background: var(--code-bg);
            border-radius: 8px;
            font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
            font-size: 12px;
            color: var(--text);
            line-height: 1.5;
            white-space: pre-wrap;
            word-break: break-all;
        }

        /* Footer note */
        .note {
            text-align: center;
            font-size: 13px;
            color: var(--text-muted);
            line-height: 1.6;
            margin-top: 20px;
            padding: 0 16px;
        }

        .note .row {
            display: inline-flex;
            align-items: center;
            gap: 6px;
        }

        .note .warning-text {
            font-size: 12px;
            color: var(--text-faint);
            display: block;
            margin-top: 4px;
        }

        .note .heart {
            color: #d85a30;
        }

        @media (max-width: 480px) {
            body { padding: 24px 12px; }
            .container { padding: 24px 20px; }
            h1 { font-size: 20px; }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="brand">
            <div class="brand-icon"><i class="fa-solid fa-link" aria-hidden="true"></i></div>
            <span class="brand-name">TEMPURL.CC</span>
        </div>
        <h1>Create a temporary URL</h1>
        <p class="subtitle">Spin up a temporary HTTPS URL pointed at any backend. Good for DNS testing and migrations.</p>

        <form id="tempUrlForm">
            <div class="field">
                <label for="domain">Domain</label>
                <div class="input-wrap">
                    <i class="fa-solid fa-globe" aria-hidden="true"></i>
                    <input type="text" id="domain" name="domain" placeholder="example.com" required>
                </div>
            </div>
            <div class="field">
                <label for="ip">Server IP</label>
                <div class="input-wrap">
                    <i class="fa-solid fa-server" aria-hidden="true"></i>
                    <input type="text" id="ip" name="ip" placeholder="192.0.2.42" required>
                </div>
            </div>
            <input type="submit" value="Create temp URL">
        </form>

        <div id="loading">Doin' Math... Please wait.<br><img src="loading.gif"></div>
        <div id="output"><?php echo $response; ?></div>

        <div class="terminal-hint">
            <div class="terminal-hint-label">
                <i class="fa-solid fa-terminal" aria-hidden="true"></i>
                <span>Or from your terminal</span>
            </div>
            <pre>curl "https://tempurl.cc/?domain=example.com&amp;ip=192.0.2.42"</pre>
        </div>
    </div>

    <div class="note">
        <span class="row"><i class="fa-regular fa-clock" aria-hidden="true"></i> All temporary links expire after 72 hours</span>
        <span class="warning-text">Free service, no abuse will be tolerated. <span class="heart">&#10084;</span> -Les</span>
    </div>

    <script>
        const COOLDOWN_MS = 10000;
        let cooldownUntil = 0;
        let cooldownIntervalId = null;
        const submitBtn = document.getElementById('tempUrlForm').querySelector('input[type="submit"]');

        function showLoading() {
            document.getElementById('loading').style.display = 'block';
            document.getElementById('output').innerHTML = '';
        }

        function clearCooldownInterval() {
            if (cooldownIntervalId !== null) {
                clearInterval(cooldownIntervalId);
                cooldownIntervalId = null;
            }
        }

        function showCooldownMessage() {
            const outputDiv = document.getElementById('output');
            const secondsLeft = Math.max(0, Math.ceil((cooldownUntil - Date.now()) / 1000));

            outputDiv.innerHTML =
                '<div class="cooldown">' +
                    '<i class="fa-solid fa-clock" aria-hidden="true"></i>' +
                    '<div style="flex:1;">' +
                        '<strong>Slow down. No spamming the form.</strong> ' +
                        '<span>You can try again in <span class="countdown-num" id="cooldownNum">' + secondsLeft + 's</span>.</span>' +
                    '</div>' +
                '</div>';

            clearCooldownInterval();
            cooldownIntervalId = setInterval(() => {
                const s = Math.max(0, Math.ceil((cooldownUntil - Date.now()) / 1000));
                const numEl = document.getElementById('cooldownNum');
                if (numEl) numEl.textContent = s + 's';
                if (s <= 0) {
                    clearCooldownInterval();
                    if (outputDiv.querySelector('.cooldown')) {
                        outputDiv.innerHTML = '';
                    }
                }
            }, 250);
        }

        function startCooldown() {
            cooldownUntil = Date.now() + COOLDOWN_MS;
            submitBtn.disabled = true;
            setTimeout(() => {
                submitBtn.disabled = false;
            }, COOLDOWN_MS);
        }

        function renderServerResponse(data) {
            const outputDiv = document.getElementById('output');
            const trimmed = (data || '').trim();
            // If the server returned an anchor tag (success), wrap it in the styled result block
            if (/^<a\s/i.test(trimmed)) {
                outputDiv.innerHTML =
                    '<div class="result">' +
                        '<i class="fa-solid fa-circle-check result-icon" aria-hidden="true"></i>' +
                        trimmed +
                        '<button id="copyIcon" type="button" title="Copy URL" onclick="copyToClipboard()">' +
                            '<i class="fa-solid fa-clipboard" aria-hidden="true"></i>Copy' +
                        '</button>' +
                    '</div>';
            } else {
                // Error / validation / rate-limit message from the server
                outputDiv.innerHTML = '<div class="error-msg">' + trimmed + '</div>';
            }
        }

        function handleFormSubmit(event) {
            event.preventDefault();

            // If we're inside the cooldown window, show the message and bail. No fetch.
            if (Date.now() < cooldownUntil) {
                showCooldownMessage();
                return;
            }

            clearCooldownInterval();
            showLoading();

            const formData = new FormData(event.target);

            fetch('/', {
                method: 'POST',
                body: formData
            })
            .then(response => response.text())
            .then(data => {
                document.getElementById('loading').style.display = 'none';
                renderServerResponse(data);
                startCooldown();
            })
            .catch(error => {
                console.error('Error:', error);
                document.getElementById('loading').style.display = 'none';
                document.getElementById('output').innerHTML =
                    '<div class="error-msg">An error occurred: ' + error.message + '</div>';
            });
        }

        function copyToClipboard() {
            const anchor = document.getElementById('output').querySelector('a');
            if (!anchor) return;
            const url = anchor.href;
            navigator.clipboard.writeText(url)
                .then(() => {
                    const btn = document.getElementById('copyIcon');
                    if (btn) {
                        btn.innerHTML = '<i class="fa-solid fa-check" aria-hidden="true"></i>Copied';
                        btn.style.color = '#0f6e56';
                    }
                })
                .catch(error => {
                    console.error('Failed to copy URL:', error);
                });
        }

        document.getElementById('tempUrlForm').addEventListener('submit', handleFormSubmit);
    </script>
</body>
</html>
