<!--
Copyright (C) 2026 Stefy Lanza <stefy@nexlab.net>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.
-->
{% extends "base.html" %}

{% block title %}Autoselect - AISBF Dashboard{% endblock %}

{% block content %}
<h2 style="margin-bottom: 30px;">Autoselect Configuration</h2>

{% if success %}
<div class="alert alert-success">{{ success }}</div>
{% endif %}

{% if error %}
<div class="alert alert-error">{{ error }}</div>
{% endif %}

<div id="autoselect-list" style="margin-bottom: 20px;">
    <!-- Autoselect list will be rendered here -->
</div>

<button type="button" class="btn" onclick="addAutoselect()" style="margin-top: 20px;"data-i18n="user_autoselects_page.add_autoselect">Add Autoselect</button>
<div style="display: flex; gap: 10px; margin-top: 20px;">
    <button type="button" class="btn" onclick="saveAutoselect()"data-i18n="user_autoselects_page.save_config">Save Configuration</button>
    <a href="/dashboard" class="btn btn-secondary">Cancel</a>
</div>

<script src="{{ url_for(request, '/dashboard/static/dragsort.js') }}"></script>
<script>
function escHtmlAttr(s) {
    return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/'/g,'&#39;');
}

const autoselectData = {
    config: {{ autoselect_json | safe }},
    rotations: {{ available_rotations | safe }},
    models: {{ available_models | safe }},
    saveUrl: "{{ url_for(request, '/dashboard/autoselect') }}",
    successUrl: "{{ url_for(request, '/dashboard/autoselect?success=1') }}"
};
let autoselectConfig = autoselectData.config;
let availableRotations = autoselectData.rotations;
let availableModels = autoselectData.models;
const providersMeta = {{ providers_meta | default('{}') | safe }};
let expandedAutoselects = new Set();
let autoselectMasterOrder = Object.keys(autoselectConfig || {});
let _autoselectDS = null;

// ===== Provider Usage =====
const _usageCache = {};
const BASE_PATH = {{ (request.scope.get('root_path', '') or '') | tojson }};

function _providerIdFromModel(modelId) {
    // model IDs in autoselect are like "provider_id/model_name"
    if (!modelId) return null;
    const parts = modelId.split('/');
    return parts.length > 1 ? parts[0] : null;
}
function _providerSupportsUsage(pid) { return pid && providersMeta[pid] && providersMeta[pid].type === 'codex'; }
function _fmtSeconds(s) {
    if (!s || s <= 0) return '0s';
    const h = Math.floor(s/3600), m = Math.floor((s%3600)/60), sec = s%60;
    if (h > 0) return `${h}h${m > 0 ? ' '+m+'m' : ''}`;
    if (m > 0) return `${m}m${sec > 0 ? ' '+sec+'s' : ''}`;
    return `${sec}s`;
}
function _windowLabel(seconds) {
    if (!seconds || seconds <= 0) return 'Window';
    if (seconds < 120) return 'Session';
    const MIN = 60, HOUR = 3600, DAY = 86400, WEEK = 604800, MONTH = 2592000;
    if (seconds % MONTH === 0) return seconds === MONTH ? 'Monthly' : `${seconds/MONTH}mo`;
    if (seconds % WEEK  === 0) return seconds === WEEK  ? 'Weekly'  : `${seconds/WEEK}wk`;
    if (seconds % DAY   === 0) return seconds === DAY   ? 'Daily'   : `${seconds/DAY}d`;
    if (seconds % HOUR  === 0) return seconds === HOUR  ? 'Hourly'  : `${seconds/HOUR}h`;
    if (seconds % MIN   === 0) return `${seconds/MIN}min`;
    if (seconds >= MONTH * 0.9) return `${Math.round(seconds/MONTH)}mo`;
    if (seconds >= WEEK  * 0.9) return 'Weekly';
    if (seconds >= DAY)         return `${Math.round(seconds/DAY)}d`;
    if (seconds >= HOUR)        return `${Math.round(seconds/HOUR)}h`;
    return `${Math.round(seconds/MIN)}min`;
}
function _usageBarHtml(pct) {
    const c = pct >= 90 ? '#ef4444' : pct >= 70 ? '#f59e0b' : '#22c55e';
    return `<div style="height:5px;background:var(--color-border);border-radius:2px;overflow:hidden;min-width:50px;flex:1;"><div style="height:100%;width:${Math.min(pct,100)}%;background:${c};"></div></div>`;
}
function _renderUsageCompact(usage) {
    if (!usage) return '';
    const parts = [];
    const plan = usage.plan_type ? `<span style="font-size:10px;color:var(--color-muted);text-transform:uppercase;">${usage.plan_type}</span>` : '';
    const rl = usage.rate_limit;
    if (rl) {
        const windows = [];
        if (rl.primary_window) windows.push(rl.primary_window);
        if (rl.secondary_window) windows.push(rl.secondary_window);
        if (Array.isArray(rl.additional_rate_limits)) windows.push(...rl.additional_rate_limits);
        windows.forEach(w => {
            const pct = w.used_percent || 0;
            let countStr = '';
            if (w.num_requests_used != null && w.num_requests_limit != null) {
                countStr = ` (${w.num_requests_used}/${w.num_requests_limit})`;
            }
            parts.push(`<div style="display:flex;align-items:center;gap:3px;font-size:10px;"><span style="color:var(--color-muted);white-space:nowrap;">${_windowLabel(w.limit_window_seconds)}:</span>${_usageBarHtml(pct)}<span>${pct}%${countStr}</span></div>`);
        });
        if (rl.limit_reached) parts.push('<span style="color:#ef4444;font-size:10px;font-weight:700;">LIMIT</span>');
    }
    return `<div style="display:inline-flex;flex-direction:column;gap:2px;vertical-align:middle;margin-left:4px;">${plan}${parts.join('')}</div>`;
}
async function fetchProviderUsage(pid) {
    try {
        const r = await fetch(`${BASE_PATH}/dashboard/api/provider/${encodeURIComponent(pid)}/usage`);
        if (!r.ok) return null;
        const d = await r.json();
        if (d.supported === false) return null;
        _usageCache[pid] = {data: d.usage, ts: Date.now()};
        return d.usage;
    } catch(e) { return null; }
}
function _updateAutoselectUsageBadges() {
    Object.keys(_usageCache).forEach(pid => {
        document.querySelectorAll(`[data-usage-pid="${pid}"]`).forEach(el => {
            const c = _usageCache[pid];
            if (c && c.data) el.innerHTML = _renderUsageCompact(c.data);
        });
    });
}
async function _refreshAutoselectUsage() {
    const pids = new Set();
    Object.values(autoselectConfig).forEach(as => {
        (as.available_models || []).forEach(m => {
            const pid = _providerIdFromModel(m.id || m);
            if (_providerSupportsUsage(pid)) pids.add(pid);
        });
    });
    for (const pid of pids) {
        const c = _usageCache[pid];
        if (c && (Date.now() - c.ts) < 14000) continue;
        await fetchProviderUsage(pid);
    }
    _updateAutoselectUsageBadges();
}
setInterval(_refreshAutoselectUsage, 15000);
document.addEventListener('DOMContentLoaded', () => setTimeout(_refreshAutoselectUsage, 500));

