{% extends "base.html" %}
{% block title %}Configuracoes - Viral Social Pro{% endblock %}
{% block nav_settings %}active{% endblock %}
{% block page_title %}Configuracoes{% endblock %}
{% block page_subtitle %}Personalize o comportamento da plataforma{% endblock %}

{% block content %}
<div x-data="settingsApp()" x-init="init()">

    <!-- Top actions -->
    <div class="flex items-center justify-between mb-6 animate-fade-up">
        <div class="flex gap-2">
            <button @click="exportSettings()" class="px-3 py-2 rounded-xl glass-light text-white/60 text-xs font-medium hover:text-white transition flex items-center gap-2">
                <i data-lucide="download" class="w-3.5 h-3.5"></i> Exportar
            </button>
            <label class="px-3 py-2 rounded-xl glass-light text-white/60 text-xs font-medium hover:text-white transition flex items-center gap-2 cursor-pointer">
                <i data-lucide="upload" class="w-3.5 h-3.5"></i> Importar
                <input type="file" accept=".json" @change="importSettings($event)" class="hidden">
            </label>
            <button @click="resetAll()" class="px-3 py-2 rounded-xl glass-light text-accent-red/60 text-xs font-medium hover:text-accent-red transition flex items-center gap-2">
                <i data-lucide="rotate-ccw" class="w-3.5 h-3.5"></i> Resetar Tudo
            </button>
        </div>
        <button @click="saveAll()" :disabled="!hasChanges" class="px-5 py-2.5 rounded-xl gradient-brand text-white font-semibold text-sm hover:opacity-90 transition flex items-center gap-2 disabled:opacity-30">
            <i data-lucide="save" class="w-4 h-4"></i> Salvar Alteracoes
        </button>
    </div>

    <!-- Category Tabs -->
    <div class="flex gap-2 mb-6 overflow-x-auto pb-1 animate-fade-up-delay">
        <template x-for="cat in categoryOrder" :key="cat">
            <button @click="activeCategory = cat" :class="activeCategory === cat ? 'active' : ''" class="tab-btn flex items-center gap-2 whitespace-nowrap">
                <i :data-lucide="categoryIcons[cat]" class="w-4 h-4"></i>
                <span x-text="categoryLabels[cat]"></span>
            </button>
        </template>
    </div>

    <!-- Loading -->
    <div x-show="loading" class="text-center py-12">
        <div class="w-5 h-5 border-2 border-brand-400 border-t-transparent rounded-full animate-spin mx-auto"></div>
    </div>

    <!-- YouTube Auth Widget (only in API Keys tab) -->
    <div x-show="!loading && activeCategory === 'api_keys'" x-data="ytAuthWidget()" x-init="checkStatus()" class="glass-card rounded-xl p-5 mb-4 border" :class="authenticated ? 'border-emerald-500/30' : 'border-amber-500/30'">
        <div class="flex items-center justify-between mb-3">
            <div class="flex items-center gap-3">
                <div class="w-10 h-10 rounded-xl flex items-center justify-center" :class="authenticated ? 'bg-emerald-500/20' : 'bg-amber-500/20'">
                    <i data-lucide="youtube" class="w-5 h-5" :class="authenticated ? 'text-emerald-400' : 'text-amber-400'"></i>
                </div>
                <div>
                    <h3 class="text-sm font-bold text-white/90">YouTube Download Auth</h3>
                    <p class="text-xs text-white/40" x-text="authenticated ? 'Conectado - downloads funcionando' : 'Necessario para baixar videos do YouTube'"></p>
                </div>
            </div>
            <span class="px-2.5 py-1 rounded-lg text-[10px] font-bold uppercase" :class="authenticated ? 'bg-emerald-500/20 text-emerald-400' : 'bg-amber-500/20 text-amber-400'" x-text="authenticated ? 'Conectado' : 'Desconectado'"></span>
        </div>

        <!-- Not authenticated: show connect button -->
        <div x-show="!authenticated && !pending">
            <p class="text-xs text-white/50 mb-3">O YouTube bloqueia downloads de servidores. Conecte uma conta Google para desbloquear. Voce so precisa fazer isso <strong class="text-white/70">uma unica vez</strong>.</p>
            <button @click="startAuth()" :disabled="authLoading" class="px-4 py-2 rounded-xl gradient-brand text-white font-semibold text-sm hover:opacity-90 transition disabled:opacity-50 flex items-center gap-2">
                <i data-lucide="link" class="w-4 h-4"></i>
                <span x-text="authLoading ? 'Gerando codigo...' : 'Conectar YouTube'"></span>
            </button>
        </div>

        <!-- Pending: show code -->
        <div x-show="pending && authCode" class="space-y-3">
            <p class="text-xs text-white/50">Abra o link abaixo no seu celular ou computador e insira o codigo:</p>
            <div class="flex items-center gap-4">
                <div class="bg-dark-700 rounded-xl px-6 py-3 text-center">
                    <p class="text-[10px] text-white/40 mb-1">Codigo</p>
                    <p class="text-2xl font-mono font-bold text-brand-400 tracking-wider" x-text="authCode"></p>
                </div>
                <div class="flex-1">
                    <a href="https://www.google.com/device" target="_blank" class="text-brand-400 hover:text-brand-300 text-sm font-semibold underline">google.com/device</a>
                    <p class="text-[10px] text-white/30 mt-1">Apos autorizar, aguarde alguns segundos...</p>
                </div>
            </div>
            <div class="flex items-center gap-2 text-xs text-white/30">
                <div class="w-3 h-3 border-2 border-brand-400 border-t-transparent rounded-full animate-spin"></div>
                Aguardando autorizacao...
            </div>
        </div>

        <!-- Authenticated: show disconnect -->
        <div x-show="authenticated" class="flex items-center gap-3">
            <button @click="revoke()" class="px-3 py-1.5 rounded-lg glass-card text-red-400 text-xs font-medium hover:bg-red-500/10 transition">Desconectar</button>
        </div>
    </div>

    <!-- Settings Grid -->
    <div x-show="!loading" class="space-y-4">
        <template x-for="(value, key) in filteredSettings()" :key="key">
            <div class="glass-card rounded-xl p-4">
                <div class="flex items-start justify-between gap-4">
                    <div class="flex-1 min-w-0">
                        <label class="text-sm font-semibold text-white/90 block mb-1" x-text="formatLabel(key)"></label>
                        <p class="text-xs text-white/30 mb-3" x-text="getDescription(key)"></p>

                        <!-- Boolean toggle -->
                        <template x-if="isBool(key, value)">
                            <button @click="toggleBool(key)" class="relative w-12 h-6 rounded-full transition-colors" :class="pendingSettings[key] === 'true' ? 'bg-brand-500' : 'bg-dark-600'">
                                <div class="absolute top-1 w-4 h-4 rounded-full bg-white transition-transform" :class="pendingSettings[key] === 'true' ? 'left-7' : 'left-1'"></div>
                            </button>
                        </template>

                        <!-- Select dropdown -->
                        <template x-if="hasOptions(key)">
                            <select @change="updateSetting(key, $event.target.value)" :value="pendingSettings[key]" class="bg-dark-700 border border-white/10 rounded-xl px-4 py-2.5 text-sm text-white/80 w-full max-w-md focus:border-brand-500 outline-none">
                                <template x-for="opt in getOptions(key)" :key="opt.value">
                                    <option :value="opt.value" :selected="pendingSettings[key] === opt.value" x-text="opt.label"></option>
                                </template>
                            </select>
                        </template>

                        <!-- Color picker -->
                        <template x-if="isColor(key)">
                            <div class="flex items-center gap-3">
                                <input type="color" :value="pendingSettings[key]" @input="updateSetting(key, $event.target.value)" class="w-10 h-10 rounded-lg border-2 border-white/10 cursor-pointer bg-transparent">
                                <input type="text" :value="pendingSettings[key]" @input="updateSetting(key, $event.target.value)" class="bg-dark-700 border border-white/10 rounded-xl px-4 py-2.5 text-sm text-white/80 w-32 font-mono">
                            </div>
                        </template>

                        <!-- Password/API key -->
                        <template x-if="isSecret(key)">
                            <div class="flex items-center gap-2 max-w-md">
                                <div class="flex-1 flex items-center bg-dark-700 border border-white/10 rounded-xl px-4 py-2.5">
                                    <input :type="showSecrets[key] ? 'text' : 'password'" :value="pendingSettings[key]" @input="updateSetting(key, $event.target.value)" class="bg-transparent border-none outline-none text-sm text-white/80 w-full font-mono" placeholder="Insira a chave...">
                                    <button @click="showSecrets[key] = !showSecrets[key]" class="ml-2 text-white/30 hover:text-white/60">
                                        <i :data-lucide="showSecrets[key] ? 'eye-off' : 'eye'" class="w-4 h-4"></i>
                                    </button>
                                </div>
                            </div>
                        </template>

                        <!-- Number input -->
                        <template x-if="isNumber(key, value) && !isBool(key, value) && !hasOptions(key)">
                            <input type="number" :value="pendingSettings[key]" @input="updateSetting(key, $event.target.value)" class="bg-dark-700 border border-white/10 rounded-xl px-4 py-2.5 text-sm text-white/80 w-40 focus:border-brand-500 outline-none" :step="isFloat(key) ? '0.01' : '1'">
                        </template>

                        <!-- Textarea for lists -->
                        <template x-if="isList(key)">
                            <textarea :value="pendingSettings[key]" @input="updateSetting(key, $event.target.value)" class="bg-dark-700 border border-white/10 rounded-xl px-4 py-2.5 text-sm text-white/80 w-full max-w-md h-20 focus:border-brand-500 outline-none resize-y" placeholder="Valores separados por virgula"></textarea>
                        </template>

                        <!-- Text input (default) -->
                        <template x-if="isText(key, value)">
                            <input type="text" :value="pendingSettings[key]" @input="updateSetting(key, $event.target.value)" class="bg-dark-700 border border-white/10 rounded-xl px-4 py-2.5 text-sm text-white/80 w-full max-w-md focus:border-brand-500 outline-none">
                        </template>
                    </div>
                </div>
            </div>
        </template>
    </div>

    <!-- Backup section at bottom -->
    <div class="glass rounded-2xl p-6 mt-8 animate-fade-up">
        <h3 class="text-base font-bold text-white/90 mb-4 flex items-center gap-2">
            <i data-lucide="hard-drive" class="w-5 h-5 text-brand-400"></i> Backup & Dados
        </h3>
        <div class="grid grid-cols-1 sm:grid-cols-3 gap-3">
            <a href="/api/backup/download" class="glass-card rounded-xl p-4 text-center hover:scale-[1.02] transition-transform block">
                <i data-lucide="database" class="w-8 h-8 text-accent-cyan mx-auto mb-2"></i>
                <p class="text-sm font-semibold text-white/80">Baixar Banco de Dados</p>
                <p class="text-xs text-white/30 mt-1">Download do SQLite</p>
            </a>
            <a href="/api/backup/download-full" class="glass-card rounded-xl p-4 text-center hover:scale-[1.02] transition-transform block">
                <i data-lucide="folder-archive" class="w-8 h-8 text-accent-green mx-auto mb-2"></i>
                <p class="text-sm font-semibold text-white/80">Backup Completo</p>
                <p class="text-xs text-white/30 mt-1">Codigo + Banco (ZIP)</p>
            </a>
            <button @click="pushGithub()" class="glass-card rounded-xl p-4 text-center hover:scale-[1.02] transition-transform">
                <i data-lucide="github" class="w-8 h-8 text-white/60 mx-auto mb-2"></i>
                <p class="text-sm font-semibold text-white/80">Push para GitHub</p>
                <p class="text-xs text-white/30 mt-1">Salvar no repositorio</p>
            </button>
        </div>
    </div>
