<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Security Check - Nginx Proxy Guard</title>
    <link rel="icon" type="image/x-icon" href="/favicon.ico">
    <script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
    <style>
        * { box-sizing: border-box; margin: 0; padding: 0; }
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
            background: #f8fafc;
            color: #1e293b;
            min-height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 20px;
        }
        .container {
            background: #ffffff;
            border-radius: 16px;
            padding: 40px;
            max-width: 480px;
            width: 100%;
            text-align: center;
            box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
        }
        .logo {
            width: 80px;
            height: 80px;
            margin: 0 auto 24px;
        }
        .logo img { width: 100%; height: 100%; object-fit: contain; }
        .brand { font-size: 0.75rem; color: #64748b; margin-bottom: 20px; letter-spacing: 0.5px; }
        h1 { font-size: 1.5rem; margin-bottom: 12px; font-weight: 600; }
        p.message { color: #64748b; margin-bottom: 28px; line-height: 1.6; font-size: 0.95rem; }
        .g-recaptcha, .cf-turnstile { display: inline-block; margin-bottom: 20px; }
        #recaptcha-v3-notice { padding: 16px; background: #f1f5f9; border-radius: 8px; margin-bottom: 20px; color: #64748b; }
        .error { color: #ef4444; margin-top: 12px; display: none; font-size: 0.9rem; }
        .success { color: #22c55e; margin-top: 12px; display: none; font-size: 0.9rem; }
        .manual-link { display: none; margin-top: 16px; }
        .manual-link a { color: #3b82f6; text-decoration: underline; font-size: 0.9rem; }
        .loading { display: none; margin-top: 12px; }
        .spinner {
            border: 3px solid #f3f3f3;
            border-top: 3px solid #3b82f6;
            border-radius: 50%;
            width: 24px;
            height: 24px;
            animation: spin 1s linear infinite;
            margin: 0 auto;
        }
        @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
        .footer { margin-top: 28px; font-size: 0.8rem; color: #64748b; line-height: 1.5; }
        .lang-switch { margin-top: 16px; }
        .lang-switch button {
            background: transparent;
            border: 1px solid #e2e8f0;
            color: #64748b;
            padding: 4px 12px;
            border-radius: 6px;
            cursor: pointer;
            font-size: 0.75rem;
            margin: 0 4px;
            transition: all 0.2s;
        }
        .lang-switch button:hover { background: #f1f5f9; }
        .lang-switch button.active { background: #3b82f6; color: white; border-color: #3b82f6; }
    </style>
</head>
<body>
    <div class="container">
        <div class="logo">
            <img src="/api/v1/challenge/favicon.ico" alt="Nginx Proxy Guard">
        </div>
        <div class="brand">NGINX PROXY GUARD</div>
        <h1 id="title">Security Check</h1>
        <p class="message" id="message">Please complete the security check to continue.</p>

        <div class="cf-turnstile" data-sitekey="0x4AAAAAACFVM7OrmQyrGYRn" data-theme="light" data-callback="onCaptchaSuccess"></div>

        <div class="loading"><div class="spinner"></div></div>
        <div class="error" id="error"></div>
        <div class="success" id="success"></div>
        <div class="manual-link" id="manual-link"><a id="manual-link-a" href="/"></a></div>

        <div class="footer">
            <span id="footer-text"></span>
        </div>

        <div class="lang-switch">
            <button onclick="setLang('ko')" id="lang-ko">한국어</button>
            <button onclick="setLang('en')" id="lang-en">English</button>
        </div>
    </div>

    <script>
        const proxyHostId = '7e4a9b79-408f-4ed9-bdf4-02376d556332';
        const reason = 'geo_restriction';
        const challengeType = 'turnstile';

        // i18n translations
        const i18n = {
            ko: {
                title: '보안 확인',
                message: '계속하려면 아래 보안 확인을 완료해주세요.',
                verifying: '확인 중...',
                success: '인증 완료! 이동 중...',
                error: '인증에 실패했습니다. 다시 시도해주세요.',
                networkError: '서버에 연결할 수 없습니다. 잠시 후 다시 시도해주세요.',
                footer: '이 보안 확인은 자동화된 접근으로부터 보호합니다.',
                manualRedirect: '자동 이동되지 않으면 여기를 클릭하세요'
            },
            en: {
                title: 'Security Check',
                message: 'Please complete the security check below to continue.',
                verifying: 'Verifying...',
                success: 'Verified! Redirecting...',
                error: 'Verification failed. Please try again.',
                networkError: 'Cannot reach the server. Please try again in a moment.',
                footer: 'This security check helps protect against automated access.',
                manualRedirect: 'Click here if you are not redirected automatically'
            }
        };

        // Admin-configured global default ('auto' | 'ko' | 'en'), injected by the server.
        const adminDefaultLang = 'auto';

        // Resolve language using the same priority as /403.html:
        //   1. Visitor's explicit click (localStorage)
        //   2. Admin-configured global default (if not 'auto')
        //   3. Browser language, with English fallback for unsupported locales
        function detectLang() {
            // UI Settings writes 'npg_language'; legacy 'npg_lang' kept for back-compat
            const saved = localStorage.getItem('npg_language') || localStorage.getItem('npg_lang');
            if (saved && i18n[saved]) return saved;
            if (i18n[adminDefaultLang]) return adminDefaultLang;
            const browserLang = navigator.language.split('-')[0];
            return i18n[browserLang] ? browserLang : 'en';
        }

        let currentLang = detectLang();

        function setLang(lang) {
            currentLang = lang;
            localStorage.setItem('npg_language', lang);
            document.documentElement.lang = lang;
            updateTexts();
            document.querySelectorAll('.lang-switch button').forEach(btn => btn.classList.remove('active'));
            document.getElementById('lang-' + lang).classList.add('active');
        }

        function t(key) {
            return i18n[currentLang][key] || i18n['en'][key] || key;
        }

        function updateTexts() {
            document.getElementById('title').textContent = t('title');
            document.getElementById('message').textContent = t('message');
            document.getElementById('footer-text').textContent = t('footer');
            document.getElementById('success').textContent = t('success');
            const v3Notice = document.getElementById('recaptcha-v3-notice');
            if (v3Notice) v3Notice.textContent = t('verifying');
        }

        // Initialize
        document.documentElement.lang = currentLang;
        updateTexts();
        document.getElementById('lang-' + currentLang).classList.add('active');

        function showError(msg) {
            document.getElementById('error').textContent = msg || t('error');
            document.getElementById('error').style.display = 'block';
            document.querySelector('.loading').style.display = 'none';
        }

        function showSuccess() {
            document.getElementById('success').textContent = t('success');
            document.getElementById('success').style.display = 'block';
            document.querySelector('.loading').style.display = 'none';
        }

        function showLoading() {
            document.querySelector('.loading').style.display = 'block';
            document.getElementById('error').style.display = 'none';
        }

        function getReturnUrl() {
            const search = window.location.search;
            const returnIdx = search.indexOf('return=');
            let url = returnIdx !== -1 ? search.substring(returnIdx + 7) : '/';
            try { url = decodeURIComponent(url); } catch(e) {}
            return url;
        }

        // Form-based verification: submits a real HTML form POST so the server
        // sets the cookie via Set-Cookie header and redirects with 302.
        // This is used as the primary method because it:
        //   1. Works even when browser extensions block fetch() requests
        //   2. Avoids race conditions between fetch and form fallback
        //   3. Lets the server handle cookie + redirect atomically
        function formVerify(token) {
            const form = document.createElement('form');
            form.method = 'POST';
            form.action = '/api/v1/challenge/verify-redirect';
            const fields = {
                token: token,
                proxy_host_id: proxyHostId,
                challenge_reason: reason,
                return_url: getReturnUrl()
            };
            for (const [k, v] of Object.entries(fields)) {
                const input = document.createElement('input');
                input.type = 'hidden';
                input.name = k;
                input.value = v;
                form.appendChild(input);
            }
            document.body.appendChild(form);
            form.submit();
        }

        // Prevent double-submission from CAPTCHA callbacks
        let isVerifying = false;

        function verifyCaptcha(token) {
            if (isVerifying) return;
            isVerifying = true;
            showLoading();
            // Use form POST as the sole verification method.
            // Previous approach tried fetch() first and fell back to form POST,
            // but this caused a race condition: if fetch reached the server and
            // consumed the CAPTCHA token, the form fallback would fail because
            // CAPTCHA providers reject already-used tokens.
            formVerify(token);
        }

        function onCaptchaSuccess(token) {
            verifyCaptcha(token);
        }

        if (challengeType === 'recaptcha_v3') {
            grecaptcha.ready(function() {
                grecaptcha.execute('0x4AAAAAACFVM7OrmQyrGYRn', {action: 'challenge'}).then(function(token) {
                    verifyCaptcha(token);
                });
            });
        }
    </script>
</body>
</html>