// ===== Model Search Modal =====
let _msAllItems = [], _msDispItems = [], _msCancelled = false, _msCallback = null;

function _msEnsure() {
    if (document.getElementById('ms-overlay')) return;
    const d = document.createElement('div');
    d.id = 'ms-overlay';
    d.style.cssText = 'display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.75);z-index:9999;align-items:center;justify-content:center;';
    d.innerHTML = `
      <div style="background:var(--bg-page);border:1px solid var(--color-border);border-radius:8px;padding:24px;max-width:560px;width:93%;max-height:85vh;display:flex;flex-direction:column;box-shadow:0 8px 32px rgba(0,0,0,0.6);">
        <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
          <h3 id="ms-title" style="margin:0;font-size:16px;color:var(--color-text);">${window.i18n.t('autoselect.search_models_title')}</h3>
          <button type="button" onclick="msClose()" style="background:none;border:none;color:var(--color-muted);cursor:pointer;font-size:22px;padding:0 4px;">&times;</button>
        </div>
        <div id="ms-status" style="font-size:13px;color:var(--color-muted);min-height:18px;margin-bottom:10px;"></div>
        <div style="display:flex;gap:8px;margin-bottom:12px;">
          <input type="text" id="ms-filter-input" placeholder="${window.i18n.t('autoselect.filter_results')}"
            style="flex:1;padding:8px;border:1px solid var(--color-border);border-radius:3px;background:var(--bg-panel);color:var(--color-text);font-size:14px;"
            onkeydown="if(event.key==='Enter')msFilter()">
          <button type="button" onclick="msFilter()" class="btn btn-secondary" style="padding:8px 14px;font-size:13px;">${window.i18n.t('autoselect.filter')}</button>
        </div>
        <div id="ms-results" style="overflow-y:auto;flex:1;max-height:340px;border:1px solid var(--color-border);border-radius:3px;background:var(--bg-panel);min-height:40px;"></div>
        <div style="margin-top:14px;display:flex;justify-content:flex-end;">
          <button type="button" onclick="msClose()" class="btn btn-secondary">${window.i18n.t('autoselect.cancel')}</button>
        </div>
      </div>`;
    document.body.appendChild(d);
}