</div>
{% endblock %}

{% block scripts %}
<script>
function settingsApp() {
    return {
        loading: true,
        activeCategory: 'general',
        settings: {},
        pendingSettings: {},
        originalSettings: {},
        hasChanges: false,
        showSecrets: {},

        categoryOrder: ['general', 'api_keys', 'scanner', 'discovery', 'viral_score', 'shop', 'alerts', 'feed', 'calendar', 'creators', 'downloads', 'backup', 'advanced'],
        categoryLabels: {
            general: 'Geral', api_keys: 'Chaves API', scanner: 'Viral Scanner',
            discovery: 'Descoberta', viral_score: 'Score Viral', shop: 'TikTok Shop',
            alerts: 'Alertas', feed: 'Feed', calendar: 'Calendario', creators: 'Criadores',
            downloads: 'Downloads', backup: 'Backup', advanced: 'Avancado'
        },
        categoryIcons: {
            general: 'settings', api_keys: 'key', scanner: 'scan-search',
            discovery: 'search', viral_score: 'flame', shop: 'shopping-bag',
            alerts: 'bell', feed: 'rss', calendar: 'calendar', creators: 'users',
            downloads: 'download', backup: 'hard-drive', advanced: 'terminal'
        },

        // Field descriptions
        descriptions: {
            app_name: 'Nome exibido no topo da plataforma',
            app_language: 'Idioma da interface',
            timezone: 'Fuso horario para calculos de datas',
            default_region: 'Regiao padrao para buscas (BR, US, etc)',
            dark_mode: 'Ativar modo escuro',
            brand_color: 'Cor principal da marca',
            items_per_page: 'Quantidade de itens por pagina nas listagens',
            scrapecreators_api_key: 'Chave da API ScrapeCreators (TikTok, Instagram, YouTube, Shop)',
            youtube_api_key: 'Chave da API do YouTube Data v3',
            apify_api_token: 'Token da API Apify para scraping avancado',
            discovery_auto_enabled: 'Executar descoberta automatica de videos virais',
            discovery_interval_hours: 'Intervalo em horas entre descobertas automaticas',
            discovery_max_per_platform: 'Maximo de videos por plataforma na descoberta',
            discovery_platforms: 'Plataformas ativas na descoberta (separadas por virgula)',
            discovery_min_views: 'Minimo de views para considerar um video relevante',
            discovery_min_likes: 'Minimo de likes para considerar um video relevante',
            discovery_keywords: 'Keywords para busca automatica (separadas por virgula)',
            viral_score_weight_views: 'Peso das views no calculo do score viral (0-1)',
            viral_score_weight_likes: 'Peso dos likes no calculo do score viral (0-1)',
            viral_score_weight_comments: 'Peso dos comentarios no calculo do score viral (0-1)',
            viral_score_weight_shares: 'Peso dos compartilhamentos no calculo do score viral (0-1)',
            viral_score_weight_engagement: 'Peso do engajamento geral no calculo do score viral (0-1)',
            viral_score_min_display: 'Score minimo para exibir um video no feed',
            viral_score_threshold_hot: 'Score para marcar como HOT (badge laranja)',
            viral_score_threshold_fire: 'Score para marcar como FIRE (badge vermelho)',
            shop_auto_monitor: 'Monitorar novos produtos automaticamente ao detectar',
            shop_snapshot_interval_hours: 'Intervalo entre snapshots de estoque (horas)',
            shop_min_sold_count: 'Minimo de vendas para considerar produto relevante',
            shop_categories_br: 'Categorias BR ativas (separadas por virgula)',
            shop_auto_detect_enabled: 'Detectar produtos virais automaticamente',
            shop_auto_detect_interval_hours: 'Intervalo entre deteccoes automaticas (horas)',
            shop_cross_platform_keywords: 'Keywords para deteccao cross-platform',
            alerts_enabled: 'Ativar sistema de alertas',
            alert_viral_threshold: 'Score viral minimo para disparar alerta',
            alert_views_spike: 'Pico de views para alerta (acima desse valor)',
            alert_new_trending: 'Alertar quando novo conteudo estiver em trending',
            alert_product_sales_spike: 'Pico de vendas (delta) para alerta de produto',
            alert_sound_enabled: 'Ativar som nos alertas',
            calendar_platforms: 'Plataformas do calendario de conteudo',
            calendar_posts_per_day: 'Posts sugeridos por dia no calendario',
            calendar_best_time_analysis_days: 'Dias de historico para analise de melhores horarios',
            download_path: 'Pasta de destino dos downloads',
            download_max_concurrent: 'Downloads simultaneos maximo',
            download_auto_thumbnail: 'Baixar thumbnail automaticamente',
            download_watermark_remove: 'Remover marca d\'agua dos videos',
            download_max_resolution: 'Resolucao maxima (720, 1080, 4K)',
            backup_auto_enabled: 'Backup automatico diario',
            backup_interval_hours: 'Intervalo entre backups (horas)',
            backup_keep_days: 'Dias para manter backups locais',
            backup_push_github: 'Enviar backup para GitHub automaticamente',
            feed_auto_refresh: 'Atualizar feed automaticamente',
            feed_refresh_interval_seconds: 'Intervalo de atualizacao do feed (segundos)',
            feed_default_sort: 'Ordenacao padrao do feed',
            feed_show_platform_badges: 'Mostrar badges de plataforma nos cards',
            feed_card_style: 'Estilo dos cards no feed',
            feed_show_engagement_rate: 'Mostrar taxa de engajamento nos cards',
            creators_auto_track: 'Rastrear criadores automaticamente ao encontrar',
            creators_min_followers: 'Minimo de seguidores para rastrear criador',
            creators_growth_alert_percent: 'Percentual de crescimento para alerta',
            api_rate_limit_per_minute: 'Limite de requests da API por minuto',
            cache_ttl_seconds: 'Tempo de vida do cache (segundos)',
            log_level: 'Nivel de log (DEBUG, INFO, WARNING, ERROR)',
            debug_mode: 'Modo debug (mais logs, sem cache)',
            data_retention_days: 'Dias para manter dados antigos',
            scanner_enabled: 'Ativar scanner automatico de videos virais',
            scanner_interval_minutes: 'Intervalo entre scans automaticos (minutos, min 10)',
            scanner_keywords: 'Keywords para busca automatica (separadas por virgula)',
            scanner_max_keywords_per_cycle: 'Maximo de keywords por ciclo (cada uma gasta 1 credito)',
            scanner_results_per_keyword: 'Resultados por keyword (max 30)',
            scanner_min_views_to_save: 'Minimo de views para salvar video (reduz lixo no banco)',
            scanner_min_viral_score: 'Score viral minimo para salvar (0 = salvar todos)',
            scanner_only_with_product: 'Salvar apenas videos com produto TikTok Shop',
            scanner_daily_credit_limit: 'Limite diario de creditos API (protecao contra gasto excessivo)',
            scanner_api_delay_seconds: 'Delay entre requests da API (segundos, protecao anti-block)',
            scanner_creative_center_enabled: 'Usar Creative Center para descobrir keywords (GRATIS)',
            scanner_creative_center_interval_minutes: 'Intervalo do Creative Center (minutos)',
            scanner_auto_detect_products: 'Auto-detectar shop_product_url nos videos',
            scanner_dedup_enabled: 'Evitar salvar videos duplicados',
            scanner_alert_mega_viral: 'Alertar quando encontrar video MEGA VIRAL (score > 90)',
        },

        // Options for select fields
        optionsMap: {
            app_language: [{value:'pt-BR', label:'Portugues (BR)'}, {value:'en-US', label:'English (US)'}, {value:'es', label:'Espanol'}],
            default_region: [{value:'BR', label:'Brasil'}, {value:'US', label:'Estados Unidos'}, {value:'GB', label:'Reino Unido'}, {value:'MX', label:'Mexico'}, {value:'AR', label:'Argentina'}, {value:'PT', label:'Portugal'}],
            feed_default_sort: [{value:'viral_score', label:'Score Viral'}, {value:'views', label:'Views'}, {value:'likes', label:'Likes'}, {value:'recent', label:'Mais Recentes'}, {value:'engagement', label:'Engajamento'}],
            feed_card_style: [{value:'compact', label:'Compacto'}, {value:'full', label:'Expandido'}, {value:'minimal', label:'Minimalista'}],
            log_level: [{value:'DEBUG', label:'Debug'}, {value:'INFO', label:'Info'}, {value:'WARNING', label:'Warning'}, {value:'ERROR', label:'Error'}],
            download_max_resolution: [{value:'720', label:'720p'}, {value:'1080', label:'1080p (Full HD)'}, {value:'2160', label:'4K'}],
        },

        // Secret fields (show as password)
        secretFields: ['scrapecreators_api_key', 'youtube_api_key', 'apify_api_token'],
        // List fields (comma-separated)
        listFields: ['discovery_platforms', 'discovery_keywords', 'shop_categories_br', 'shop_cross_platform_keywords', 'calendar_platforms', 'scanner_keywords'],
        // Color fields
        colorFields: ['brand_color'],
        // Float fields
        floatFields: ['viral_score_weight_views', 'viral_score_weight_likes', 'viral_score_weight_comments', 'viral_score_weight_shares', 'viral_score_weight_engagement'],

        async init() {
            await this.loadSettings();
            this.$nextTick(() => { if (window.lucide) lucide.createIcons(); });
        },

        async loadSettings() {
            this.loading = true;
            try {
                const r = await fetch('/api/settings/all');
                const d = await r.json();
                this.settings = d.settings || {};
                // Flatten to key:value
                this.pendingSettings = {};
                this.originalSettings = {};
                for (const [cat, entries] of Object.entries(this.settings)) {
                    for (const [k, v] of Object.entries(entries)) {
                        this.pendingSettings[k] = v;
                        this.originalSettings[k] = v;
                    }
                }
            } catch(e) { showToast('Erro ao carregar configuracoes', 'error'); }
            this.loading = false;
            this.$nextTick(() => { if (window.lucide) lucide.createIcons(); });
        },

        filteredSettings() {
            const result = {};
            for (const [k, v] of Object.entries(this.pendingSettings)) {
                const cat = this.getCategory(k);
                if (cat === this.activeCategory) result[k] = v;
            }
            return result;
        },

        getCategory(key) {
            for (const [cat, entries] of Object.entries(this.settings)) {
                if (key in entries) return cat;
            }
            return 'general';
        },

        updateSetting(key, value) {
            this.pendingSettings[key] = value;
            this.hasChanges = JSON.stringify(this.pendingSettings) !== JSON.stringify(this.originalSettings);
        },

        toggleBool(key) {
            this.pendingSettings[key] = this.pendingSettings[key] === 'true' ? 'false' : 'true';
            this.hasChanges = true;
        },

        async saveAll() {
            const changed = {};
            for (const [k, v] of Object.entries(this.pendingSettings)) {
                if (v !== this.originalSettings[k]) changed[k] = v;
            }
            if (Object.keys(changed).length === 0) return;
            try {
                for (const [k, v] of Object.entries(changed)) {
                    await fetch(`/api/settings/${k}?value=${encodeURIComponent(v)}`, { method: 'PUT' });
                }
                this.originalSettings = {...this.pendingSettings};
                this.hasChanges = false;
                showToast(`${Object.keys(changed).length} configuracoes salvas!`, 'success');
            } catch(e) { showToast('Erro ao salvar', 'error'); }
        },

        async resetAll() {
            if (!confirm('Tem certeza que deseja resetar TODAS as configuracoes para o padrao?')) return;
            try {
                await fetch('/api/settings/reset', { method: 'POST' });
                await this.loadSettings();
                showToast('Configuracoes resetadas!', 'success');
            } catch(e) { showToast('Erro', 'error'); }
        },

        async exportSettings() {
            try {
                const r = await fetch('/api/settings/export', { method: 'POST' });
                const d = await r.json();
                const blob = new Blob([JSON.stringify(d, null, 2)], { type: 'application/json' });
                const url = URL.createObjectURL(blob);
                const a = document.createElement('a'); a.href = url; a.download = 'viral_social_settings.json'; a.click();
                URL.revokeObjectURL(url);
                showToast('Configuracoes exportadas!', 'success');
            } catch(e) { showToast('Erro', 'error'); }
        },

        async importSettings(event) {
            const file = event.target.files[0];
            if (!file) return;
            try {
                const text = await file.text();
                const data = JSON.parse(text);
                const r = await fetch('/api/settings/import', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data) });
                const d = await r.json();
                showToast(`${d.imported} configuracoes importadas!`, 'success');
                await this.loadSettings();
            } catch(e) { showToast('Erro ao importar', 'error'); }
        },

        async pushGithub() {
            showToast('Enviando backup para GitHub...', 'info');
            try {
                const r = await fetch('/api/backup/push-github', { method: 'POST' });
                const d = await r.json();
                showToast(d.status === 'ok' ? 'Backup enviado ao GitHub!' : 'Erro: ' + d.error, d.status === 'ok' ? 'success' : 'error');
            } catch(e) { showToast('Erro', 'error'); }
        },

        // Field type detection
        isBool(key, value) { return value === 'true' || value === 'false'; },
        hasOptions(key) { return key in this.optionsMap; },
        getOptions(key) { return this.optionsMap[key] || []; },
        isSecret(key) { return this.secretFields.includes(key); },
        isList(key) { return this.listFields.includes(key); },
        isColor(key) { return this.colorFields.includes(key); },
        isFloat(key) { return this.floatFields.includes(key); },
        isNumber(key, value) { return !this.isSecret(key) && !this.isList(key) && !this.isColor(key) && /^\d+\.?\d*$/.test(value); },
        isText(key, value) {
            return !this.isBool(key, value) && !this.hasOptions(key) && !this.isSecret(key) &&
                   !this.isList(key) && !this.isColor(key) && !this.isNumber(key, value);
        },

        formatLabel(key) {
            return key.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase())
                .replace('Api', 'API').replace('Br', 'BR').replace('Url', 'URL')
                .replace('Ttl', 'TTL').replace('Hr', 'hr');
        },
        getDescription(key) { return this.descriptions[key] || ''; },
    }
}

