// Config Options - Centralized configuration options for dropdown fields
class ConfigOptions {

  // Per-app form renders id="GLUETUN_VPN_*"; global form renders id="config-CFG_GLUETUN_VPN_*".
  static findGluetunProviderEl() {
    return document.getElementById('config-CFG_GLUETUN_VPN_SERVICE_PROVIDER')
        || document.getElementById('GLUETUN_VPN_SERVICE_PROVIDER');
  }
  static findGluetunVpnTypeEl() {
    return document.getElementById('config-CFG_GLUETUN_VPN_TYPE')
        || document.getElementById('GLUETUN_VPN_TYPE');
  }
  static findGluetunFieldEl(suffix) {
    return document.getElementById(`config-CFG_GLUETUN_${suffix}`)
        || document.getElementById(`GLUETUN_${suffix}`);
  }

  // Show only the credential fields that match the selected VPN type.
  static refreshGluetunCredentialVisibility() {
    const typeEl = this.findGluetunVpnTypeEl();
    if (!typeEl) return;
    const type = (typeEl.value || '').toLowerCase();
    const wg = ['WIREGUARD_PRIVATE_KEY', 'WIREGUARD_ADDRESSES'];
    const ov = ['OPENVPN_USER', 'OPENVPN_PASSWORD'];
    const setVisible = (suffix, visible) => {
      const el = this.findGluetunFieldEl(suffix);
      if (!el) return;
      const wrapper = el.closest('.form-field') || el.parentElement;
      if (wrapper) wrapper.style.display = visible ? '' : 'none';
    };
    wg.forEach((s) => setVisible(s, type === 'wireguard'));
    ov.forEach((s) => setVisible(s, type === 'openvpn'));
    this.refreshMullvadGenerateButton(type);
  }

  static refreshMullvadGenerateButton(typeValue) {
    const providerEl = this.findGluetunProviderEl();
    const provider = (providerEl?.value || '').toLowerCase();
    const type = (typeValue || this.findGluetunVpnTypeEl()?.value || '').toLowerCase();
    const shouldShow = provider === 'mullvad' && type === 'wireguard';

    document.querySelectorAll('.mullvad-generate-field').forEach(b => b.remove());
    if (!shouldShow) return;

    const typeEl = this.findGluetunVpnTypeEl();
    const anchor = typeEl && typeEl.closest('.form-field');
    if (!anchor) return;

    const keyEl = this.findGluetunFieldEl('WIREGUARD_PRIVATE_KEY');
    const addrEl = this.findGluetunFieldEl('WIREGUARD_ADDRESSES');
    const configured = !!(keyEl?.value && addrEl?.value);

    const block = document.createElement('div');
    block.className = 'form-field mullvad-generate-field';
    block.innerHTML = `
      <label class="form-label">Mullvad WireGuard</label>
      <div class="mullvad-generate-actions">
        <button type="button" class="btn btn-secondary mullvad-generate-btn">Generate from Mullvad account</button>
        <span class="mullvad-generate-status${configured ? ' is-configured' : ''}">
          <span class="mullvad-generate-tick">${configured ? '✓' : ''}</span>
          <span class="mullvad-generate-status-text">${configured ? 'Configured' : 'Not configured'}</span>
        </span>
      </div>
      <small class="form-help">Generates a WireGuard key against your Mullvad account and fills the credentials below.</small>
    `;
    block.querySelector('.mullvad-generate-btn')
      .addEventListener('click', () => window.appsManager?.openMullvadGenerateModal?.());
    anchor.insertAdjacentElement('afterend', block);
  }

  static refreshMullvadGenerateStatus() {
    const status = document.querySelector('.mullvad-generate-field .mullvad-generate-status');
    if (!status) return;
    const keyEl = this.findGluetunFieldEl('WIREGUARD_PRIVATE_KEY');
    const addrEl = this.findGluetunFieldEl('WIREGUARD_ADDRESSES');
    const configured = !!(keyEl?.value && addrEl?.value);
    status.classList.toggle('is-configured', configured);
    status.querySelector('.mullvad-generate-tick').textContent = configured ? '✓' : '';
    status.querySelector('.mullvad-generate-status-text').textContent = configured ? 'Configured' : 'Not configured';
  }