async function msOpenAll(inputId, cb) {
    _msEnsure(); _msCancelled = false; _msAllItems = []; _msDispItems = [];
    _msCallback = function(v) { const e = document.getElementById(inputId); if (e) e.value = v; cb(v); };
    const o = document.getElementById('ms-overlay'); o.style.display = 'flex';
    document.getElementById('ms-title').textContent = window.i18n.t('autoselect.search_models_title');
    document.getElementById('ms-filter-input').value = '';
    const all = availableRotations.map(r => ({id: r, name: r + ' (rotation)'})).concat(availableModels);
    if (all.length) {
        _msAllItems = all;
        document.getElementById('ms-status').textContent = all.length + ' model(s) available. Use Filter to narrow results.';
        msRenderResults(all);
    } else {
        document.getElementById('ms-status').textContent = window.i18n.t('autoselect.no_models_loaded');
        document.getElementById('ms-results').innerHTML = `<p style="color:var(--color-muted);text-align:center;padding:20px;">${window.i18n.t('autoselect.loading')}</p>`;
        try {
            const r = await fetch('/dashboard/search-all-models?refresh=true');
            if (_msCancelled) return;
            const data = await r.json(); const fetched = data.models || [];
            _msAllItems = fetched;
            availableModels = fetched.filter(m => m.type === 'provider');
            document.getElementById('ms-status').textContent = fetched.length ? window.i18n.interpolate(window.i18n.t('autoselect.models_found'), {n: fetched.length}) : window.i18n.t('autoselect.no_models_loaded');
            msRenderResults(fetched);
        } catch(e) {
            if (!_msCancelled) { document.getElementById('ms-status').textContent = window.i18n.t('autoselect.error_prefix') + ' ' + e.message; document.getElementById('ms-results').innerHTML = `<p style="color:#f87171;padding:15px;">${window.i18n.t('autoselect.failed_load')}</p>`; }
        }
    }
}

function msFilter() {
    const q = document.getElementById('ms-filter-input').value.trim().toLowerCase();
    document.getElementById('ms-status').textContent = window.i18n.t('autoselect.searching');
    const filtered = q ? _msAllItems.filter(m => (typeof m === 'string' ? m : m.id + ' ' + m.name).toLowerCase().includes(q)) : _msAllItems;
    document.getElementById('ms-status').textContent = window.i18n.interpolate(window.i18n.t('autoselect.result_count'), {n: filtered.length});
    msRenderResults(filtered);
}

function msRenderResults(items) {
    _msDispItems = items;
    const el = document.getElementById('ms-results');
    if (!items || !items.length) { el.innerHTML = `<p style="color:var(--color-muted);text-align:center;padding:20px;">${window.i18n.t('autoselect.no_results')}</p>`; return; }
    el.innerHTML = items.map((item, i) => {
        const isStr = typeof item === 'string';
        const id = isStr ? item : item.id, label = isStr ? item : item.name;
        return `<div data-idx="${i}" onclick="msPickIdx(this)" style="padding:8px 12px;cursor:pointer;border-bottom:1px solid var(--color-border);font-size:13px;word-break:break-all;" onmouseover="this.style.background='var(--bg-accent)'" onmouseout="this.style.background=''">` +
               (id !== label ? `<span style="color:var(--color-text);">${escHtmlAttr(id)}</span><span style="color:var(--color-subtle);font-size:11px;margin-left:6px;">${escHtmlAttr(label)}</span>` : `<span>${escHtmlAttr(id)}</span>`) + '</div>';
    }).join('');
}

function msPickIdx(el) {
    const i = parseInt(el.getAttribute('data-idx'));
    const item = _msDispItems[i]; const val = typeof item === 'string' ? item : item.id;
    if (_msCallback) _msCallback(val);
    msClose();
}

function msClose() {
    _msCancelled = true;
    const el = document.getElementById('ms-overlay'); if (el) el.style.display = 'none';
}

function msOpenAllForInput(btn) {
    const inputId = btn.getAttribute('data-input-id');
    const input = document.getElementById(inputId);
    msOpenAll(inputId, function(v) {
        if (input) { input.value = v; input.dispatchEvent(new Event('change')); }
    });
}

function buildModelSelectHtml(uid, currentValue, allModels, onChangeExpr) {
    if (allModels.length <= 25) {
        const opts = allModels.map(m =>
            `<option value="${escHtmlAttr(m.id)}" ${currentValue === m.id ? 'selected' : ''}>${escHtmlAttr(m.name)}</option>`
        ).join('');
        return `<select id="${uid}" onchange="${onChangeExpr}" required>
            <option value="">${window.i18n.t('autoselect.select_model')}</option>${opts}</select>`;
    } else {
        return `<div style="display:flex;gap:5px;align-items:center;">
            <input type="text" id="${escHtmlAttr(uid)}" value="${escHtmlAttr(currentValue)}"
                   onchange="${onChangeExpr}"
                   placeholder="Rotation…"
                   style="flex:1;padding:8px;border:1px solid var(--color-border);border-radius:3px;background:var(--bg-page);color:var(--color-text);font-size:14px;">
            <button type="button" class="btn btn-secondary"
                data-input-id="${escHtmlAttr(uid)}"
                onclick="msOpenAllForInput(this)"
                style="padding:7px 12px;white-space:nowrap;">${window.i18n.t('autoselect.search')}</button>
        </div>`;
    }
}