function ytAuthWidget() {
    return {
        authenticated: false,
        pending: false,
        authCode: null,
        authLoading: false,
        pollTimer: null,

        async checkStatus() {
            try {
                const r = await fetch('/api/youtube/auth/status');
                const d = await r.json();
                this.authenticated = d.authenticated;
                this.pending = d.pending;
                this.authCode = d.code;
                if (d.pending && d.code) this.startPolling();
            } catch(e) {}
            this.$nextTick(() => { if(window.lucide) lucide.createIcons(); });
        },

        async startAuth() {
            this.authLoading = true;
            try {
                const r = await fetch('/api/youtube/auth/start', { method: 'POST' });
                const d = await r.json();
                if (d.code) {
                    this.authCode = d.code;
                    this.pending = true;
                    this.startPolling();
                } else if (d.error) {
                    showToast(d.error, 'error');
                }
            } catch(e) {
                showToast('Erro ao iniciar autenticacao', 'error');
            }
            this.authLoading = false;
            this.$nextTick(() => { if(window.lucide) lucide.createIcons(); });
        },

        startPolling() {
            if (this.pollTimer) clearInterval(this.pollTimer);
            this.pollTimer = setInterval(async () => {
                try {
                    const r = await fetch('/api/youtube/auth/status');
                    const d = await r.json();
                    if (d.authenticated) {
                        this.authenticated = true;
                        this.pending = false;
                        this.authCode = null;
                        clearInterval(this.pollTimer);
                        showToast('YouTube conectado com sucesso!', 'success');
                        this.$nextTick(() => { if(window.lucide) lucide.createIcons(); });
                    } else if (!d.pending) {
                        this.pending = false;
                        this.authCode = null;
                        clearInterval(this.pollTimer);
                        if (d.error) showToast(d.error, 'error');
                    }
                } catch(e) {}
            }, 3000);
        },

        async revoke() {
            try {
                await fetch('/api/youtube/auth/revoke', { method: 'POST' });
                this.authenticated = false;
                showToast('YouTube desconectado', 'info');
            } catch(e) {}
            this.$nextTick(() => { if(window.lucide) lucide.createIcons(); });
        },
    }
}
</script>
{% endblock %}