  static loadGluetunProviderIcons() {
    if (this._gluetunIconsPromise) return this._gluetunIconsPromise;
    this._gluetunIconsPromise = (async () => {
      try {
        const res = await fetch('/data/apps/gluetun-provider-icons.json', { cache: 'no-store' });
        if (!res.ok) return {};
        return await res.json();
      } catch { return {}; }
    })();
    this._gluetunIconsPromise.then((m) => { window.gluetunProviderIcons = m || {}; });
    return this._gluetunIconsPromise;
  }
  static _gluetunIconsPromise = null;

  // Pulled from gluetun's upstream servers.json by appWebuiRefresh_gluetun.
  // Generator writes to /data/apps/generated/; static fallback ships at /data/apps/.
  // We try generated first, fall back to bundled, fall back to a tiny static list.
  static _gluetunProvidersPromise = null;
  static loadGluetunProviders() {
    if (this._gluetunProvidersPromise) return this._gluetunProvidersPromise;
    this._gluetunProvidersPromise = (async () => {
      const tryFetch = async (url) => {
        try {
          const res = await fetch(url, { cache: 'no-store' });
          if (!res.ok) return null;
          const json = await res.json();
          return json && json.providers ? json.providers : null;
        } catch { return null; }
      };
      const live = await tryFetch('/data/apps/generated/gluetun-providers.json');
      if (live) return live;
      const fallback = await tryFetch('/data/apps/gluetun-providers.json');
      if (fallback) return fallback;
      return null;
    })();
    this._gluetunProvidersPromise.then((p) => {
      window.gluetunProviders = p;
      // If the provider field rendered before this finished, repopulate it
      // (and the VPN-type field, which depends on the selected provider).
      const sel = ConfigOptions.findGluetunProviderEl();
      if (sel && p) {
        const previous = sel.value;
        const opts = ConfigOptions.getGluetunProviderOptions();
        sel.innerHTML = opts.map((o) =>
          `<option value="${o.value}" ${o.value === previous ? 'selected' : ''}>${o.label}</option>`
        ).join('');
        ConfigOptions.refreshGluetunVpnTypeOptions();
      }
      ConfigOptions.refreshGluetunCredentialVisibility();
    });
    return this._gluetunProvidersPromise;
  }

  static getGluetunProviderOptions() {
    const providers = window.gluetunProviders;
    if (!providers) {
      this.loadGluetunProviders();
      return [
        { value: 'mullvad', label: 'Mullvad' },
        { value: 'nordvpn', label: 'NordVPN' },
        { value: 'protonvpn', label: 'ProtonVPN' },
        { value: 'surfshark', label: 'Surfshark' },
        { value: 'custom', label: 'Custom (manual config)' }
      ];
    }
    const titleCase = (s) => s.replace(/\b\w/g, (c) => c.toUpperCase());
    return Object.keys(providers).sort().map((slug) => ({
      value: slug,
      label: slug === 'custom' ? 'Custom (manual config)' : titleCase(slug)
    }));
  }

  // Repaint the VPN-type <select> based on the currently chosen provider.
  // Called from a delegated change listener so we don't touch the renderer.
  static refreshGluetunVpnTypeOptions() {
    const sel = ConfigOptions.findGluetunVpnTypeEl();
    if (!sel) return;
    const previous = sel.value;
    const opts = this.getGluetunVpnTypeOptions();
    const stillValid = opts.some((o) => o.value === previous);
    sel.innerHTML = opts.map((o) =>
      `<option value="${o.value}" ${(stillValid ? o.value === previous : false) || (!stillValid && o.value === opts[0].value) ? 'selected' : ''}>${o.label}</option>`
    ).join('');
    this.refreshGluetunCredentialVisibility();
  }

  static getGluetunVpnTypeOptions() {
    const providers = window.gluetunProviders;
    const selected = (typeof document !== 'undefined' && ConfigOptions.findGluetunProviderEl())
      ? ConfigOptions.findGluetunProviderEl().value
      : null;
    if (providers && selected && providers[selected] && Array.isArray(providers[selected].vpnTypes) && providers[selected].vpnTypes.length) {
      return providers[selected].vpnTypes.map((t) => ({
        value: t,
        label: t === 'openvpn' ? 'OpenVPN' : (t === 'wireguard' ? 'WireGuard' : t)
      }));
    }
    return [
      { value: 'wireguard', label: 'WireGuard' },
      { value: 'openvpn', label: 'OpenVPN' }
    ];
  }

