// ===== App Settings Page =====
// Manage operational settings stored in the AppSetting DB table.
// Changes take effect after clicking "Restart Worker" in the sidebar.
// Secrets (connection strings, API keys) are NOT shown here — those stay in .env.

function AppSettingsPage() {
  const toast = useToast();
  const [settings, setSettings] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [saving, setSaving] = React.useState({});
  const [edits, setEdits] = React.useState({});

  React.useEffect(() => { loadSettings(); }, []);

  async function loadSettings() {
    setLoading(true);
    try {
      const data = await API.get('/api/app-settings');
      setSettings(data.settings || []);
    } catch (err) {
      toast(err.message || 'Failed to load settings', 'error');
    } finally {
      setLoading(false);
    }
  }

  function handleEdit(key, value) {
    setEdits(prev => ({ ...prev, [key]: value }));
  }

  function getDisplayValue(setting) {
    return edits.hasOwnProperty(setting.settingKey) ? edits[setting.settingKey] : setting.settingValue;
  }

  function hasUnsavedChange(setting) {
    return edits.hasOwnProperty(setting.settingKey) && edits[setting.settingKey] !== setting.settingValue;
  }

  async function saveSetting(key) {
    const value = edits[key];
    if (value === undefined) return;
    setSaving(prev => ({ ...prev, [key]: true }));
    try {
      await API.put(`/api/app-settings/${encodeURIComponent(key)}`, { value });
      toast(`${key} updated. Restart Worker to apply.`, 'success');
      // Update local state
      setSettings(prev => prev.map(s => s.settingKey === key ? { ...s, settingValue: value, updatedUtc: new Date().toISOString() } : s));
      setEdits(prev => { const n = { ...prev }; delete n[key]; return n; });
    } catch (err) {
      toast(err.message || 'Failed to save setting', 'error');
    } finally {
      setSaving(prev => ({ ...prev, [key]: false }));
    }
  }

  async function saveAllPending() {
    const pending = Object.keys(edits).filter(k => {
      const s = settings.find(s => s.settingKey === k);
      return s && edits[k] !== s.settingValue;
    });
    for (const key of pending) {
      await saveSetting(key);
    }
  }

  function cancelEdit(key) {
    setEdits(prev => { const n = { ...prev }; delete n[key]; return n; });
  }

  const pendingCount = Object.keys(edits).filter(k => {
    const s = settings.find(s => s.settingKey === k);
    return s && edits[k] !== s.settingValue;
  }).length;

  // Group by category
  const categories = {};
  settings.forEach(s => {
    if (!categories[s.category]) categories[s.category] = [];
    categories[s.category].push(s);
  });

  const [revealed, setRevealed] = React.useState({});

  function isSecretCategory(cat) {
    return cat === 'Secrets';
  }

  function isSecretKey(key) {
    const l = key.toLowerCase();
    return l.includes('connectionstring') || l.includes('password') || l.includes('secret')
      || l.includes('apikey') || l.includes('api_key') || l.includes('token')
      || l.includes('encryption') || l.includes('jwt') || l.includes('key');
  }

  function maskValue(val) {
    if (!val || val.length <= 4) return '\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022';
    return val.slice(0, 4) + '\u2022'.repeat(Math.min(val.length - 4, 20));
  }

  const categoryIcons = {
    'Feature Toggles': '\uD83D\uDEA6',
    'Telemetry': '\uD83D\uDCE1',
    'Training': '\uD83C\uDFCB\uFE0F',
    'Worker': '\u2699\uFE0F',
    'General': '\uD83D\uDCCB',
    'Secrets': '\uD83D\uDD10',
    'Infrastructure': '\uD83C\uDFD7\uFE0F',
    'Email': '\uD83D\uDCE7',
    'Notifications': '\uD83D\uDD14',
  };

  function isBoolSetting(value) {
    return value === 'true' || value === 'false';
  }

  return React.createElement('div', { className: 'page-content' },
    React.createElement('div', { className: 'page-header' },
      React.createElement('h1', { className: 'page-title' }, '\u2699\uFE0F App Settings'),
      React.createElement('p', { className: 'page-subtitle' },
        'Operational settings stored in DB \u2014 changes take effect after Worker restart')
    ),

    // Action bar
    React.createElement('div', { className: 'filters-bar' },
      React.createElement('button', {
        className: 'btn btn-outline btn-sm',
        onClick: loadSettings,
        disabled: loading
      }, '\u21BB Refresh'),
      pendingCount > 0 && React.createElement('button', {
        className: 'btn btn-sm',
        onClick: saveAllPending,
        style: { marginLeft: '8px', background: '#3b82f6', color: '#fff', border: 'none', borderRadius: '6px', padding: '6px 14px', fontWeight: 600 }
      }, `\uD83D\uDCBE Save All (${pendingCount})`),
      pendingCount > 0 && React.createElement('span', {
        className: 'text-sm', style: { marginLeft: '12px', color: '#f59e0b', fontWeight: 600 }
      }, '\u26A0 Unsaved changes \u2014 remember to Restart Worker after saving')
    ),

    loading ? React.createElement(Loading, { text: 'Loading settings\u2026' }) :
    settings.length === 0 ?
      React.createElement(EmptyState, {
        icon: '\u2699\uFE0F',
        title: 'No Settings',
        text: 'The AppSetting table has not been created yet. Run migration 068.'
      }) :

    // Settings grouped by category
    Object.entries(categories).map(([category, items]) =>
      React.createElement('div', { key: category, className: 'card mb-4' },
        React.createElement('div', { className: 'card-header' },
          React.createElement('span', null,
            React.createElement('span', { style: { marginRight: '8px' } }, categoryIcons[category] || '\uD83D\uDCCB'),
            category
          ),
          React.createElement('span', { className: 'text-sm text-muted' }, `${items.length} settings`)
        ),
        React.createElement('div', { className: 'card-body', style: { padding: 0 } },
          items.map(s => {
            const currentValue = getDisplayValue(s);
            const changed = hasUnsavedChange(s);
            const isBool = isBoolSetting(s.settingValue);
            const isSecret = isSecretCategory(s.category) || isSecretKey(s.settingKey);

            return React.createElement('div', {
              key: s.settingKey,
              style: {
                display: 'flex', alignItems: 'center', gap: '12px',
                padding: '12px 16px',
                borderBottom: '1px solid var(--border, #e2e8f0)',
                background: changed ? 'rgba(59,130,246,0.05)' : 'transparent',
              }
            },
              // Key + description
              React.createElement('div', { style: { flex: 1, minWidth: 0 } },
                React.createElement('div', {
                  style: { fontWeight: 600, fontSize: '13px', fontFamily: 'monospace', wordBreak: 'break-all' }
                }, s.settingKey),
                s.description && React.createElement('div', {
                  style: { fontSize: '11px', color: 'var(--text-secondary)', marginTop: '2px' }
                }, s.description),
                React.createElement('div', {
                  style: { fontSize: '10px', color: 'var(--text-secondary)', marginTop: '2px' }
                }, `Updated: ${s.updatedUtc || '\u2014'}${s.updatedBy ? ` by ${s.updatedBy}` : ''}`)
              ),
              // Value input
              React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: '8px', flexShrink: 0 } },
                isBool ?
                  // Toggle switch for booleans
                  React.createElement('button', {
                    onClick: () => handleEdit(s.settingKey, currentValue === 'true' ? 'false' : 'true'),
                    style: {
                      width: '52px', height: '28px', borderRadius: '14px', border: 'none', cursor: 'pointer',
                      background: currentValue === 'true' ? '#22c55e' : '#d1d5db',
                      position: 'relative', transition: 'background 0.2s',
                    }
                  },
                    React.createElement('span', {
                      style: {
                        position: 'absolute', top: '2px',
                        left: currentValue === 'true' ? '26px' : '2px',
                        width: '24px', height: '24px', borderRadius: '50%',
                        background: '#fff', transition: 'left 0.2s',
                        boxShadow: '0 1px 3px rgba(0,0,0,0.2)',
                      }
                    })
                  )
                : isSecret ?
                  // Secret: masked input with reveal toggle
                  React.createElement(React.Fragment, null,
                    React.createElement('input', {
                      type: revealed[s.settingKey] ? 'text' : 'password',
                      value: currentValue,
                      onChange: (e) => handleEdit(s.settingKey, e.target.value),
                      className: 'form-input',
                      style: {
                        width: '280px', padding: '6px 10px', fontSize: '13px',
                        fontFamily: 'monospace',
                        borderColor: changed ? '#3b82f6' : undefined,
                      }
                    }),
                    React.createElement('button', {
                      onClick: () => setRevealed(prev => ({ ...prev, [s.settingKey]: !prev[s.settingKey] })),
                      title: revealed[s.settingKey] ? 'Hide' : 'Reveal',
                      style: {
                        background: 'none', border: '1px solid var(--border, #d1d5db)',
                        borderRadius: '4px', padding: '4px 6px', cursor: 'pointer', fontSize: '14px',
                      }
                    }, revealed[s.settingKey] ? '\uD83D\uDD90\uFE0F' : '\uD83D\uDC41\uFE0F')
                  )
                :
                  // Text input for non-booleans
                  React.createElement('input', {
                    type: 'text',
                    value: currentValue,
                    onChange: (e) => handleEdit(s.settingKey, e.target.value),
                    className: 'form-input',
                    style: {
                      width: '280px', padding: '6px 10px', fontSize: '13px',
                      fontFamily: 'monospace',
                      borderColor: changed ? '#3b82f6' : undefined,
                    }
                  }),
                // Save / Cancel buttons when changed
                changed && React.createElement('button', {
                  className: 'btn btn-sm',
                  onClick: () => saveSetting(s.settingKey),
                  disabled: saving[s.settingKey],
                  style: {
                    background: '#22c55e', color: '#fff', border: 'none',
                    borderRadius: '4px', padding: '4px 10px', fontSize: '11px', fontWeight: 600,
                  }
                }, saving[s.settingKey] ? '\u23F3' : '\u2714'),
                changed && React.createElement('button', {
                  className: 'btn btn-sm btn-ghost',
                  onClick: () => cancelEdit(s.settingKey),
                  style: { padding: '4px 8px', fontSize: '11px' }
                }, '\u2715')
              )
            );
          })
        )
      )
    ),

    // Info box
    React.createElement('div', {
      style: {
        padding: '12px 16px', borderRadius: '8px', fontSize: '12px',
        background: 'var(--bg-surface-alt, #f8fafc)',
        border: '1px solid var(--border, #e2e8f0)',
        color: 'var(--text-secondary)',
        lineHeight: 1.6,
      }
    },
      React.createElement('b', null, '\uD83D\uDD12 Security: '),
      'Secrets are masked by default. Click the eye icon to reveal. Only admin users can access this page.',
      React.createElement('br'),
      React.createElement('b', null, '\uD83D\uDD04 Apply changes: '),
      'After saving, click ', React.createElement('b', null, 'Restart Worker'),
      ' in the sidebar to reload settings.'
    )
  );
}
