import { useState, useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import { IconSunFilled, IconMoonFilled, IconDeviceDesktop, IconEyeFilled, IconTextSize, IconX,
         IconCookieFilled, IconKeyFilled, IconKeyboardFilled, IconShieldFilled, IconLockFilled,
         IconWorldFilled, IconTrashFilled, IconDownloadFilled, IconLogout2, IconArrowMoveRight,
         IconUserFilled, IconSettingsFilled, IconReceiptFilled, IconDeviceSpeakerFilled,
         IconAccessibleFilled } from '@tabler/icons-react'
import { motion, AnimatePresence } from 'motion/react'
import { useStore } from '../store'
import * as api from '../api'
import type { PasskeyItem, ReceiptPayload } from '../api'
import { applySettings } from '../settingsApply'
import Select from './ui/Select'
import { useFocusTrap } from '../hooks/useFocusTrap'

interface Settings {
  theme: 'system' | 'light' | 'dark'
  colorblind: 'none' | 'protanopia' | 'deuteranopia' | 'tritanopia'
  textScale: number
  cookieLifetime: number
  hideFromLeaderboards: boolean
  privateProfile: boolean
  federatedContentFilter: 'all' | 'approved' | 'local'
  blockedInstances: string[]
  anonymousSolveMode: boolean
  autoPurgeEnabled: boolean
  autoPurgeDays: number
  noTrackMode: boolean
  anonymizeTimes: boolean
  sessionBinding: boolean
  torFriendly: boolean
  encryptSolveData: boolean
  ephemeralSession: boolean
}

const defaultSettings: Settings = {
  theme: 'system', colorblind: 'none', textScale: 100, cookieLifetime: 2592000,
  hideFromLeaderboards: false, privateProfile: false, federatedContentFilter: 'all',
  blockedInstances: [], anonymousSolveMode: false, autoPurgeEnabled: false,
  autoPurgeDays: 90, noTrackMode: false, anonymizeTimes: false,
  sessionBinding: false, torFriendly: false, encryptSolveData: false, ephemeralSession: false,
}

const LIFETIME_KEYS: { value: number; key: string }[] = [
  { value: 0, key: 'settings.session.thisSession' }, { value: 86400, key: 'settings.session.oneDay' },
  { value: 604800, key: 'settings.session.oneWeek' }, { value: 2592000, key: 'settings.session.thirtyDays' },
  { value: 7776000, key: 'settings.session.ninetyDays' }, { value: 31536000, key: 'settings.session.oneYear' },
]

type PrivacyPreset = 'open' | 'private' | 'fortress'
type Tab = 'profile' | 'display' | 'accessibility' | 'session' | 'visibility' | 'data' | 'federation' | 'account'

const TABS: { id: Tab; labelKey: string; icon: typeof IconUserFilled }[] = [
  { id: 'profile', labelKey: 'settings.tabs.profile', icon: IconUserFilled },
  { id: 'display', labelKey: 'settings.tabs.display', icon: IconSunFilled },
  { id: 'accessibility', labelKey: 'settings.tabs.accessibility', icon: IconAccessibleFilled },
  { id: 'session', labelKey: 'settings.tabs.session', icon: IconCookieFilled },
  { id: 'visibility', labelKey: 'settings.tabs.visibility', icon: IconEyeFilled },
  { id: 'data', labelKey: 'settings.tabs.data', icon: IconLockFilled },
  { id: 'federation', labelKey: 'settings.tabs.federation', icon: IconWorldFilled },
  { id: 'account', labelKey: 'settings.tabs.account', icon: IconSettingsFilled },
]

function applyPreset(preset: PrivacyPreset): Partial<Settings> {
  switch (preset) {
    case 'open': return { hideFromLeaderboards: false, privateProfile: false, federatedContentFilter: 'all', anonymousSolveMode: false, autoPurgeEnabled: false, noTrackMode: false, anonymizeTimes: false, sessionBinding: false, encryptSolveData: false, ephemeralSession: false }
    case 'private': return { hideFromLeaderboards: true, privateProfile: true, federatedContentFilter: 'local', anonymousSolveMode: true, autoPurgeEnabled: false, noTrackMode: false, anonymizeTimes: false, sessionBinding: false }
    case 'fortress': return { hideFromLeaderboards: true, privateProfile: true, federatedContentFilter: 'local', anonymousSolveMode: true, autoPurgeEnabled: true, autoPurgeDays: 30, noTrackMode: true, anonymizeTimes: true, sessionBinding: true, encryptSolveData: true }
  }
}

function detectPreset(s: Settings): PrivacyPreset | null {
  if (!s.hideFromLeaderboards && !s.privateProfile && s.federatedContentFilter === 'all' && !s.anonymousSolveMode && !s.noTrackMode) return 'open'
  if (s.hideFromLeaderboards && s.privateProfile && s.noTrackMode && s.autoPurgeEnabled && s.sessionBinding && s.encryptSolveData) return 'fortress'
  if (s.hideFromLeaderboards && s.privateProfile && s.anonymousSolveMode) return 'private'
  return null
}

function Toggle({ checked, onChange, label, hint, disabled, disabledHint }: { checked: boolean; onChange: (v: boolean) => void; label: string; hint?: string; disabled?: boolean; disabledHint?: string }) {
  return (
    <label className={`privacy-toggle ${disabled ? 'privacy-toggle-disabled' : ''}`}>
      <input type="checkbox" checked={checked} onChange={e => onChange(e.target.checked)} disabled={disabled} />
      <div>
        <span>{label}</span>
        {disabled && disabledHint ? <span className="privacy-toggle-hint">{disabledHint}</span> : hint && <span className="privacy-toggle-hint">{hint}</span>}
      </div>
    </label>
  )
}

function NarratorSettingsBlock() {
  const { t } = useTranslation()
  const narratorSettings = useStore(s => s.narratorSettings)
  const setNarratorSettings = useStore(s => s.setNarratorSettings)

  return (
    <div className="settings-narrator-controls">
      <div className="settings-narrator-item">
        <label className="settings-sublabel">{t('settings.narrator.verbosity')}</label>
        <Select value={narratorSettings.verbosity}
          onChange={v => { const s = String(v); if (s === 'brief' || s === 'normal' || s === 'verbose') setNarratorSettings({ verbosity: s }) }}
          options={[
            { value: 'brief', label: t('settings.narrator.brief') },
            { value: 'normal', label: t('settings.narrator.normal') },
            { value: 'verbose', label: t('settings.narrator.verbose') },
          ]} />
      </div>
      <Toggle checked={narratorSettings.sounds} onChange={v => setNarratorSettings({ sounds: v })}
        label={t('settings.narrator.soundEffects')} />
    </div>
  )
}

export default function SettingsPanel({ onClose }: { onClose: () => void }) {
  const trapRef = useFocusTrap(true)
  const { t, i18n } = useTranslation()
  const [settings, setSettings] = useState<Settings>(defaultSettings)
  const [pendingScale, setPendingScale] = useState(100)
  const inputMode = useStore(s => s.inputMode)
  const setInputMode = useStore(s => s.setInputMode)
  const [passkeys, setPasskeys] = useState<PasskeyItem[]>([])
  const [registering, setRegistering] = useState(false)
  const [passkeyError, setPasskeyError] = useState('')
  const [deleteConfirm, setDeleteConfirm] = useState(false)
  const [newBlockedDomain, setNewBlockedDomain] = useState('')
  const [tab, setTab] = useState<Tab>('profile')
  const [migrateDomain, setMigrateDomain] = useState('')
  const [importMsg, setImportMsg] = useState('')
  const [migrating, setMigrating] = useState(false)
  const [migrateMsg, setMigrateMsg] = useState('')
  const [displayName, setDisplayName] = useState('')
  const [claimInput, setClaimInput] = useState('')
  const [claimStatus, setClaimStatus] = useState<{ ok: boolean; msg: string } | null>(null)
  const [claimingManual, setClaimingManual] = useState(false)

  const supportsPasskey = !!window.PublicKeyCredential
  const hasPasskey = useStore(s => s.hasPasskey)
  const activePreset = detectPreset(settings)


  useEffect(() => {
    api.fetchSettings().then(s => {
      const merged = { ...defaultSettings, ...s }
      setSettings(merged); setPendingScale(merged.textScale); applySettings(merged)
      if (s.inputMode === 'auto' || s.inputMode === 'keyboard' || s.inputMode === 'stylus') setInputMode(s.inputMode)
    })
    api.fetchPasskeys().then(setPasskeys)
    api.fetchMe().then(me => setDisplayName(me.display_name || '')).catch(() => {})
  }, [])

  const update = (partial: Partial<Settings>) => {
    const next = { ...settings, ...partial }; setSettings(next); applySettings(next); api.saveSettings(next)
  }

  const addPasskey = async () => {
    setRegistering(true); setPasskeyError('')
    try { await api.registerPasskey(); setPasskeys(await api.fetchPasskeys()) }
    catch (e) { setPasskeyError(e instanceof Error ? e.message : 'Failed') }
    setRegistering(false)
  }

  const addBlockedDomain = () => {
    const d = newBlockedDomain.trim().toLowerCase()
    if (d && !settings.blockedInstances.includes(d)) update({ blockedInstances: [...settings.blockedInstances, d] })
    setNewBlockedDomain('')
  }

  return (
    <motion.div className="settings-overlay" onClick={onClose}
      initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}
      transition={{ duration: 0.15 }}>
      <motion.div ref={trapRef} className="settings-panel settings-panel-tabs" onClick={e => e.stopPropagation()}
        role="dialog" aria-modal="true" aria-label={t('settings.title')}
        initial={{ opacity: 0, scale: 0.95, y: 12 }}
        animate={{ opacity: 1, scale: 1, y: 0 }}
        exit={{ opacity: 0, scale: 0.95, y: 12 }}
        transition={{ duration: 0.2, ease: [0.25, 0.1, 0.25, 1] }}>
        <div className="settings-header">
          <h3>{t('settings.title')}</h3>
          <button className="btn btn-sm btn-ghost" onClick={onClose} aria-label={t('common.close')}><IconX size={16} aria-hidden="true" /></button>
        </div>

        <div className="settings-body">
          <div className="settings-sidebar" role="tablist" aria-orientation="vertical">
            {TABS.map(tb => (
              <button key={tb.id}
                className={`settings-sidebar-tab ${tab === tb.id ? 'settings-sidebar-tab-active' : ''}`}
                onClick={() => setTab(tb.id)}
                role="tab"
                aria-selected={tab === tb.id}
                aria-controls="settings-tabpanel"
                id={`settings-tab-${tb.id}`}>
                <tb.icon size={14} aria-hidden="true" />
                {t(tb.labelKey)}
              </button>
            ))}
          </div>

          <div className="settings-content" role="tabpanel" id="settings-tabpanel"
            aria-labelledby={`settings-tab-${tab}`}>
            <AnimatePresence mode="wait">
            <motion.div key={tab}
              initial={{ opacity: 0, y: 6 }}
              animate={{ opacity: 1, y: 0 }}
              exit={{ opacity: 0, y: -6 }}
              transition={{ duration: 0.12 }}>

              {/* ==================== PROFILE ==================== */}
              {tab === 'profile' && (<>
                <div className="settings-section">
                  <label className="settings-label">{t('settings.profile.displayName')}</label>
                  <input type="text" className="onboard-username" value={displayName}
                    onChange={e => setDisplayName(e.target.value)}
                    onBlur={() => { if (displayName.trim()) api.updateMe({ display_name: displayName.trim() }) }}
                    placeholder={t('settings.profile.placeholder')} maxLength={30}
                    autoComplete="nickname" />
                  <p className="settings-hint">{t('settings.profile.hint')}</p>
                </div>

                <div className="settings-section">
                  <label className="settings-label">{t('settings.profile.sessionLabel')}</label>
                  <p className="settings-hint">
                    {hasPasskey ? t('settings.profile.hasPasskey') : t('settings.profile.noPasskey')}
                  </p>
                </div>
              </>)}

              {/* ==================== DISPLAY ==================== */}
              {tab === 'display' && (<>
                <div className="settings-section">
                  <label className="settings-label">{t('settings.display.theme')}</label>
                  <div className="settings-row">
                    {(['system', 'light', 'dark'] as const).map(th => (
                      <button key={th} className={`btn btn-sm ${settings.theme === th ? 'btn-primary' : ''}`} aria-pressed={settings.theme === th} onClick={() => update({ theme: th })}>
                        {th === 'system' ? <><IconDeviceDesktop size={13} style={{ verticalAlign: -2 }} /> {t('settings.display.system')}</> :
                         th === 'light' ? <><IconSunFilled size={13} style={{ verticalAlign: -2 }} /> {t('settings.display.light')}</> :
                         <><IconMoonFilled size={13} style={{ verticalAlign: -2 }} /> {t('settings.display.dark')}</>}
                      </button>
                    ))}
                  </div>
                </div>

                <div className="settings-section">
                  <label className="settings-label"><IconKeyboardFilled size={11} style={{ verticalAlign: -1, marginRight: 4 }} /> {t('settings.display.inputMode')}</label>
                  <div className="settings-row">
                    {(['auto', 'keyboard', 'stylus'] as const).map(m => (
                      <button key={m} className={`btn btn-sm ${inputMode === m ? 'btn-primary' : ''}`} aria-pressed={inputMode === m}
                        onClick={() => { setInputMode(m); api.fetchSettings().then(s => api.saveSettings({ ...s, inputMode: m })) }}>
                        {m === 'auto' ? t('settings.display.inputAuto') : m === 'keyboard' ? t('settings.display.inputKeyboard') : t('settings.display.inputStylus')}
                      </button>
                    ))}
                  </div>
                </div>

                <div className="settings-section">
                  <Toggle checked={settings.torFriendly || false} onChange={v => update({ torFriendly: v })}
                    label={t('settings.display.torFriendly')} hint={t('settings.display.torHint')} />
                </div>

                <div className="settings-section">
                  <label className="settings-label">{t('settings.display.language')}</label>
                  <Select value={i18n.language} onChange={v => i18n.changeLanguage(String(v))} options={
                    Object.keys(i18n.options.resources || {}).map(lng => ({ value: lng, label: lng.toUpperCase() }))
                  } />
                </div>

                <div className="settings-section">
                  <Toggle checked={false} onChange={() => {}}
                    label={t('settings.display.pushNotifications')}
                    hint={t('settings.display.pushHint')}
                    disabled={true}
                    disabledHint={t('settings.display.pushComingSoon')} />
                </div>
              </>)}

              {/* ==================== ACCESSIBILITY ==================== */}
              {tab === 'accessibility' && (<>
                <div className="settings-section">
                  <label className="settings-label settings-section-heading">
                    <IconDeviceSpeakerFilled size={13} style={{ verticalAlign: -2, marginRight: 4 }} />
                    {t('settings.narrator.title')}
                  </label>
                  <p className="settings-hint">{t('settings.narrator.hint')}</p>
                  <NarratorSettingsBlock />
                </div>

                <div className="settings-divider" />

                <div className="settings-section">
                  <label className="settings-label settings-section-heading">
                    <IconEyeFilled size={13} style={{ verticalAlign: -2, marginRight: 4 }} />
                    {t('settings.display.colorblind')}
                  </label>
                  <p className="settings-hint">{t('settings.accessibility.colorblindHint')}</p>
                  <Select value={settings.colorblind} onChange={v => { const c = String(v); if (c === 'none' || c === 'protanopia' || c === 'deuteranopia' || c === 'tritanopia') update({ colorblind: c }) }} options={[
                    { value: 'none', label: t('settings.display.colorblindNone') },
                    { value: 'protanopia', label: t('settings.display.protanopia') },
                    { value: 'deuteranopia', label: t('settings.display.deuteranopia') },
                    { value: 'tritanopia', label: t('settings.display.tritanopia') },
                  ]} />
                </div>

                <div className="settings-divider" />

                <div className="settings-section">
                  <label className="settings-label settings-section-heading">
                    <IconTextSize size={13} style={{ verticalAlign: -2, marginRight: 4 }} />
                    {t('settings.display.textSize', { scale: pendingScale })}
                  </label>
                  <p className="settings-hint">{t('settings.accessibility.textSizeHint')}</p>
                  <input type="range" min={80} max={200} step={10} value={pendingScale}
                    className="settings-range"
                    onChange={e => setPendingScale(Number(e.target.value))}
                    onMouseUp={() => update({ textScale: pendingScale })}
                    onTouchEnd={() => update({ textScale: pendingScale })} />
                  <div className="settings-range-labels">
                    <span>80%</span>
                    <span>100%</span>
                    <span>200%</span>
                  </div>
                </div>
              </>)}

              {/* ==================== SESSION ==================== */}
              {tab === 'session' && (<>
                <div className="settings-section">
                  <label className="settings-label"><IconCookieFilled size={11} style={{ verticalAlign: -1, marginRight: 4 }} /> {t('settings.session.duration')}</label>
                  <div className="settings-grid-3">
                    {LIFETIME_KEYS.map(opt => (
                      <button key={opt.value} className={`btn btn-sm ${settings.cookieLifetime === opt.value ? 'btn-primary' : ''}`} aria-pressed={settings.cookieLifetime === opt.value}
                        onClick={() => update({ cookieLifetime: opt.value })}>{t(opt.key)}</button>
                    ))}
                  </div>
                  <p className="settings-hint">{t('settings.session.durationHint')}</p>
                </div>

                <div className="settings-section">
                  <label className="settings-label"><IconKeyFilled size={11} style={{ verticalAlign: -1, marginRight: 4 }} /> {t('settings.session.passkeys')}</label>
                  {passkeys.length > 0 ? (
                    <div className="passkey-list">
                      {passkeys.map(pk => (
                        <div key={pk.id} className="passkey-item">
                          <span>{pk.name}</span>
                          <span className="passkey-date">{new Date(pk.created_at).toLocaleDateString()}</span>
                        </div>
                      ))}
                    </div>
                  ) : (
                    <p className="settings-hint">{t('settings.session.noPasskeys')}</p>
                  )}
                  {passkeyError && <p className="settings-hint" role="alert" style={{ color: 'var(--color-error)' }}>{passkeyError}</p>}
                  {supportsPasskey && (
                    <button className="btn btn-sm" onClick={addPasskey} disabled={registering} style={{ marginTop: 8 }}>
                      <IconKeyFilled size={13} style={{ verticalAlign: -2 }} /> {registering ? t('settings.session.registering') : t('settings.session.addPasskey')}
                    </button>
                  )}
                  {!supportsPasskey && <p className="settings-hint">{t('settings.session.noSupport')}</p>}
                </div>

                <div className="settings-section">
                  <Toggle checked={settings.sessionBinding} onChange={v => update({ sessionBinding: v })}
                    label={t('settings.session.sessionBinding')} hint={t('settings.session.sessionBindingHint')}
                    disabled={!hasPasskey} disabledHint={t('settings.session.requiresPasskey')} />
                </div>
              </>)}

              {/* ==================== VISIBILITY ==================== */}
              {tab === 'visibility' && (<>
                <div className="settings-section">
                  <label className="settings-label">{t('settings.visibility.quickSetup')}</label>
                  <div className="privacy-presets">
                    {([
                      { id: 'open', icon: IconWorldFilled, label: t('settings.visibility.open'), desc: t('settings.visibility.openDesc') },
                      { id: 'private', icon: IconEyeFilled, label: t('settings.visibility.private'), desc: t('settings.visibility.privateDesc') },
                      { id: 'fortress', icon: IconLockFilled, label: t('settings.visibility.fortress'), desc: t('settings.visibility.fortressDesc') },
                    ] satisfies Array<{ id: PrivacyPreset; icon: typeof IconWorldFilled; label: string; desc: string }>).map(p => (
                      <button key={p.id} className={`privacy-preset ${activePreset === p.id ? 'privacy-preset-active' : ''}`}
                        onClick={() => update(applyPreset(p.id))}>
                        <p.icon size={16} />
                        <strong>{p.label}</strong>
                        <span>{p.desc}</span>
                      </button>
                    ))}
                  </div>
                </div>

                <div className="settings-section">
                  <label className="settings-label"><IconShieldFilled size={11} style={{ verticalAlign: -1, marginRight: 4 }} /> {t('settings.visibility.visibilityLabel')}</label>
                  <Toggle checked={settings.hideFromLeaderboards} onChange={v => update({ hideFromLeaderboards: v })}
                    label={t('settings.visibility.hideLeaderboards')} hint={t('settings.visibility.hideLeaderboardsHint')} />
                  <Toggle checked={settings.privateProfile} onChange={v => update({ privateProfile: v })}
                    label={t('settings.visibility.privateProfile')} hint={t('settings.visibility.privateProfileHint')} />
                  <Toggle checked={settings.anonymousSolveMode} onChange={v => update({ anonymousSolveMode: v })}
                    label={t('settings.visibility.anonSolve')} hint={t('settings.visibility.anonSolveHint')} />
                </div>
              </>)}

              {/* ==================== DATA ==================== */}
              {tab === 'data' && (<>
                <div className="settings-section">
                  <label className="settings-label"><IconLockFilled size={11} style={{ verticalAlign: -1, marginRight: 4 }} /> {t('settings.data.title')}</label>
                  <Toggle checked={settings.noTrackMode} onChange={v => update({ noTrackMode: v })}
                    label={t('settings.data.noTrack')} hint={t('settings.data.noTrackHint')} />
                  <Toggle checked={settings.anonymizeTimes} onChange={v => update({ anonymizeTimes: v })}
                    label={t('settings.data.anonTimes')} hint={t('settings.data.anonTimesHint')} />
                  <Toggle checked={settings.encryptSolveData} onChange={v => update({ encryptSolveData: v })}
                    label={t('settings.data.encrypt')} hint={t('settings.data.encryptHint')}
                    disabled={!hasPasskey} disabledHint={t('settings.session.requiresPasskey')} />
                  <Toggle checked={settings.ephemeralSession} onChange={v => update({ ephemeralSession: v })}
                    label={t('settings.data.ephemeral')} hint={t('settings.data.ephemeralHint')}
                    disabled={!hasPasskey} disabledHint={t('settings.session.requiresPasskey')} />
                  <Toggle checked={settings.autoPurgeEnabled} onChange={v => update({ autoPurgeEnabled: v })}
                    label={t('settings.data.autoPurge')}
                    disabled={!hasPasskey} disabledHint={t('settings.session.requiresPasskey')} />
                  {settings.autoPurgeEnabled && (
                    <div className="privacy-purge-days">
                      <span>{t('settings.data.purgeAfter')}</span>
                      <Select value={settings.autoPurgeDays} onChange={v => update({ autoPurgeDays: Number(v) })} options={[
                        { value: 7, label: t('settings.data.purgeDays.7') }, { value: 30, label: t('settings.data.purgeDays.30') },
                        { value: 60, label: t('settings.data.purgeDays.60') }, { value: 90, label: t('settings.data.purgeDays.90') },
                      ]} />
                    </div>
                  )}
                </div>
              </>)}

              {/* ==================== FEDERATION ==================== */}
              {tab === 'federation' && (<>
                <div className="settings-section">
                  <label className="settings-label"><IconWorldFilled size={11} style={{ verticalAlign: -1, marginRight: 4 }} /> {t('settings.federation.fedContent')}</label>
                  <Select value={settings.federatedContentFilter} onChange={v => { const f = String(v); if (f === 'all' || f === 'approved' || f === 'local') update({ federatedContentFilter: f }) }} options={[
                    { value: 'all', label: t('settings.federation.showAll') },
                    { value: 'approved', label: t('settings.federation.approvedOnly') },
                    { value: 'local', label: t('settings.federation.localOnly') },
                  ]} />
                </div>

                <div className="settings-section">
                  <label className="settings-label">{t('settings.federation.blockedInstances')}</label>
                  <div className="cc-submit-row">
                    <input type="text" placeholder="domain.example.com" value={newBlockedDomain}
                      aria-label={t('settings.federation.blockedInstances')}
                      onChange={e => setNewBlockedDomain(e.target.value)} onKeyDown={e => e.key === 'Enter' && addBlockedDomain()} />
                    <button className="btn btn-sm" onClick={addBlockedDomain} disabled={!newBlockedDomain.trim()}>{t('settings.federation.block')}</button>
                  </div>
                  {settings.blockedInstances.length > 0 && (
                    <div className="privacy-blocked-list">
                      {settings.blockedInstances.map(d => (
                        <span key={d} className="privacy-blocked-tag">{d}<button aria-label="Remove" onClick={() => update({ blockedInstances: settings.blockedInstances.filter(x => x !== d) })}><IconX size={10} aria-hidden="true" /></button></span>
                      ))}
                    </div>
                  )}
                  <div className="settings-row" style={{ marginTop: 8 }}>
                    <button className="btn btn-sm" onClick={() => api.exportUserBlocklist()}>{t('settings.federation.exportBlocklist')}</button>
                    <button className="btn btn-sm" onClick={() => {
                      const input = document.createElement('input'); input.type = 'file'; input.accept = '.json'
                      input.onchange = async () => {
                        if (!input.files?.length) return
                        try { await api.importUserBlocklist(JSON.parse(await input.files[0].text()))
                          api.fetchSettings().then(s => setSettings({ ...defaultSettings, ...s }))
                        } catch { /* ignored */ }
                      }; input.click()
                    }}>{t('settings.federation.importBlocklist')}</button>
                  </div>
                </div>
              </>)}

              {/* ==================== ACCOUNT ==================== */}
              {tab === 'account' && (<>
                <div className="settings-section">
                  <label className="settings-label">{t('settings.account.yourData')}</label>
                  <p className="settings-hint" style={{ marginBottom: 12 }}>
                    {t('settings.account.dataHint')}
                  </p>
                  <div className="settings-row">
                    <button className="btn btn-sm" onClick={() => api.exportData()}>
                      <IconDownloadFilled size={13} style={{ verticalAlign: -2 }} /> {t('settings.account.export')}
                    </button>
                    <button className="btn btn-sm" onClick={() => {
                      const input = document.createElement('input'); input.type = 'file'; input.accept = '.json'
                      input.onchange = async () => {
                        if (!input.files?.length) return
                        try {
                          const data = JSON.parse(await input.files[0].text())
                          const res = await api.importData(data)
                          let msg = t('onboarding.imported', { count: res.imported })
                          if (res.skipped?.length) msg += ' ' + t('onboarding.skipped', { items: res.skipped.join(', ') })
                          setImportMsg(msg)
                        } catch (e) { setImportMsg(e instanceof Error ? e.message : t('onboarding.importFailed')) }
                      }; input.click()
                    }}>
                      {t('settings.account.import')}
                    </button>
                  </div>
                  {importMsg && <p className="settings-hint" role="status" style={{ marginTop: 8 }}>{importMsg}</p>}
                </div>

                <div className="settings-section">
                  <label className="settings-label"><IconReceiptFilled size={11} style={{ verticalAlign: -1, marginRight: 4 }} /> {t('settings.account.claimSolve')}</label>
                  <p className="settings-hint" style={{ marginBottom: 12 }}>
                    {t('settings.account.claimHint')}
                  </p>
                  <div className="receipt-claim-input">
                    <input type="text" placeholder="https://instance.com/api/receipts/... or JSON"
                      value={claimInput} onChange={e => { setClaimInput(e.target.value); setClaimStatus(null) }} />
                    <button className="btn btn-sm" disabled={!claimInput.trim() || claimingManual} onClick={async () => {
                      setClaimingManual(true); setClaimStatus(null)
                      try {
                        const val = claimInput.trim()
                        let receipt: ReceiptPayload
                        if (val.startsWith('{')) {
                          receipt = JSON.parse(val)
                        } else {
                          const match = val.match(/\/receipts\/([a-zA-Z0-9-]+)/)
                          if (!match) throw new Error('Could not parse receipt ID from URL')
                          receipt = await api.getReceipt(match[1])
                        }
                        await api.claimReceipt(receipt)
                        setClaimStatus({ ok: true, msg: t('settings.account.solveClaimed') })
                        setClaimInput('')
                      } catch (e) {
                        setClaimStatus({ ok: false, msg: e instanceof Error ? e.message : t('settings.account.failedToClaim') })
                      }
                      setClaimingManual(false)
                    }}>{claimingManual ? t('settings.account.claiming') : t('settings.account.claim')}</button>
                  </div>
                  {claimStatus && (
                    <p className={`receipt-claim-msg ${claimStatus.ok ? 'receipt-claim-msg-ok' : 'receipt-claim-msg-err'}`} role="status">
                      {claimStatus.msg}
                    </p>
                  )}
                </div>

                <div className={`settings-section ${!hasPasskey ? 'settings-section-disabled' : ''}`}>
                  <label className="settings-label"><IconArrowMoveRight size={11} style={{ verticalAlign: -1, marginRight: 4 }} /> {t('settings.account.moveInstance')}</label>
                  {!hasPasskey ? (
                    <p className="settings-hint">{t('settings.session.requiresPasskey')}</p>
                  ) : (<>
                  <p className="settings-hint" style={{ marginBottom: 12 }}>
                    {t('settings.account.moveHint')}
                  </p>
                  <div className="cc-submit-row">
                    <input type="text" placeholder="new-instance.example.com" value={migrateDomain}
                      onChange={e => setMigrateDomain(e.target.value)}
                      onKeyDown={e => e.key === 'Enter' && migrateDomain.trim() && !migrating && (() => {
                        setMigrating(true); setMigrateMsg('')
                        api.migrateAccount(migrateDomain.trim()).then(res => {
                          const blob = new Blob([JSON.stringify(res.export, null, 2)], { type: 'application/json' })
                          const url = URL.createObjectURL(blob)
                          const a = document.createElement('a'); a.href = url; a.download = 'cruciverb-export.json'; a.click()
                          URL.revokeObjectURL(url)
                          setMigrateMsg(t('settings.account.migrateSuccess'))
                        }).catch(e => setMigrateMsg(e instanceof Error ? e.message : t('settings.account.migrateFailed')))
                        .finally(() => setMigrating(false))
                      })()} />
                    <button className="btn btn-sm" disabled={!migrateDomain.trim() || migrating} onClick={() => {
                      setMigrating(true); setMigrateMsg('')
                      api.migrateAccount(migrateDomain.trim()).then(res => {
                        const blob = new Blob([JSON.stringify(res.export, null, 2)], { type: 'application/json' })
                        const url = URL.createObjectURL(blob)
                        const a = document.createElement('a'); a.href = url; a.download = 'cruciverb-export.json'; a.click()
                        URL.revokeObjectURL(url)
                        setMigrateMsg(t('settings.account.migrateSuccess'))
                      }).catch(e => setMigrateMsg(e instanceof Error ? e.message : t('settings.account.migrateFailed')))
                      .finally(() => setMigrating(false))
                    }}>{migrating ? t('settings.account.migrating') : t('settings.account.migrate')}</button>
                  </div>
                  {migrateMsg && <p className="settings-hint" role="status" style={{ marginTop: 8 }}>{migrateMsg}</p>}
                  </>)}
                </div>

                <div className="settings-section">
                  <label className="settings-label">{t('settings.account.signOut')}</label>
                  <p className="settings-hint" style={{ marginBottom: 12 }}>
                    {t('settings.account.signOutHint')}
                  </p>
                  <button className="btn btn-sm" onClick={() => {
                    api.saveSettings({ ...settings, cookieLifetime: 0 })
                    document.cookie = 'cruciverb_session=; Path=/; Max-Age=0'
                    window.location.reload()
                  }}>
                    <IconLogout2 size={13} style={{ verticalAlign: -2 }} /> {t('settings.account.signOutEverywhere')}
                  </button>
                </div>

                <div className="settings-section settings-danger">
                  <label className="settings-label">{t('settings.account.deleteAccount')}</label>
                  <p className="settings-hint" style={{ marginBottom: 12 }}>
                    {t('settings.account.deleteHint')}
                  </p>
                  {!deleteConfirm ? (
                    <button className="btn btn-sm privacy-delete-btn" onClick={() => setDeleteConfirm(true)}>
                      <IconTrashFilled size={13} style={{ verticalAlign: -2 }} /> {t('settings.account.deleteAccount')}
                    </button>
                  ) : (
                    <div className="privacy-delete-confirm" role="alertdialog" aria-label={t('settings.account.confirmDelete')}>
                      <p>{t('settings.account.confirmDelete')}</p>
                      <div style={{ display: 'flex', gap: 8 }}>
                        <button className="btn btn-sm privacy-delete-btn" onClick={async () => { await api.deleteAccount(); window.location.reload() }}>{t('settings.account.yesDelete')}</button>
                        <button className="btn btn-sm" onClick={() => setDeleteConfirm(false)}>{t('party.cancel')}</button>
                      </div>
                    </div>
                  )}
                </div>
              </>)}

            </motion.div>
            </AnimatePresence>
          </div>
        </div>
      </motion.div>
    </motion.div>
  )
}