  // Get select options for specific config keys
  static getSelectOptions(key) {
    //console.log('=== getSelectOptions ENTRY === called with:', key);
    const optionMaps = {
      'CFG_DOCKER_INSTALL_TYPE': [
        { value: 'rooted', label: 'Rooted' },
        { value: 'rootless', label: 'Rootless' }
      ],
      'CFG_ROOTLESS_NET': [
        { value: 'pasta', label: 'Pasta (recommended)' },
        { value: 'slirp4netns', label: 'slirp4netns (fallback)' }
      ],
      'CFG_UFW_LOGGING': [
        { value: 'off', label: 'Off' },
        { value: 'low', label: 'Low' },
        { value: 'medium', label: 'Medium' },
        { value: 'high', label: 'High' },
        { value: 'full', label: 'Full' }
      ],
      'CFG_TEXT_EDITOR': [
        { value: 'nano', label: 'Nano' },
        { value: 'vim', label: 'Vim' }
      ],
      'CFG_INSTALL_MODE': [
        { value: 'git', label: 'Git Repository' },
        { value: 'local', label: 'Local Folder' }
      ],
      'CFG_MAIL_SECURE': [
        { value: 'tls', label: 'TLS' },
        { value: 'ssl', label: 'SSL' },
        { value: 'none', label: 'None' }
      ],
      'CFG_TRAEFIK_DASHBOARD_ACCESS': [
        { value: 'local-only', label: 'Local + Domain (recommended)' },
        { value: 'domain-only', label: 'Domain only (most secure)' },
        { value: 'public', label: 'Public + Domain (legacy, unauthenticated on :8080)' }
      ],
    };

    if (key === 'CFG_GLUETUN_VPN_SERVICE_PROVIDER') return this.getGluetunProviderOptions();
    if (key === 'CFG_GLUETUN_VPN_TYPE') return this.getGluetunVpnTypeOptions();

    // Generator-emitted options take precedence — they come from the
    // [value:Label|...] block in the config file's inline comment, so a
    // CFG file change auto-flows through to the dropdown without
    // touching this file. The hardcoded cases below stay as a safety
    // net for keys whose options are computed or theme-specific.
    const generated = window.configData && window.configData.config &&
                      window.configData.config[key] &&
                      window.configData.config[key].options;
    if (Array.isArray(generated) && generated.length > 0) {
      return generated;
    }

    // Per-location backup dropdowns (CFG_BACKUP_LOC_<n>_*). Their options are
    // static and identical for every location, but the config generator only
    // scans flat per-category files — it never descends into the nested
    // configs/backup/locations/<n>/ dir — so configData carries no options for
    // these keys. Resolve them here by suffix so every location index works,
    // including ones added after install. (The global CFG_BACKUP_ENGINE/
    // STRATEGY still come from the generator via the check above.)
    const locDropdown = key.match(/^CFG_BACKUP_LOC_[0-9]+_(TYPE|PATH_MODE|ENGINE|SSH_AUTH)$/);
    if (locDropdown) {
      const BACKUP_LOC_OPTIONS = {
        TYPE: [
          { value: 'local',  label: 'Local / mounted path' },
          { value: 'sftp',   label: 'SFTP' },
          { value: 'rest',   label: 'REST' },
          { value: 's3',     label: 'S3' },
          { value: 'b2',     label: 'Backblaze B2' },
          { value: 'gs',     label: 'Google Cloud Storage' },
          { value: 'azure',  label: 'Azure' },
          { value: 'rclone', label: 'rclone' }
        ],
        PATH_MODE: [
          { value: 'auto',   label: 'Automatic (backups root, one subfolder per location)' },
          { value: 'custom', label: 'Custom path' }
        ],
        ENGINE: [
          { value: 'restic', label: 'Restic' },
          { value: 'borg',   label: 'BorgBackup' },
          { value: 'kopia',  label: 'Kopia' }
        ],
        SSH_AUTH: [
          { value: 'key',      label: 'SSH key (~/.ssh/id_rsa)' },
          { value: 'password', label: 'Password (via sshpass)' }
        ]
      };
      return BACKUP_LOC_OPTIONS[locDropdown[1]];
    }

    const result = optionMaps[key] || [];
    //console.log('Final result for', key, ':', result);
    return result;
  }