function renderAutoselectList() {
    const container = document.getElementById('autoselect-list');
    container.innerHTML = '';

    const visibleKeys = autoselectMasterOrder.filter(k => k in (autoselectConfig || {}));
    if (!autoselectConfig || visibleKeys.length === 0) {
        container.innerHTML = `<p style="color: var(--color-muted);">${window.i18n.t('autoselect.no_autoselects')}</p>`;
        return;
    }

    visibleKeys.forEach(key => {
        const autoselect = autoselectConfig[key];
        const autoselectItem = document.createElement('div');
        autoselectItem.className = 'autoselect-item';
        autoselectItem.dataset.sortKey = key;
        autoselectItem.style.cssText = 'border: 1px solid var(--color-border); margin-bottom: 10px; border-radius: 5px; background: var(--bg-page);';

        const isExpanded = expandedAutoselects.has(key);
        const modelCount = autoselect.available_models ? autoselect.available_models.length : 0;

        const safeKey = key.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
        autoselectItem.innerHTML = `
            <div class="autoselect-header" onclick="toggleAutoselect('${safeKey}')" style="padding: 15px; cursor: pointer; display: flex; justify-content: space-between; align-items: center; user-select: none;">
                <div style="display: flex; align-items: center; gap: 10px;">
                    <span class="drag-handle" onclick="event.stopPropagation();" title="Drag to reorder">⠿</span>
                    <span style="font-size: 18px;">${isExpanded ? '▼' : '▶'}</span>
                    <strong style="font-size: 16px;">${escHtmlAttr(autoselect.model_name || key)}</strong>
                    <span style="color: var(--color-muted); font-size: 14px;">(${modelCount} ${modelCount !== 1 ? window.i18n.t('autoselect.models_plural') : window.i18n.t('autoselect.models_singular')})</span>
                </div>
                <div style="display: flex; gap: 8px;">
                    <button type="button" class="btn btn-secondary" onclick="event.stopPropagation(); copyAutoselect('${safeKey}')" style="padding: 5px 15px;">${window.i18n.t('autoselect.copy')}</button>
                    <button type="button" class="btn btn-secondary" onclick="event.stopPropagation(); removeAutoselect('${safeKey}')" style="background: #dc3545; padding: 5px 15px;">${window.i18n.t('autoselect.remove')}</button>
                </div>
            </div>
            <div id="autoselect-details-${escHtmlAttr(key)}" style="display: ${isExpanded ? 'block' : 'none'}; padding: 20px; border-top: 1px solid var(--color-border); background: var(--bg-panel);">
            </div>
        `;

        container.appendChild(autoselectItem);

        if (isExpanded) {
            renderAutoselectDetails(key);
        }
    });

    if (!_autoselectDS) {
        _autoselectDS = new DragSort({
            containerId: 'autoselect-list',
            masterOrder: { value: autoselectMasterOrder },
            onReorder: function(newOrder) {
                autoselectMasterOrder = newOrder;
                renderAutoselectList();
                fetch(BASE_PATH + '/dashboard/api/autoselect/reorder', {
                    method: 'POST', headers: {'Content-Type':'application/json'},
                    body: JSON.stringify({order: newOrder})
                }).catch(function(){});
            }
        });
    } else {
        _autoselectDS._opts.masterOrder.value = autoselectMasterOrder;
        _autoselectDS.attach();
    }
}

function toggleAutoselect(key) {
    if (expandedAutoselects.has(key)) {
        expandedAutoselects.delete(key);
    } else {
        expandedAutoselects.add(key);
    }
    renderAutoselectList();
}

