{% extends "admin/base.html" %}

{% block title %}Settings - Auth MCP Admin{% endblock %}

{% block content %}
<div x-data="settingsManager()">
    <!-- Header -->
    <div class="flex items-center justify-between mb-8">
        <div>
            <h1 class="text-3xl font-bold text-gray-900 flex items-center gap-3">
                <i data-lucide="settings" class="w-8 h-8 text-blue-600"></i>
                Settings
            </h1>
            <p class="text-gray-600 mt-1">Configure system settings and policies</p>
        </div>
    </div>

    <!-- Success Alert -->
    <div x-show="showSuccess" x-cloak
         class="mb-6 p-4 bg-green-50 border-l-4 border-green-500 text-green-800 rounded-lg flex items-center gap-2">
        <i data-lucide="check-circle" class="w-5 h-5"></i>
        <span>Settings saved successfully!</span>
    </div>

    <!-- Error Alert -->
    <div x-show="showError" x-cloak
         class="mb-6 p-4 bg-red-50 border-l-4 border-red-500 text-red-800 rounded-lg flex items-center gap-2">
        <i data-lucide="alert-triangle" class="w-5 h-5"></i>
        <span x-text="errorMessage"></span>
    </div>

    <!-- API Access Token Section -->
    <div class="bg-white rounded-xl shadow-sm overflow-hidden mb-6">
        <div class="bg-gradient-to-r from-purple-600 to-pink-600 px-6 py-4 flex items-center gap-2 text-white">
            <i data-lucide="shield-check" class="w-5 h-5"></i>
            <h2 class="text-lg font-semibold">API Access Token</h2>
        </div>
        <div class="p-6 space-y-4">
            <p class="text-sm text-gray-600">Use this token to authenticate API requests and GitHub Copilot CLI MCP connections.</p>
            
            <!-- Access Token -->
            <div>
                <label class="block text-sm font-medium text-gray-700 mb-2">Your Access Token</label>
                <div class="flex gap-2">
                    <input type="text" readonly id="accessToken" value="{{ access_token }}" 
                           class="flex-1 px-3 py-2 border border-gray-300 rounded-lg bg-gray-50 font-mono text-sm">
                    <button onclick="copyAccessToken()" 
                            class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-2">
                        <i data-lucide="copy" class="w-4 h-4"></i>
                        Copy
                    </button>
                </div>
                <p class="text-xs text-gray-500 mt-1">Expires in: <span class="font-medium" id="tokenExpiresIn">{{ token_expires_in }}</span></p>
            </div>

            <!-- MCP Client Format -->
            <div>
                <label class="block text-sm font-medium text-gray-700 mb-2">For GitHub Copilot CLI</label>
                <div class="flex gap-2">
                    <input type="text" readonly id="mcpHeaderJson" value='{"Authorization": "Bearer {{ access_token }}"}'
                           class="flex-1 px-3 py-2 border border-gray-300 rounded-lg bg-gray-50 font-mono text-sm">
                    <button onclick="copyMcpHeader()" 
                            class="px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors flex items-center gap-2">
                        <i data-lucide="copy" class="w-4 h-4"></i>
                        Copy JSON
                    </button>
                </div>
                <p class="text-xs text-gray-500 mt-1">Paste this in "HTTP Headers" field when adding HTTP MCP server</p>
            </div>

            <!-- Refresh Token Button -->
            <div class="pt-2 border-t border-gray-200">
                <button onclick="rotateAccessToken()" 
                        class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 transition-colors flex items-center gap-2">
                    <i data-lucide="refresh-cw" class="w-4 h-4"></i>
                    Rotate Token
                </button>
            </div>
        </div>
    </div>

    <!-- JWT Token Settings -->
    <div class="bg-white rounded-xl shadow-sm overflow-hidden mb-6">
        <div class="bg-gradient-to-r from-blue-600 to-cyan-600 px-6 py-4 flex items-center gap-2 text-white">
            <i data-lucide="key" class="w-5 h-5"></i>
            <h2 class="text-lg font-semibold">JWT Token Settings</h2>
        </div>
        <div class="p-6">
            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-2">Access Token Lifetime (minutes)</label>
                    <input type="number" id="accessTokenTTL" min="1" max="525600" required
                           class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
                    <p class="text-xs text-gray-500 mt-1">Recommended: 1440 (24 hours), 10080 (7 days), 43200 (30 days)</p>
                </div>
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-2">Refresh Token Lifetime (days)</label>
                    <input type="number" id="refreshTokenTTL" min="1" max="365" required
                           class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
                    <p class="text-xs text-gray-500 mt-1">Recommended: 7, 30, or 90 days</p>
                </div>
            </div>
            <div class="mt-4 flex items-start">
                <input type="checkbox" id="enforceSingleSession"
                       class="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500 mt-1">
                <div class="ml-3">
                    <label for="enforceSingleSession" class="font-medium text-gray-900">Enforce Single Session</label>
                    <p class="text-sm text-gray-600">When enabled, new logins invalidate previous access tokens (one active token per user).</p>
                    <p class="text-xs text-gray-500 mt-1">If Codex runs on multiple machines, disable this to avoid logouts (tokens are stored locally per machine).</p>
                </div>
            </div>
            <div class="mt-4 p-4 bg-blue-50 border border-blue-200 rounded-lg">
                <div class="flex items-start gap-2">
                    <i data-lucide="info" class="w-5 h-5 text-blue-600 mt-0.5"></i>
                    <div class="text-sm text-blue-800">
                        <strong>Note:</strong> For Claude Desktop MCP, longer access token lifetimes (24h - 7d) are recommended
                        since token auto-refresh is not yet supported by MCP clients.
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- Password Policy -->
    <div class="bg-white rounded-xl shadow-sm overflow-hidden mb-6">
        <div class="bg-gradient-to-r from-cyan-600 to-blue-600 px-6 py-4 flex items-center gap-2 text-white">
            <i data-lucide="shield-check" class="w-5 h-5"></i>
            <h2 class="text-lg font-semibold">Password Policy</h2>
        </div>
        <div class="p-6">
            <div class="mb-4">
                <label class="block text-sm font-medium text-gray-700 mb-2">Minimum Length</label>
                <input type="number" id="passwordMinLength" min="4" max="128" required
                       class="w-full md:w-64 px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
            </div>
            <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
                <div class="flex items-center">
                    <input type="checkbox" id="requireUppercase"
                           class="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500">
                    <label for="requireUppercase" class="ml-2 text-sm text-gray-700">Require Uppercase</label>
                </div>
                <div class="flex items-center">
                    <input type="checkbox" id="requireLowercase"
                           class="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500">
                    <label for="requireLowercase" class="ml-2 text-sm text-gray-700">Require Lowercase</label>
                </div>
                <div class="flex items-center">
                    <input type="checkbox" id="requireDigit"
                           class="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500">
                    <label for="requireDigit" class="ml-2 text-sm text-gray-700">Require Digit</label>
                </div>
                <div class="flex items-center">
                    <input type="checkbox" id="requireSpecial"
                           class="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500">
                    <label for="requireSpecial" class="ml-2 text-sm text-gray-700">Require Special Char</label>
                </div>
            </div>
        </div>
    </div>

    <!-- System Settings -->
    <div class="bg-white rounded-xl shadow-sm overflow-hidden mb-6">
        <div class="bg-gradient-to-r from-blue-600 to-cyan-600 px-6 py-4 flex items-center gap-2 text-white">
            <i data-lucide="toggle-left" class="w-5 h-5"></i>
            <h2 class="text-lg font-semibold">System Settings</h2>
        </div>
        <div class="p-6">
            <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
                <div class="flex items-start">
                    <input type="checkbox" id="allowRegistration"
                           class="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500 mt-1">
                    <div class="ml-3">
                        <label for="allowRegistration" class="font-medium text-gray-900">Allow Public Registration</label>
                        <p class="text-sm text-gray-600">Enable /auth/register endpoint for public user registration</p>
                    </div>
                </div>
                <div class="flex items-start">
                    <input type="checkbox" id="authRequired"
                           class="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500 mt-1">
                    <div class="ml-3">
                        <label for="authRequired" class="font-medium text-gray-900">Authentication Required</label>
                        <p class="text-sm text-gray-600">Require authentication for all MCP endpoints</p>
                    </div>
                </div>
                <div class="flex items-start">
                    <input type="checkbox" id="allowDcr"
                           class="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500 mt-1">
                    <div class="ml-3">
                        <label for="allowDcr" class="font-medium text-gray-900">Allow Dynamic Client Registration (DCR)</label>
                        <p class="text-sm text-gray-600">Enable /oauth/register for MCP clients like Codex to self-register OAuth clients</p>
                    </div>
                </div>
            </div>
            <div class="mt-4 p-4 bg-blue-50 border border-blue-200 rounded-lg">
                <div class="flex items-start gap-2">
                    <i data-lucide="info" class="w-5 h-5 text-blue-600 mt-0.5 flex-shrink-0"></i>
                    <div class="text-sm text-blue-800">
                        <strong>Codex / OAuth MCP clients:</strong> Two settings are needed for Codex to connect via OAuth:
                        <ul class="mt-1 ml-4 list-disc space-y-1">
                            <li><strong>Allow DCR</strong> must be enabled so Codex can self-register as an OAuth client (<code class="bg-blue-100 px-1 rounded">codex mcp login</code>).</li>
                            <li><strong>Enforce Single Session</strong> (JWT section above) should be disabled if Codex runs on multiple machines, otherwise logging in from one machine invalidates tokens on the others.</li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- Rate Limits -->
    <div class="bg-white rounded-xl shadow-sm overflow-hidden mb-6">
        <div class="bg-gradient-to-r from-orange-600 to-red-600 px-6 py-4 flex items-center gap-2 text-white">
            <i data-lucide="gauge" class="w-5 h-5"></i>
            <h2 class="text-lg font-semibold">Rate Limits</h2>
        </div>
        <div class="p-6 space-y-4">
            <p class="text-sm text-gray-600">Per-user request limits to protect backend servers from abuse.</p>
            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-2">MCP Requests (max per window)</label>
                    <input type="number" id="mcpLimit" min="1" max="10000" required
                           class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-orange-500 focus:border-orange-500">
                </div>
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-2">MCP Window (seconds)</label>
                    <input type="number" id="mcpWindow" min="1" max="86400" required
                           class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-orange-500 focus:border-orange-500">
                </div>
            </div>
            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-2">Login Attempts (max per window)</label>
                    <input type="number" id="loginLimit" min="1" max="100" required
                           class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-orange-500 focus:border-orange-500">
                </div>
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-2">Login Window (seconds)</label>
                    <input type="number" id="loginWindow" min="1" max="86400" required
                           class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-orange-500 focus:border-orange-500">
                </div>
            </div>
            <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-2">Register Attempts (max per window)</label>
                    <input type="number" id="registerLimit" min="1" max="100" required
                           class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-orange-500 focus:border-orange-500">
                </div>
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-2">Register Window (seconds)</label>
                    <input type="number" id="registerWindow" min="1" max="86400" required
                           class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-orange-500 focus:border-orange-500">
                </div>
            </div>
            <div class="p-4 bg-orange-50 border border-orange-200 rounded-lg">
                <div class="flex items-start gap-2">
                    <i data-lucide="info" class="w-5 h-5 text-orange-600 mt-0.5"></i>
                    <div class="text-sm text-orange-800">
                        <strong>MCP Rate Limit</strong>: limits per-user requests to backend MCP servers.
                        Default: 100 requests per 60 seconds. Changes apply immediately.
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- Save Buttons -->
    <div class="flex justify-end gap-3">
        <button @click="loadSettings()"
                class="px-6 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition-colors flex items-center gap-2">
            <i data-lucide="rotate-ccw" class="w-4 h-4"></i>
            Reset
        </button>
        <button @click="saveSettings()"
                class="px-6 py-2 bg-gradient-to-r from-blue-600 to-cyan-600 hover:from-blue-700 hover:to-cyan-700 text-white rounded-lg transition-colors flex items-center gap-2">
            <i data-lucide="save" class="w-4 h-4"></i>
            Save All Settings
        </button>
    </div>