  // Get comprehensive timezone options
  static getTimezoneOptions() {
    return [
      { value: 'Etc/UTC', label: 'Etc/UTC' },
      { value: 'America/New_York', label: 'America/New_York' },
      { value: 'America/Chicago', label: 'America/Chicago' },
      { value: 'America/Denver', label: 'America/Denver' },
      { value: 'America/Los_Angeles', label: 'America/Los_Angeles' },
      { value: 'America/Anchorage', label: 'America/Anchorage' },
      { value: 'America/Honolulu', label: 'America/Honolulu' },
      { value: 'America/Toronto', label: 'America/Toronto' },
      { value: 'America/Vancouver', label: 'America/Vancouver' },
      { value: 'America/Mexico_City', label: 'America/Mexico_City' },
      { value: 'America/Sao_Paulo', label: 'America/Sao_Paulo' },
      { value: 'Europe/London', label: 'Europe/London' },
      { value: 'Europe/Paris', label: 'Europe/Paris' },
      { value: 'Europe/Berlin', label: 'Europe/Berlin' },
      { value: 'Europe/Rome', label: 'Europe/Rome' },
      { value: 'Europe/Madrid', label: 'Europe/Madrid' },
      { value: 'Europe/Amsterdam', label: 'Europe/Amsterdam' },
      { value: 'Europe/Brussels', label: 'Europe/Brussels' },
      { value: 'Europe/Zurich', label: 'Europe/Zurich' },
      { value: 'Europe/Vienna', label: 'Europe/Vienna' },
      { value: 'Europe/Stockholm', label: 'Europe/Stockholm' },
      { value: 'Europe/Oslo', label: 'Europe/Oslo' },
      { value: 'Europe/Copenhagen', label: 'Europe/Copenhagen' },
      { value: 'Europe/Helsinki', label: 'Europe/Helsinki' },
      { value: 'Europe/Warsaw', label: 'Europe/Warsaw' },
      { value: 'Europe/Prague', label: 'Europe/Prague' },
      { value: 'Europe/Budapest', label: 'Europe/Budapest' },
      { value: 'Europe/Moscow', label: 'Europe/Moscow' },
      { value: 'Asia/Dubai', label: 'Asia/Dubai' },
      { value: 'Asia/Kolkata', label: 'Asia/Kolkata' },
      { value: 'Asia/Shanghai', label: 'Asia/Shanghai' },
      { value: 'Asia/Hong_Kong', label: 'Asia/Hong_Kong' },
      { value: 'Asia/Tokyo', label: 'Asia/Tokyo' },
      { value: 'Asia/Seoul', label: 'Asia/Seoul' },
      { value: 'Asia/Singapore', label: 'Asia/Singapore' },
      { value: 'Asia/Bangkok', label: 'Asia/Bangkok' },
      { value: 'Asia/Jakarta', label: 'Asia/Jakarta' },
      { value: 'Australia/Sydney', label: 'Australia/Sydney' },
      { value: 'Australia/Melbourne', label: 'Australia/Melbourne' },
      { value: 'Australia/Perth', label: 'Australia/Perth' },
      { value: 'Pacific/Auckland', label: 'Pacific/Auckland' },
      { value: 'Africa/Cairo', label: 'Africa/Cairo' },
      { value: 'Africa/Lagos', label: 'Africa/Lagos' },
      { value: 'Africa/Johannesburg', label: 'Africa/Johannesburg' }
    ];
  }

  // Check if a config key should use dropdown
  static isDropdownKey(key) {
    //console.log('ConfigOptions.isDropdownKey called with:', key);
    const result = key === 'CFG_DOCKER_INSTALL_TYPE' ||
           key === 'CFG_UFW_LOGGING' ||
           key === 'CFG_TEXT_EDITOR' ||
           /^CFG_BACKUP_LOC_[0-9]+_TYPE$/.test(key) ||
           /^CFG_BACKUP_LOC_[0-9]+_ENGINE$/.test(key) ||
           key === 'CFG_BACKUP_ENGINE' ||
           /^CFG_BACKUP_LOC_[0-9]+_SSH_AUTH$/.test(key) ||
           /^CFG_BACKUP_LOC_[0-9]+_PATH_MODE$/.test(key) ||
           key === 'CFG_BACKUP_STRATEGY' ||
           key === 'CFG_INSTALL_MODE' ||
           key === 'CFG_MAIL_SECURE' ||
           key === 'CFG_GLUETUN_VPN_SERVICE_PROVIDER' ||
           key === 'CFG_GLUETUN_VPN_TYPE' ||
           key === 'CFG_TRAEFIK_DASHBOARD_ACCESS';
    //console.log('ConfigOptions.isDropdownKey result:', result);
    return result;
  }