function renderAutoselectDetails(autoselectKey) {
    const container = document.getElementById(`autoselect-details-${autoselectKey}`);
    const autoselect = autoselectConfig[autoselectKey];
    const safeAKey = autoselectKey.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
    
    // Default to "internal" if selection_model is not set
    const selectionValue = autoselect.selection_model || 'internal';
    
    // Build selection model options: internal + rotations + provider models
    let selectionOptions = `<option value="internal" ${selectionValue === 'internal' ? 'selected' : ''}>${window.i18n.t('autoselect.internal_model')}</option>`;
    selectionOptions += `<optgroup label="${window.i18n.t('autoselect.rotations_group')}">`;
    selectionOptions += availableRotations.map(r =>
        `<option value="${r}" ${selectionValue === r ? 'selected' : ''}>${r}</option>`
    ).join('');
    selectionOptions += '</optgroup>';
    selectionOptions += `<optgroup label="${window.i18n.t('autoselect.provider_models_group')}">`;
    selectionOptions += availableModels.map(m =>
        `<option value="${m.id}" ${selectionValue === m.id ? 'selected' : ''}>${m.name}</option>`
    ).join('');
    selectionOptions += '</optgroup>';
    
    // Build fallback options: rotations + provider models
    let fallbackOptions = `<optgroup label="${window.i18n.t('autoselect.rotations_group')}">`;
    fallbackOptions += availableRotations.map(r =>
        `<option value="${r}" ${autoselect.fallback === r ? 'selected' : ''}>${r}</option>`
    ).join('');
    fallbackOptions += '</optgroup>';
    fallbackOptions += `<optgroup label="${window.i18n.t('autoselect.provider_models_group')}">`;
    fallbackOptions += availableModels.map(m =>
        `<option value="${m.id}" ${autoselect.fallback === m.id ? 'selected' : ''}>${m.name}</option>`
    ).join('');
    fallbackOptions += '</optgroup>';
    
    container.innerHTML = `
        <div class="form-group">
            <label>${window.i18n.t('autoselect.model_name')}</label>
            <input type="text" value="${autoselect.model_name}" onchange="updateAutoselect('${autoselectKey}', 'model_name', this.value)" required>
        </div>
        
        <div class="form-group">
            <label>${window.i18n.t('autoselect.capabilities')}</label>
            <input type="text" value="${autoselect.capabilities ? autoselect.capabilities.join(', ') : ''}" onchange="updateAutoselectCapabilities('${autoselectKey}', this.value)" placeholder="${window.i18n.t('autoselect.capabilities_placeholder')}">
        </div>
        
        <div class="form-group">
            <label>
                <input type="checkbox" ${autoselect.nsfw ? 'checked' : ''} onchange="updateAutoselect('${autoselectKey}', 'nsfw', this.checked)">
                ${window.i18n.t('autoselect.nsfw')}
            </label>
        </div>
        
        <div class="form-group">
            <label>
                <input type="checkbox" ${autoselect.privacy ? 'checked' : ''} onchange="updateAutoselect('${autoselectKey}', 'privacy', this.checked)">
                ${window.i18n.t('autoselect.privacy')}
            </label>
        </div>
        
        <div class="form-group">
            <label>
                <input type="checkbox" ${autoselect.classify_nsfw ? 'checked' : ''} onchange="updateAutoselect('${autoselectKey}', 'classify_nsfw', this.checked)">
                ${window.i18n.t('autoselect.classify_nsfw')}
            </label>
            <small style="color: var(--color-muted); font-size: 12px; display: block; margin-top: 5px;">${window.i18n.t('autoselect.classify_nsfw_desc')}</small>
        </div>
        
        <div class="form-group">
            <label>
                <input type="checkbox" ${autoselect.classify_privacy ? 'checked' : ''} onchange="updateAutoselect('${autoselectKey}', 'classify_privacy', this.checked)">
                ${window.i18n.t('autoselect.classify_privacy')}
            </label>
            <small style="color: var(--color-muted); font-size: 12px; display: block; margin-top: 5px;">${window.i18n.t('autoselect.classify_privacy_desc')}</small>
        </div>
        
        <div class="form-group">
            <label>
                <input type="checkbox" ${autoselect.classify_semantic ? 'checked' : ''} onchange="updateAutoselect('${autoselectKey}', 'classify_semantic', this.checked)">
                ${window.i18n.t('autoselect.classify_semantic')}
            </label>
            <small style="color: var(--color-muted); font-size: 12px; display: block; margin-top: 5px;">${window.i18n.t('autoselect.classify_semantic_desc')}</small>
        </div>
        
        <div class="form-group">
            <label>${window.i18n.t('autoselect.description')}</label>
            <textarea onchange="updateAutoselect('${autoselectKey}', 'description', this.value)" style="min-height: 60px;">${autoselect.description || ''}</textarea>
        </div>
        
        <div class="form-group">
            <label>${window.i18n.t('autoselect.selection_model')}</label>
            <select onchange="updateAutoselect('${autoselectKey}', 'selection_model', this.value)" required>
                <option value="">${window.i18n.t('autoselect.select_model')}</option>
                ${selectionOptions}
            </select>
            <small style="color: var(--color-muted); font-size: 12px; display: block; margin-top: 5px;">${window.i18n.t('autoselect.selection_model_desc')}</small>
        </div>
        
        <div class="form-group">
            <label>${window.i18n.t('autoselect.fallback_model')}</label>
            <select onchange="updateAutoselect('${autoselectKey}', 'fallback', this.value)" required>
                <option value="">${window.i18n.t('autoselect.select_model')}</option>
                ${fallbackOptions}
            </select>
            <small style="color: var(--color-muted); font-size: 12px; display: block; margin-top: 5px;">${window.i18n.t('autoselect.fallback_model_desc')}</small>
        </div>
        
        <h4 style="margin-top: 20px; margin-bottom: 10px;">${window.i18n.t('autoselect.default_settings')}</h4>
        <p style="color: var(--color-muted); font-size: 14px; margin-bottom: 10px;">${window.i18n.t('autoselect.default_settings_desc')}</p>
        
        <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;">
            <div class="form-group">
                <label>${window.i18n.t('autoselect.default_rate_limit')}</label>
                <input type="number" value="${autoselect.default_rate_limit || ''}" onchange="updateAutoselect('${autoselectKey}', 'default_rate_limit', this.value ? parseFloat(this.value) : null)" step="0.1" placeholder="${window.i18n.t('autoselect.optional')}">
            </div>
            
            <div class="form-group">
                <label>${window.i18n.t('autoselect.default_max_request_tokens')}</label>
                <input type="number" value="${autoselect.default_max_request_tokens || ''}" onchange="updateAutoselect('${autoselectKey}', 'default_max_request_tokens', this.value ? parseInt(this.value) : null)" placeholder="${window.i18n.t('autoselect.optional')}">
            </div>
            
            <div class="form-group">
                <label>${window.i18n.t('autoselect.default_context_size')}</label>
                <input type="number" value="${autoselect.default_context_size || ''}" onchange="updateAutoselect('${autoselectKey}', 'default_context_size', this.value ? parseInt(this.value) : null)" placeholder="${window.i18n.t('autoselect.optional')}">
            </div>
            
            <div class="form-group">
                <label>${window.i18n.t('autoselect.default_rate_limit_tpm')}</label>
                <input type="number" value="${autoselect.default_rate_limit_TPM || ''}" onchange="updateAutoselect('${autoselectKey}', 'default_rate_limit_TPM', this.value ? parseInt(this.value) : null)" placeholder="${window.i18n.t('autoselect.optional')}">
                <small style="color: var(--color-muted); font-size: 12px; display: block; margin-top: 5px;">${window.i18n.t('autoselect.default_rate_limit_tpm_desc')}</small>
            </div>
            
            <div class="form-group">
                <label>${window.i18n.t('autoselect.default_rate_limit_tph')}</label>
                <input type="number" value="${autoselect.default_rate_limit_TPH || ''}" onchange="updateAutoselect('${autoselectKey}', 'default_rate_limit_TPH', this.value ? parseInt(this.value) : null)" placeholder="${window.i18n.t('autoselect.optional')}">
                <small style="color: var(--color-muted); font-size: 12px; display: block; margin-top: 5px;">${window.i18n.t('autoselect.default_rate_limit_tph_desc')}</small>
            </div>
            
            <div class="form-group">
                <label>${window.i18n.t('autoselect.default_rate_limit_tpd')}</label>
                <input type="number" value="${autoselect.default_rate_limit_TPD || ''}" onchange="updateAutoselect('${autoselectKey}', 'default_rate_limit_TPD', this.value ? parseInt(this.value) : null)" placeholder="${window.i18n.t('autoselect.optional')}">
                <small style="color: var(--color-muted); font-size: 12px; display: block; margin-top: 5px;">${window.i18n.t('autoselect.default_rate_limit_tpd_desc')}</small>
            </div>
            
            <div class="form-group">
                <label>${window.i18n.t('autoselect.default_condense_context')}</label>
                <input type="number" value="${autoselect.default_condense_context || ''}" onchange="updateAutoselect('${autoselectKey}', 'default_condense_context', this.value ? parseInt(this.value) : null)" placeholder="${window.i18n.t('autoselect.optional')}">
                <small style="color: var(--color-muted); font-size: 12px; display: block; margin-top: 5px;">${window.i18n.t('autoselect.default_condense_context_desc')}</small>
            </div>
        </div>
        
        <h4 style="margin-top: 20px; margin-bottom: 10px;">${window.i18n.t('autoselect.available_models')}</h4>
        <p style="color: var(--color-muted); font-size: 14px; margin-bottom: 10px;">${window.i18n.t('autoselect.available_models_desc')}</p>
        <div id="models-${autoselectKey}"></div>
        <button type="button" class="btn btn-secondary" onclick="addAutoselectModel('${safeAKey}')" style="margin-top: 10px;">${window.i18n.t('autoselect.add_model')}</button>

        <div style="margin-top: 20px; padding-top: 15px; border-top: 1px solid var(--color-border); display: flex; gap: 10px; align-items: center;">
            <button type="button" class="btn" onclick="saveAutoselectItem('${safeAKey}')" style="background: #22c55e;">${window.i18n.t('autoselect.save_this')}</button>
            <span id="asel-save-status-${autoselectKey}" style="font-size: 13px; color: var(--color-muted);"></span>
        </div>
    `;

    renderAutoselectModels(autoselectKey);
}

