// SettingsPanel — slide-over: stack selection, notification channel binding,
// language. Channels are real backend state (ew_channels): email verifies via
// 6-digit code; webhook/discord verify via a live test ping.
const inputStyle = {
  width: '100%', padding: '10px 12px', borderRadius: 8, fontSize: 12,
  fontFamily: 'var(--font-mono)', border: '1px solid var(--border-color)',
  background: 'transparent', color: 'var(--text-primary)', outline: 'none',
};
const smallBtn = (primary) => ({
  padding: '9px 14px', borderRadius: 8, cursor: 'pointer', whiteSpace: 'nowrap',
  fontSize: 10, fontWeight: 700, letterSpacing: '0.1em', textTransform: 'uppercase',
  border: '1px solid', borderColor: primary ? 'var(--text-primary)' : 'var(--border-color)',
  background: primary ? 'var(--text-primary)' : 'transparent',
  color: primary ? 'var(--bg-primary)' : 'var(--text-secondary)',
});

function ChannelErr({ msg }) {
  if (!msg) return null;
  return <p style={{ margin: '6px 0 0', fontSize: 10, color: 'var(--sev-breaking)' }}>{msg}</p>;
}

function VerifiedRow({ label, target, onRemove, t }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
      <span style={{ fontSize: 12, color: 'var(--text-primary)', flex: 'none' }}>{label}</span>
      <span style={{ fontSize: 10, color: 'var(--text-secondary)', flex: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{target}</span>
      <span style={{ fontSize: 9, fontWeight: 700, letterSpacing: '0.15em', color: 'var(--status-ok)', flex: 'none' }}>VERIFIED</span>
      <button onClick={onRemove} style={{ ...smallBtn(false), padding: '6px 10px' }}>{t('channels.remove')}</button>
    </div>
  );
}

// Email: enter address → code lands in inbox → confirm.
function EmailBind({ t, session, row, refresh }) {
  const [email, setEmail] = React.useState('');
  const [code, setCode] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');

  if (row && row.verified) {
    return <VerifiedRow label="Email" target={row.target} t={t}
      onRemove={() => window.EWApi.removeChannel(session.token, 'email').then(refresh)} />;
  }

  const sendCode = async () => {
    setBusy(true); setErr('');
    try { await window.EWApi.bindEmail(session.token, email.trim()); refresh(); }
    catch (e) { setErr(t('error.generic')); }
    finally { setBusy(false); }
  };
  const confirm = async () => {
    setBusy(true); setErr('');
    try { await window.EWApi.confirmEmail(session.token, code.trim()); setCode(''); refresh(); }
    catch (e) { setErr(t('error.generic')); }
    finally { setBusy(false); }
  };

  return (
    <div>
      <div style={{ fontSize: 12, marginBottom: 8 }}>Email</div>
      {row ? (
        <>
          <p style={{ margin: '0 0 8px', fontSize: 10, color: 'var(--text-secondary)' }}>{t('channels.codeSent')} ({row.target})</p>
          <div style={{ display: 'flex', gap: 8 }}>
            <input style={inputStyle} value={code} onChange={e => setCode(e.target.value)}
              inputMode="numeric" maxLength={6} placeholder="000000" aria-label="Verification code" />
            <button disabled={busy || code.trim().length !== 6} onClick={confirm} style={smallBtn(true)}>{t('channels.confirm')}</button>
          </div>
        </>
      ) : (
        <div style={{ display: 'flex', gap: 8 }}>
          <input style={inputStyle} value={email} onChange={e => setEmail(e.target.value)}
            type="email" placeholder="you@example.com" aria-label="Email" />
          <button disabled={busy || !email.includes('@')} onClick={sendCode} style={smallBtn(true)}>{t('channels.sendCode')}</button>
        </div>
      )}
      <ChannelErr msg={err} />
    </div>
  );
}

// Webhook / Discord: URL is verified by an immediate test delivery.
function UrlBind({ t, session, row, refresh, type, label, placeholder }) {
  const [url, setUrl] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');

  if (row && row.verified) {
    return <VerifiedRow label={label} target={row.target} t={t}
      onRemove={() => window.EWApi.removeChannel(session.token, type).then(refresh)} />;
  }

  const save = async () => {
    setBusy(true); setErr('');
    try { await window.EWApi.bindUrl(session.token, type, url.trim()); setUrl(''); refresh(); }
    catch (e) { setErr(e.code === 'test_failed' ? t('channels.testFailed') : t('error.generic')); }
    finally { setBusy(false); }
  };

  return (
    <div>
      <div style={{ fontSize: 12, marginBottom: 8 }}>{label}</div>
      <div style={{ display: 'flex', gap: 8 }}>
        <input style={inputStyle} value={url} onChange={e => setUrl(e.target.value)}
          placeholder={placeholder} aria-label={label + ' URL'} />
        <button disabled={busy || !url.startsWith('https://')} onClick={save} style={smallBtn(true)}>{t('channels.save')}</button>
      </div>
      <ChannelErr msg={err} />
    </div>
  );
}

function ChannelSection({ t, session, me, refresh }) {
  if (!window.EWApi.hasApi()) {
    return <p style={{ margin: 0, fontSize: 11, color: 'var(--text-secondary)' }}>{t('channels.offline')}</p>;
  }
  if (!session) {
    return <p style={{ margin: 0, fontSize: 11, color: 'var(--text-secondary)' }}>{t('channels.loginFirst')}</p>;
  }
  const channels = (me && me.channels) || [];
  const get = (type) => channels.find(c => c.type === type);
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
      <EmailBind t={t} session={session} row={get('email')} refresh={refresh} />
      <UrlBind t={t} session={session} row={get('webhook')} refresh={refresh}
        type="webhook" label="Webhook" placeholder="https://your-endpoint.example/hook" />
      <UrlBind t={t} session={session} row={get('discord')} refresh={refresh}
        type="discord" label="Discord" placeholder="https://discord.com/api/webhooks/…" />
      <p style={{ margin: 0, fontSize: 10, lineHeight: 1.6, color: 'var(--text-secondary)' }}>{t('settings.notifHint')}</p>
    </div>
  );
}