  // Check if a config key should use timezone dropdown
  static isTimezoneKey(key) {
    return key.includes('TIMEZONE');
  }

  // Fetch available domains from system configuration
  static async getAvailableDomains() {
    try {
      //console.log('🔍 Starting domain fetch...');
      
      // Try to load system config to get domain information
      const response = await fetch('/data/config/generated/configs.json');
      //console.log('📡 Config response status:', response.status);
      
      if (!response.ok) {
        console.warn('Could not load system config for domains, returning empty list');
        return [];
      }
      
      const configData = await response.json();
      //console.log('📄 Full config data:', configData);
      //console.log('🔧 Config keys available:', Object.keys(configData));
      
      const config = configData.config || {};
      //console.log('⚙️ Config object:', config);
      //console.log('🔑 Config keys:', Object.keys(config));
      
      const domains = [];
      
      // Check CFG_DOMAIN_1 through CFG_DOMAIN_9
      for (let i = 1; i <= 9; i++) {
        const domainKey = `CFG_DOMAIN_${i}`;
        const domainValue = config[domainKey]?.value || config[domainKey] || '';
        //console.log(`🌐 Checking ${domainKey}:`, domainValue);
        
        if (domainValue.trim() !== '') {
          domains.push({
            number: i,
            domain: domainValue.trim(),
            key: domainKey
          });
        }
      }
      
      //console.log('✅ Found configured domains:', domains);
      return domains;
      
    } catch (error) {
      console.error('❌ Error fetching domains:', error);
      return [];
    }
  }

  // Get domain options for DOMAIN field
  static async getDomainOptions() {
    //console.log('🎯 Getting domain options...');
    const domains = await this.getAvailableDomains();
    //console.log('📊 Domains returned:', domains);
    
    if (domains.length === 0) {
      //console.log('⚠️ No domains found, returning fallback option');
      // No domains configured - return empty option
      return [
        { value: '1', label: 'No domains configured - Configure domains in Network settings first' }
      ];
    }
    
    // Create options with just domain names
    const options = domains.map(domain => ({
      value: domain.number.toString(),
      label: domain.domain
    }));
    
    //console.log('✅ Generated domain options:', options);
    return options;
  }

  // Check if a config key should use domain dropdown
  static isDomainKey(key) {
    return key === 'DOMAIN';
  }
}

// Export to global scope
window.ConfigOptions = ConfigOptions;

// Kick off provider snapshot fetch immediately so the dropdown is hot on first paint.
ConfigOptions.loadGluetunProviders();
ConfigOptions.loadGluetunProviderIcons();

// Delegated listener: when the gluetun provider <select> changes, rebuild the
// VPN-type <select> from that provider's supported types. Avoids reaching into
// the renderer to wire onchange per-field.
document.addEventListener('change', (e) => {
  if (!e.target) return;
  if (e.target.id === 'config-CFG_GLUETUN_VPN_SERVICE_PROVIDER'
   || e.target.id === 'GLUETUN_VPN_SERVICE_PROVIDER') {
    ConfigOptions.refreshGluetunVpnTypeOptions();
  } else if (e.target.id === 'config-CFG_GLUETUN_VPN_TYPE'
          || e.target.id === 'GLUETUN_VPN_TYPE') {
    ConfigOptions.refreshGluetunCredentialVisibility();
  } else if (e.target.id === 'config-CFG_GLUETUN_WIREGUARD_PRIVATE_KEY'
          || e.target.id === 'GLUETUN_WIREGUARD_PRIVATE_KEY'
          || e.target.id === 'config-CFG_GLUETUN_WIREGUARD_ADDRESSES'
          || e.target.id === 'GLUETUN_WIREGUARD_ADDRESSES') {
    ConfigOptions.refreshMullvadGenerateStatus();
  }
});

document.addEventListener('input', (e) => {
  if (!e.target) return;
  if (e.target.id === 'config-CFG_GLUETUN_WIREGUARD_PRIVATE_KEY'
   || e.target.id === 'GLUETUN_WIREGUARD_PRIVATE_KEY'
   || e.target.id === 'config-CFG_GLUETUN_WIREGUARD_ADDRESSES'
   || e.target.id === 'GLUETUN_WIREGUARD_ADDRESSES') {
    ConfigOptions.refreshMullvadGenerateStatus();
  }
});