function renderAutoselectModels(autoselectKey) {
    const container = document.getElementById(`models-${autoselectKey}`);
    const autoselect = autoselectConfig[autoselectKey];
    
    if (!autoselect.available_models || autoselect.available_models.length === 0) {
        container.innerHTML = `<p style="color: var(--color-muted);">${window.i18n.t('autoselect.no_models')}</p>`;
        return;
    }
    
    container.innerHTML = '';
    autoselect.available_models.forEach((model, index) => {
        const modelDiv = document.createElement('div');
        modelDiv.style.cssText = 'border: 1px solid var(--color-border); padding: 15px; margin-bottom: 10px; border-radius: 3px; background: var(--bg-page);';
        const safeKey = autoselectKey.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
        const allOptions = availableRotations.map(r => ({id: r, name: r}));
        const selUid = `asel-mod-${autoselectKey}-${index}`;

        const _modelPid = _providerIdFromModel(model.model_id || '');
        const _modelUsage = _providerSupportsUsage(_modelPid) && _usageCache[_modelPid] ? _renderUsageCompact(_usageCache[_modelPid].data) : '';
        const _usageBadge = _modelPid && _providerSupportsUsage(_modelPid)
            ? `<span data-usage-pid="${_modelPid}" style="margin-left:6px;">${_modelUsage}</span>` : '';

        modelDiv.innerHTML = `
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; flex-wrap:wrap; gap:6px;">
                <div style="display:flex;align-items:center;flex-wrap:wrap;gap:6px;">
                    <strong>${window.i18n.t('autoselect.model_label')} ${index + 1}</strong>
                    ${_usageBadge}
                </div>
                <button type="button" class="btn btn-secondary" onclick="removeAutoselectModel('${safeKey}', ${index})" style="background: #dc3545; padding: 5px 10px; font-size: 12px;">${window.i18n.t('autoselect.remove')}</button>
            </div>

            <div class="form-group">
                <label>${window.i18n.t('autoselect.model_id')}</label>
                ${buildModelSelectHtml(selUid, model.model_id || '', allOptions,
                    `updateAutoselectModel('${safeKey}',${index},'model_id',this.value)`)}
                <small style="color: var(--color-muted); font-size: 12px; display: block; margin-top: 5px;">${window.i18n.t('autoselect.model_id_desc')}</small>
            </div>
            
            <div class="form-group">
                <label>${window.i18n.t('autoselect.model_description')}</label>
                <textarea onchange="updateAutoselectModel('${autoselectKey}', ${index}, 'description', this.value)" style="min-height: 80px;" required>${model.description || ''}</textarea>
                <small style="color: var(--color-subtle); font-size: 12px;">${window.i18n.t('autoselect.model_description_hint')}</small>
            </div>
            
            <div class="form-group">
                <label>
                    <input type="checkbox" ${model.nsfw ? 'checked' : ''} onchange="updateAutoselectModel('${autoselectKey}', ${index}, 'nsfw', this.checked)">
                    ${window.i18n.t('autoselect.nsfw')}
                </label>
            </div>
            
            <div class="form-group">
                <label>
                    <input type="checkbox" ${model.privacy ? 'checked' : ''} onchange="updateAutoselectModel('${autoselectKey}', ${index}, 'privacy', this.checked)">
                    ${window.i18n.t('autoselect.privacy')}
                </label>
            </div>
        `;
        
        container.appendChild(modelDiv);
    });
}