function SettingsPanel({ open, onClose, t, lang, setLang, selected, setSelected, session, me, refreshMe }) {
  const { STACK_ITEMS } = window.EchoWatchData;
  const { LangRow, CheckSquare } = window.EWShared;
  const toggleStack = (id) => setSelected((s) => s.includes(id) ? s.filter(x => x !== id) : [...s, id]);

  React.useEffect(() => {
    if (!open) return undefined;
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open, onClose]);

  if (!open) return null;
  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, zIndex: 30, background: 'rgba(0,0,0,0.5)',
      display: 'flex', justifyContent: 'flex-end' }}>
      <div role="dialog" aria-modal="true" aria-label={t('settings.title')} onClick={(e) => e.stopPropagation()} style={{
        width: 'min(380px, 100vw)', height: '100%', background: 'var(--bg-primary)', borderLeft: '1px solid var(--border-color)',
        padding: 28, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 28,
      }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <h2 style={{ margin: 0, fontSize: 16, fontWeight: 700, letterSpacing: '0.05em', textTransform: 'uppercase' }}>{t('settings.title')}</h2>
          <button onClick={onClose} aria-label="Close" style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-secondary)', fontSize: 15 }}>✕</button>
        </div>

        <div>
          <div className="label-tech" style={{ marginBottom: 12 }}>{t('settings.stack')}</div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {STACK_ITEMS.map((s) => {
              const on = selected.includes(s.id);
              return (
                <button key={s.id} onClick={() => toggleStack(s.id)} aria-pressed={on} style={{
                  display: 'flex', alignItems: 'center', gap: 10, padding: '10px 12px', textAlign: 'left',
                  borderRadius: 8, cursor: 'pointer', border: '1px solid',
                  borderColor: on ? 'var(--text-primary)' : 'var(--border-color)',
                  background: on ? 'var(--bg-secondary)' : 'transparent',
                  color: 'var(--text-primary)', fontSize: 12,
                }}>
                  <CheckSquare on={on} size={14} />
                  {s.name}
                </button>
              );
            })}
          </div>
        </div>

        <div>
          <div className="label-tech" style={{ marginBottom: 12 }}>{t('settings.notifications')}</div>
          <ChannelSection t={t} session={session} me={me} refresh={refreshMe} />
        </div>

        <div>
          <div className="label-tech" style={{ marginBottom: 12 }}>{t('settings.language')}</div>
          <LangRow lang={lang} setLang={setLang} />
        </div>

        <button onClick={onClose} style={{
          marginTop: 'auto', width: '100%', padding: '14px 0', borderRadius: 9999, border: 'none', cursor: 'pointer',
          background: 'var(--text-primary)', color: 'var(--bg-primary)',
          fontSize: 12, fontWeight: 700, letterSpacing: '0.1em', textTransform: 'uppercase',
        }}>{t('settings.done')}</button>
      </div>
    </div>
  );
}
window.SettingsPanel = SettingsPanel;