</div>

<style>
    [x-cloak] { display: none !important; }
</style>
{% endblock %}

{% block extra_scripts %}
<script>
    function settingsManager() {
        return {
            showSuccess: false,
            showError: false,
            errorMessage: '',
            
            init() {
                // Load settings on component init
                this.loadSettings();
            },
            
            async loadSettings() {
                try {
                    const response = await fetch('/admin/api/settings');
                    const settings = await response.json();

                    // JWT settings
                    document.getElementById('accessTokenTTL').value = settings.jwt?.access_token_expire_minutes || 1440;
                    document.getElementById('refreshTokenTTL').value = settings.jwt?.refresh_token_expire_days || 7;
                    document.getElementById('enforceSingleSession').checked = settings.jwt?.enforce_single_session !== false;

                    // Password policy
                    const policy = settings.password_policy || {};
                    document.getElementById('passwordMinLength').value = policy.min_length || 8;
                    document.getElementById('requireUppercase').checked = policy.require_uppercase !== false;
                    document.getElementById('requireLowercase').checked = policy.require_lowercase !== false;
                    document.getElementById('requireDigit').checked = policy.require_digit !== false;
                    document.getElementById('requireSpecial').checked = policy.require_special || false;

                    // System settings
                    const system = settings.system || {};
                    document.getElementById('allowRegistration').checked = system.allow_registration !== false;
                    document.getElementById('authRequired').checked = system.auth_required !== false;
                    document.getElementById('allowDcr').checked = system.allow_dcr === true;

                    // Rate limits
                    const rl = settings.rate_limit || {};
                    document.getElementById('mcpLimit').value = rl.mcp_limit || 100;
                    document.getElementById('mcpWindow').value = rl.mcp_window || 60;
                    document.getElementById('loginLimit').value = rl.login_limit || 5;
                    document.getElementById('loginWindow').value = rl.login_window || 60;
                    document.getElementById('registerLimit').value = rl.register_limit || 3;
                    document.getElementById('registerWindow').value = rl.register_window || 300;

                } catch (error) {
                    this.showErrorAlert('Failed to load settings: ' + error.message);
                }
            },
            
            async saveSettings() {
                const parseIntStrict = (id, min, max, label) => {
                    const raw = document.getElementById(id).value;
                    const value = Number.parseInt(raw, 10);
                    if (!Number.isFinite(value)) {
                        throw new Error(`${label} must be a number`);
                    }
                    if (value < min || value > max) {
                        throw new Error(`${label} must be between ${min} and ${max}`);
                    }
                    return value;
                };

                const settings = {
                    jwt: {
                        access_token_expire_minutes: parseIntStrict('accessTokenTTL', 1, 525600, 'Access token lifetime'),
                        refresh_token_expire_days: parseIntStrict('refreshTokenTTL', 1, 365, 'Refresh token lifetime'),
                        enforce_single_session: document.getElementById('enforceSingleSession').checked
                    },
                    password_policy: {
                        min_length: parseIntStrict('passwordMinLength', 4, 128, 'Password minimum length'),
                        require_uppercase: document.getElementById('requireUppercase').checked,
                        require_lowercase: document.getElementById('requireLowercase').checked,
                        require_digit: document.getElementById('requireDigit').checked,
                        require_special: document.getElementById('requireSpecial').checked
                    },
                    system: {
                        allow_registration: document.getElementById('allowRegistration').checked,
                        auth_required: document.getElementById('authRequired').checked,
                        allow_dcr: document.getElementById('allowDcr').checked
                    },
                    rate_limit: {
                        mcp_limit: parseIntStrict('mcpLimit', 1, 10000, 'MCP request limit'),
                        mcp_window: parseIntStrict('mcpWindow', 1, 86400, 'MCP window'),
                        login_limit: parseIntStrict('loginLimit', 1, 100, 'Login limit'),
                        login_window: parseIntStrict('loginWindow', 1, 86400, 'Login window'),
                        register_limit: parseIntStrict('registerLimit', 1, 100, 'Register limit'),
                        register_window: parseIntStrict('registerWindow', 1, 86400, 'Register window')
                    }
                };

                try {
                    const response = await fetch('/admin/api/settings', {
                        method: 'PUT',
                        headers: {'Content-Type': 'application/json'},
                        body: JSON.stringify(settings)
                    });

                    if (response.ok) {
                        this.showSuccessAlert();
                    } else {
                        const error = await response.json();
                        this.showErrorAlert(error.detail || 'Failed to save settings');
                    }
                } catch (error) {
                    this.showErrorAlert('Error: ' + error.message);
                }
            },
            
            showSuccessAlert() {
                this.showSuccess = true;
                this.showError = false;
                setTimeout(() => this.showSuccess = false, 3000);
                window.scrollTo({ top: 0, behavior: 'smooth' });
                setTimeout(() => lucide.createIcons(), 100);
            },
            
            showErrorAlert(message) {
                this.errorMessage = message;
                this.showError = true;
                this.showSuccess = false;
                window.scrollTo({ top: 0, behavior: 'smooth' });
                setTimeout(() => lucide.createIcons(), 100);
            }
        }
    }

    function copyToClipboard(text, message = 'Copied!') {
        const canUseClipboard = navigator.clipboard && window.isSecureContext;
        if (canUseClipboard) {
            navigator.clipboard.writeText(text).then(() => {
                showToast(message);
            }).catch(() => {
                showToast('Failed to copy', 'error');
            });
            return;
        }
        try {
            const textarea = document.createElement('textarea');
            textarea.value = text;
            textarea.setAttribute('readonly', '');
            textarea.style.position = 'absolute';
            textarea.style.left = '-9999px';
            document.body.appendChild(textarea);
            textarea.select();
            document.execCommand('copy');
            document.body.removeChild(textarea);
            showToast(message);
        } catch (err) {
            showToast('Failed to copy', 'error');
        }
    }

    function copyAccessToken() {
        const input = document.getElementById('accessToken');
        copyToClipboard(input.value, 'Token copied!');
    }

    function copyMcpHeader() {
        const input = document.getElementById('mcpHeaderJson');
        copyToClipboard(input.value, 'MCP header copied!');
    }

    async function rotateAccessToken() {
        try {
            const response = await fetch('/admin/api/access-token/rotate', { method: 'POST' });
            const data = await response.json();
            if (!response.ok) {
                throw new Error(data.detail || 'Failed to rotate token');
            }
            const tokenInput = document.getElementById('accessToken');
            const headerInput = document.getElementById('mcpHeaderJson');
            const expiresEl = document.getElementById('tokenExpiresIn');
            tokenInput.value = data.access_token || '';
            headerInput.value = `{\"Authorization\": \"Bearer ${data.access_token || ''}\"}`;
            if (expiresEl) {
                expiresEl.textContent = data.token_expires_in || '';
            }
            showToast('Token rotated!');
        } catch (err) {
            showToast(err.message || 'Failed to rotate token', 'error');
        }
    }

    document.addEventListener('DOMContentLoaded', function() {
        setTimeout(() => lucide.createIcons(), 100);
    });
</script>
{% endblock %}