async function apiCall(method, url, body) {
    const opts = { method, headers: { 'Content-Type': 'application/json' } };
    if (body !== undefined) opts.body = JSON.stringify(body);
    const r = await fetch(url, opts);
    return r.json();
}

async function saveAutoselectItem(key) {
    const statusEl = document.getElementById(`asel-save-status-${key}`);
    // Validate: no available_model may have an empty model_id
    const cfg = autoselectConfig[key];
    const invalidModels = (cfg.available_models || []).filter(m => !(m.model_id || '').trim());
    if (invalidModels.length > 0) {
        if (statusEl) { statusEl.textContent = window.i18n.t('autoselect.error_empty_model_id'); statusEl.style.color = '#f87171'; }
        showAlert(window.i18n.t('autoselect.error_empty_model_id'), window.i18n.t('autoselect.invalid_key_title'), '⚠️', 'warn');
        return;
    }
    if (statusEl) statusEl.textContent = window.i18n.t('autoselect.saving');
    try {
        const result = await apiCall('POST', '/dashboard/api/autoselect', {
            autoselect_id: key,
            config: autoselectConfig[key]
        });
        if (result.success) {
            if (statusEl) { statusEl.textContent = window.i18n.t('autoselect.saved'); statusEl.style.color = '#4ade80'; setTimeout(() => { statusEl.textContent = ''; }, 3000); }
        } else {
            if (statusEl) { statusEl.textContent = window.i18n.t('autoselect.error_prefix') + ' ' + (result.error || 'Unknown'); statusEl.style.color = '#f87171'; }
        }
    } catch (e) {
        if (statusEl) { statusEl.textContent = window.i18n.t('autoselect.error_prefix') + ' ' + e.message; statusEl.style.color = '#f87171'; }
    }
}

async function copyAutoselect(sourceKey) {
    const newKey = await showPrompt(window.i18n.interpolate(window.i18n.t('autoselect.copy_prompt'), {key: sourceKey}), `${sourceKey}_copy`, 'autoselect-key', window.i18n.t('autoselect.copy_title'));
    if (!newKey) return;
    if (newKey === sourceKey) { showAlert(window.i18n.t('autoselect.key_different'), window.i18n.t('autoselect.invalid_key_title'), '⚠️', 'warn'); return; }
    if (autoselectConfig[newKey]) { showAlert(window.i18n.t('autoselect.key_exists'), window.i18n.t('autoselect.key_exists_title'), '⚠️', 'warn'); return; }
    const cloned = JSON.parse(JSON.stringify(autoselectConfig[sourceKey]));
    cloned.model_name = newKey;
    autoselectConfig[newKey] = cloned;
    try {
        const result = await apiCall('POST', '/dashboard/api/autoselect', { autoselect_id: newKey, config: cloned });
        if (!result.success) {
            showAlert('Error copying autoselect: ' + (result.error || 'Unknown'), 'Error', '❌', 'danger');
            delete autoselectConfig[newKey];
            return;
        }
    } catch (e) {
        showAlert('Error copying autoselect: ' + e.message, 'Error', '❌', 'danger');
        delete autoselectConfig[newKey];
        return;
    }
    if (!autoselectMasterOrder.includes(newKey)) autoselectMasterOrder.push(newKey);
    expandedAutoselects.add(newKey);
    renderAutoselectList();
}

async function addAutoselect() {
    const key = await showPrompt(window.i18n.t('autoselect.add_prompt'), '', 'e.g. autoselect', window.i18n.t('autoselect.add_title'));
    if (!key) return;
    if (autoselectConfig[key]) {
        showAlert(window.i18n.t('autoselect.key_exists'), window.i18n.t('autoselect.key_exists_title'), '⚠️', 'warn');
        return;
    }
    const newCfg = { model_name: key, description: '', selection_model: '', fallback: '', available_models: [] };
    autoselectConfig[key] = newCfg;
    try {
        const result = await apiCall('POST', '/dashboard/api/autoselect', { autoselect_id: key, config: newCfg });
        if (!result.success) {
            showAlert('Error creating autoselect: ' + (result.error || 'Unknown'), 'Error', '❌', 'danger');
            delete autoselectConfig[key];
            return;
        }
    } catch (e) {
        showAlert('Error creating autoselect: ' + e.message, 'Error', '❌', 'danger');
        delete autoselectConfig[key];
        return;
    }
    if (!autoselectMasterOrder.includes(key)) autoselectMasterOrder.push(key);
    expandedAutoselects.add(key);
    renderAutoselectList();
}

async function removeAutoselect(key) {
    if (await showDangerConfirm(window.i18n.interpolate(window.i18n.t('autoselect.remove_confirm'), {key}), window.i18n.t('autoselect.remove_title'))) {
        try {
            const result = await apiCall('DELETE', '/dashboard/api/autoselect/' + encodeURIComponent(key));
            if (!result.success) { showAlert('Error: ' + (result.error || 'Unknown'), 'Error', '❌', 'danger'); return; }
        } catch (e) { showAlert('Error: ' + e.message, 'Error', '❌', 'danger'); return; }
        delete autoselectConfig[key];
        autoselectMasterOrder = autoselectMasterOrder.filter(k => k !== key);
        expandedAutoselects.delete(key);
        renderAutoselectList();
    }
}

function updateAutoselect(key, field, value) {
    autoselectConfig[key][field] = value;
}

function updateAutoselectCapabilities(autoselectKey, value) {
    const trimmed = value.trim();
    if (!trimmed) {
        autoselectConfig[autoselectKey].capabilities = null;
        return;
    }
    
    // Split by comma and clean up
    autoselectConfig[autoselectKey].capabilities = 
        trimmed.split(',').map(s => s.trim()).filter(s => s);
}

function addAutoselectModel(autoselectKey) {
    if (!autoselectConfig[autoselectKey].available_models) {
        autoselectConfig[autoselectKey].available_models = [];
    }
    
    autoselectConfig[autoselectKey].available_models.push({
        model_id: '',
        description: ''
    });
    
    renderAutoselectModels(autoselectKey);
}

async function removeAutoselectModel(autoselectKey, index) {
    if (await showDangerConfirm(window.i18n.t('autoselect.remove_model_confirm'), window.i18n.t('autoselect.remove_model_title'))) {
        autoselectConfig[autoselectKey].available_models.splice(index, 1);
        renderAutoselectModels(autoselectKey);
    }
}

function updateAutoselectModel(autoselectKey, index, field, value) {
    autoselectConfig[autoselectKey].available_models[index][field] = value;
}

async function saveAutoselect() {
    // Validate all autoselects before submitting
    for (const [key, cfg] of Object.entries(autoselectConfig)) {
        const invalid = (cfg.available_models || []).filter(m => !(m.model_id || '').trim());
        if (invalid.length > 0) {
            showAlert(
                `Autoselect "${key}": ${window.i18n.t('autoselect.error_empty_model_id')}`,
                window.i18n.t('autoselect.invalid_key_title'), '⚠️', 'warn'
            );
            return;
        }
    }
    try {
        const response = await fetch(autoselectData.saveUrl, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: (function() {
                const orderedConfig = {};
                autoselectMasterOrder.forEach(k => { if (autoselectConfig[k]) orderedConfig[k] = autoselectConfig[k]; });
                return 'config=' + encodeURIComponent(JSON.stringify(orderedConfig, null, 2));
            })()
        });

        if (response.ok) {
            window.location.href = autoselectData.successUrl;
        } else {
            showAlert(window.i18n.t('autoselect.error_saving'), 'Error', '❌', 'danger');
        }
    } catch (error) {
        showAlert('Error: ' + error.message, 'Error', '❌', 'danger');
    }
}

// Initial render — defer until i18n is ready so translated strings are available
function _doInitialRender() { renderAutoselectList(); }
if (window.i18n) { _doInitialRender(); } else { document.addEventListener('i18n:ready', _doInitialRender, {once: true}); }
</script>

<style>
.autoselect-item {
    animation: fadeIn 0.3s;
}

.autoselect-header:hover {
    background: var(--bg-accent);
}

@keyframes fadeIn {
    from { opacity: 0; transform: translateY(-10px); }
    to { opacity: 1; transform: translateY(0); }
}

.form-group {
    margin-bottom: 15px;
}

.form-group label {
    display: block;
    margin-bottom: 5px;
    font-weight: 500;
}

.form-group input[type="text"],
.form-group textarea,
.form-group select {
    width: 100%;
    padding: 8px;
    border: 1px solid var(--color-border);
    border-radius: 3px;
    font-size: 14px;
}

.form-group input[type="checkbox"] {
    margin-right: 5px;
}
</style>
{% endblock %}
