import { useEffect, useRef, useState } from 'react'
import { api, ApiError, type Integration } from '../lib/api'
import { useAuth } from '../lib/AuthContext'
import {
  User,
  Palette,
  Plug,
  Bell,
  Database,
  Info,
  Eye,
  EyeOff,
  Check,
  Download,
  Upload,
  Trash2,
  Camera,
} from 'lucide-react'

const navSections = [
  { id: 'profile', label: 'Profile', icon: User },
  { id: 'appearance', label: 'Appearance', icon: Palette },
  { id: 'integrations', label: 'Integrations', icon: Plug },
  { id: 'notifications', label: 'Notifications', icon: Bell },
  { id: 'data', label: 'Data & Backup', icon: Database },
  { id: 'about', label: 'About', icon: Info },
]

const accentColors = [
  { name: 'Gold', color: '#C8A434' },
  { name: 'Teal', color: '#2DD4BF' },
  { name: 'Purple', color: '#A855F7' },
  { name: 'Blue', color: '#3B82F6' },
  { name: 'Green', color: '#2ECC71' },
  { name: 'Red', color: '#E74C3C' },
]

type FieldDef = { key: string; label: string; secret?: boolean; hint?: string; placeholder?: string }

const integrationTypeDefs: { type: string; name: string; multiInstance?: boolean; fields: FieldDef[] }[] = [
  { type: 'proxmox', name: 'Proxmox', multiInstance: true, fields: [
    { key: 'baseUrl', label: 'Host URL', hint: 'e.g. https://192.168.1.10:8006', placeholder: 'https://192.168.1.10:8006' },
    {
      key: 'apiKey',
      label: 'API Token',
      secret: true,
      hint: 'Must be the FULL token string from Datacenter → Permissions → API Tokens, in the form USER@REALM!TOKENID=SECRET — not just the secret.',
      placeholder: 'root@pam!archnest=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
    },
  ] },
  { type: 'docker', name: 'Docker', multiInstance: true, fields: [
    { key: 'baseUrl', label: 'Socket / Remote URL', hint: 'Unix socket path or remote daemon URL, e.g. unix:///var/run/docker.sock or tcp://host:2375', placeholder: 'unix:///var/run/docker.sock' },
  ] },
  { type: 'netbird', name: 'NetBird', fields: [
    { key: 'apiKey', label: 'API Key', secret: true, hint: 'Personal access token from NetBird dashboard → Settings → Access Tokens.' },
  ] },
  { type: 'cloudflare', name: 'Cloudflare', fields: [
    { key: 'apiKey', label: 'API Token', secret: true, hint: 'A scoped API token (not your Global API Key) from My Profile → API Tokens.' },
    { key: 'zoneId', label: 'Zone ID', hint: 'Found on the domain overview page in the Cloudflare dashboard.' },
  ] },
  { type: 'aws', name: 'AWS', multiInstance: true, fields: [
    { key: 'accessKey', label: 'Access Key ID', hint: 'IAM user access key, e.g. AKIAIOSFODNN7EXAMPLE' },
    { key: 'secretKey', label: 'Secret Access Key', secret: true, hint: 'IAM user secret key — paired with the Access Key ID above.' },
    { key: 'region', label: 'Region', hint: 'e.g. us-east-1', placeholder: 'us-east-1' },
  ] },
  { type: 'uptime_kuma', name: 'Uptime Kuma', fields: [
    { key: 'baseUrl', label: 'URL', placeholder: 'https://uptime.example.com' },
    { key: 'apiKey', label: 'API Key', secret: true },
  ] },
  { type: 'weather', name: 'Weather API', fields: [{ key: 'location', label: 'Location' }, { key: 'units', label: 'Units' }] },
  { type: 'remote_desktop', name: 'Remote Desktop', multiInstance: true, fields: [
    { key: 'protocol', label: 'Protocol (rdp / vnc / telnet)' },
    { key: 'hostname', label: 'Hostname' },
    { key: 'port', label: 'Port' },
    { key: 'username', label: 'Username' },
    { key: 'domain', label: 'Domain (RDP only)' },
    { key: 'password', label: 'Password', secret: true },
  ] },
]

const sshFields: FieldDef[] = [
  { key: 'host', label: 'Host / IP' },
  { key: 'port', label: 'Port (default 22)' },
  { key: 'username', label: 'Username' },
  { key: 'password', label: 'Password', secret: true },
  { key: 'privateKey', label: 'Private Key (PEM)', secret: true },
  { key: 'passphrase', label: 'Key Passphrase', secret: true },
  { key: 'certificate', label: 'OPKSSH Certificate (id_key-cert.pub)', secret: true },
]

const cardBase: React.CSSProperties = {
  backgroundColor: 'rgba(10, 10, 12, 0.92)',
  border: '1px solid rgba(200, 164, 52, 0.08)',
  borderRadius: '12px',
  padding: '22px',
  position: 'relative',
}

const sectionTitle: React.CSSProperties = {
  fontSize: '11px',
  textTransform: 'uppercase',
  letterSpacing: '1.5px',
  color: '#7A7D85',
  fontWeight: 500,
  marginBottom: '16px',
}

const labelStyle: React.CSSProperties = {
  fontSize: '11px',
  color: '#7A7D85',
  marginBottom: '6px',
  display: 'block',
}

const inputStyle: React.CSSProperties = {
  width: '100%',
  height: '34px',
  borderRadius: '8px',
  border: '1px solid rgba(200,164,52,0.12)',
  backgroundColor: 'rgba(255,255,255,0.03)',
  color: '#E8E6E0',
  fontSize: '12px',
  padding: '0 12px',
  outline: 'none',
}

function Toggle({ on, onClick }: { on: boolean; onClick: () => void }) {
  return (
    <button
      onClick={onClick}
      className="cursor-pointer border-none"
      style={{
        width: '38px',
        height: '20px',
        borderRadius: '10px',
        backgroundColor: on ? '#C8A434' : 'rgba(255,255,255,0.08)',
        position: 'relative',
        transition: 'background-color 0.2s ease',
        flexShrink: 0,
      }}
    >
      <span
        style={{
          position: 'absolute',
          top: '2px',
          left: on ? '20px' : '2px',
          width: '16px',
          height: '16px',
          borderRadius: '50%',
          backgroundColor: '#0A0B0D',
          transition: 'left 0.2s ease',
        }}
      />
    </button>
  )
}

function GoldButton({ children, danger, onClick, disabled }: { children: React.ReactNode; danger?: boolean; onClick?: () => void; disabled?: boolean }) {
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      className="flex items-center gap-2 cursor-pointer transition-colors whitespace-nowrap"
      style={{
        fontSize: '12px',
        fontWeight: 600,
        color: danger ? '#E74C3C' : '#0A0B0D',
        backgroundColor: danger ? 'transparent' : '#C8A434',
        border: danger ? '1px solid rgba(231,76,60,0.4)' : 'none',
        borderRadius: '8px',
        padding: '9px 16px',
        boxShadow: danger ? 'none' : '0 0 14px rgba(200,164,52,0.2)',
        opacity: disabled ? 0.6 : 1,
      }}
    >
      {children}
    </button>
  )
}

function ProfileSection() {
  const { user, setUser } = useAuth()
  const fileInputRef = useRef<HTMLInputElement>(null)
  const [displayName, setDisplayName] = useState(user?.display_name ?? '')
  const [email, setEmail] = useState(user?.email ?? '')
  const [avatar, setAvatar] = useState<string | null>(user?.avatar_data_url ?? null)
  const [saving, setSaving] = useState(false)
  const [savedMsg, setSavedMsg] = useState('')

  useEffect(() => {
    setDisplayName(user?.display_name ?? '')
    setEmail(user?.email ?? '')
    setAvatar(user?.avatar_data_url ?? null)
  }, [user])

  const initials = (displayName || user?.username || '?').slice(0, 2).toUpperCase()

  function handleAvatarChange(e: React.ChangeEvent<HTMLInputElement>) {
    const file = e.target.files?.[0]
    if (!file) return
    const reader = new FileReader()
    reader.onload = () => setAvatar(reader.result as string)
    reader.readAsDataURL(file)
  }

  async function handleSave() {
    setSaving(true)
    setSavedMsg('')
    try {
      const { user: updated } = await api.updateMe({ displayName, email, avatarDataUrl: avatar })
      setUser(updated)
      setSavedMsg('Saved')
    } catch (err) {
      setSavedMsg(err instanceof ApiError ? err.message : 'Failed to save')
    } finally {
      setSaving(false)
    }
  }

  return (
    <div style={cardBase}>
      <h3 style={sectionTitle}>Profile</h3>
      <div className="flex items-center gap-4" style={{ marginBottom: '24px' }}>
        <div
          onClick={() => fileInputRef.current?.click()}
          className="relative rounded-full border-2 flex items-center justify-center font-bold cursor-pointer group"
          style={{
            width: '64px',
            height: '64px',
            borderColor: '#C8A434',
            color: '#C8A434',
            fontSize: '20px',
            backgroundColor: 'rgba(200,164,52,0.08)',
            backgroundImage: avatar ? `url(${avatar})` : undefined,
            backgroundSize: 'cover',
            backgroundPosition: 'center',
            overflow: 'hidden',
          }}
          title="Upload photo"
        >
          {!avatar && initials}
          <div
            className="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity"
            style={{ backgroundColor: 'rgba(0,0,0,0.55)' }}
          >
            <Camera size={18} color="#E8E6E0" />
          </div>
        </div>
        <input ref={fileInputRef} type="file" accept="image/*" onChange={handleAvatarChange} className="hidden" />
        <div>
          <span style={{ fontSize: '15px', color: '#E8E6E0', fontWeight: 600 }}>{displayName || user?.username}</span>
          <br />
          <span style={{ fontSize: '12px', color: '#7A7D85' }}>{email || 'No email set'}</span>
        </div>
      </div>
      <div className="grid grid-cols-2 gap-4" style={{ marginBottom: '20px' }}>
        <div>
          <label style={labelStyle}>Display Name</label>
          <input style={inputStyle} value={displayName} onChange={(e) => setDisplayName(e.target.value)} />
        </div>
        <div>
          <label style={labelStyle}>Email</label>
          <input style={inputStyle} value={email} onChange={(e) => setEmail(e.target.value)} />
        </div>
      </div>
      <div className="flex items-center gap-3">
        <GoldButton onClick={handleSave} disabled={saving}>
          <Check size={14} />
          {saving ? 'Saving…' : 'Save Changes'}
        </GoldButton>
        {savedMsg && <span style={{ fontSize: '12px', color: '#7A7D85' }}>{savedMsg}</span>}
      </div>
    </div>
  )
}

function AppearanceSection() {
  const [theme, setTheme] = useState<'dark' | 'light'>('dark')
  const [accent, setAccent] = useState('Gold')
  const [fontSize, setFontSize] = useState(13)
  const [radius, setRadius] = useState(12)
  const [sidebarExpanded, setSidebarExpanded] = useState(true)
  const [animations, setAnimations] = useState(true)

  return (
    <div style={cardBase}>
      <h3 style={sectionTitle}>Appearance</h3>

      <div className="flex items-center justify-between" style={{ marginBottom: '20px' }}>
        <span style={{ fontSize: '13px', color: '#E8E6E0' }}>Theme</span>
        <div className="flex items-center gap-1" style={{ backgroundColor: 'rgba(255,255,255,0.03)', borderRadius: '8px', padding: '3px' }}>
          {(['dark', 'light'] as const).map((t) => (
            <button
              key={t}
              onClick={() => setTheme(t)}
              className="cursor-pointer border-none capitalize"
              style={{
                fontSize: '11px',
                padding: '6px 14px',
                borderRadius: '6px',
                color: theme === t ? '#0A0B0D' : '#7A7D85',
                backgroundColor: theme === t ? '#C8A434' : 'transparent',
                fontWeight: 600,
              }}
            >
              {t}
            </button>
          ))}
        </div>
      </div>

      <div style={{ marginBottom: '20px' }}>
        <span style={{ fontSize: '13px', color: '#E8E6E0', marginBottom: '10px', display: 'block' }}>Accent Color</span>
        <div className="flex items-center gap-3">
          {accentColors.map((a) => (
            <button
              key={a.name}
              onClick={() => setAccent(a.name)}
              title={a.name}
              className="cursor-pointer border-none rounded-full flex items-center justify-center"
              style={{
                width: '28px',
                height: '28px',
                backgroundColor: a.color,
                outline: accent === a.name ? `2px solid ${a.color}` : 'none',
                outlineOffset: '3px',
              }}
            >
              {accent === a.name && <Check size={14} color="#0A0B0D" />}
            </button>
          ))}
        </div>
      </div>

      <div style={{ marginBottom: '20px' }}>
        <div className="flex items-center justify-between" style={{ marginBottom: '8px' }}>
          <span style={{ fontSize: '13px', color: '#E8E6E0' }}>Font Size</span>
          <span style={{ fontSize: '11px', color: '#C8A434' }}>{fontSize}px</span>
        </div>
        <input
          type="range"
          min={12}
          max={16}
          value={fontSize}
          onChange={(e) => setFontSize(Number(e.target.value))}
          className="w-full"
          style={{ accentColor: '#C8A434' }}
        />
      </div>

      <div style={{ marginBottom: '20px' }}>
        <div className="flex items-center justify-between" style={{ marginBottom: '8px' }}>
          <span style={{ fontSize: '13px', color: '#E8E6E0' }}>Card Border Radius</span>
          <span style={{ fontSize: '11px', color: '#C8A434' }}>{radius}px</span>
        </div>
        <input
          type="range"
          min={4}
          max={16}
          value={radius}
          onChange={(e) => setRadius(Number(e.target.value))}
          className="w-full"
          style={{ accentColor: '#C8A434' }}
        />
      </div>

      <div className="flex items-center justify-between" style={{ marginBottom: '16px' }}>
        <span style={{ fontSize: '13px', color: '#E8E6E0' }}>Sidebar Expanded by Default</span>
        <Toggle on={sidebarExpanded} onClick={() => setSidebarExpanded((v) => !v)} />
      </div>

      <div className="flex items-center justify-between">
        <span style={{ fontSize: '13px', color: '#E8E6E0' }}>Animations</span>
        <Toggle on={animations} onClick={() => setAnimations((v) => !v)} />
      </div>
    </div>
  )
}

function SshHostsSection() {
  const [hosts, setHosts] = useState<Integration[] | null>(null)
  const [revealed, setRevealed] = useState<Set<string>>(new Set())
  const [drafts, setDrafts] = useState<Record<number, Record<string, string>>>({})
  const [statusMsg, setStatusMsg] = useState<Record<number, string>>({})
  const [busy, setBusy] = useState<Set<number>>(new Set())
  const [newDrafts, setNewDrafts] = useState<{ key: number; values: Record<string, string> }[]>([])
  const nextNewKey = useRef(-1)

  useEffect(() => {
    refresh()
  }, [])

  function refresh() {
    api.listIntegrations().then(({ integrations }) => setHosts(integrations.filter((i) => i.type === 'ssh')))
  }

  function toggleReveal(key: string) {
    setRevealed((prev) => {
      const next = new Set(prev)
      if (next.has(key)) next.delete(key)
      else next.add(key)
      return next
    })
  }

  function setBusyFlag(id: number, value: boolean) {
    setBusy((prev) => {
      const next = new Set(prev)
      if (value) next.add(id)
      else next.delete(id)
      return next
    })
  }

  function addNewHost() {
    const key = nextNewKey.current--
    setNewDrafts((prev) => [...prev, { key, values: {} }])
  }

  function setNewDraftField(key: number, fieldKey: string, value: string) {
    setNewDrafts((prev) => prev.map((d) => (d.key === key ? { ...d, values: { ...d.values, [fieldKey]: value } } : d)))
  }

  function removeNewDraft(key: number) {
    setNewDrafts((prev) => prev.filter((d) => d.key !== key))
  }

  function setDraftField(id: number, fieldKey: string, value: string) {
    setDrafts((prev) => ({ ...prev, [id]: { ...prev[id], [fieldKey]: value } }))
  }

  const fieldsWithJumpHost = (): FieldDef[] => [
    ...sshFields,
    { key: 'jumpHostIntegrationId', label: 'Jump Host (optional)' },
    { key: 'sessionLogging', label: 'Record session to disk' },
  ]

  function buildPayload(fields: FieldDef[], values: Record<string, string>) {
    const config: Record<string, string> = {}
    const secrets: Record<string, string> = {}
    for (const f of fields) {
      const value = values[f.key]
      if (value === undefined) continue
      if (f.secret) secrets[f.key] = value
      else config[f.key] = value
    }
    return { config, secrets }
  }

  async function handleSaveExisting(host: Integration) {
    setBusyFlag(host.id, true)
    setStatusMsg((prev) => ({ ...prev, [host.id]: '' }))
    try {
      const draft = drafts[host.id] ?? {}
      const { config, secrets } = buildPayload(fieldsWithJumpHost(), draft)
      const { integration } = await api.updateIntegration(host.id, { config, secrets })
      setHosts((prev) => (prev ?? []).map((h) => (h.id === integration.id ? integration : h)))
      setStatusMsg((prev) => ({ ...prev, [host.id]: 'Saved' }))
    } catch (err) {
      setStatusMsg((prev) => ({ ...prev, [host.id]: err instanceof ApiError ? err.message : 'Save failed' }))
    } finally {
      setBusyFlag(host.id, false)
    }
  }

  async function handleSaveNew(key: number, values: Record<string, string>) {
    setBusyFlag(key, true)
    try {
      const { config, secrets } = buildPayload(fieldsWithJumpHost(), values)
      const name = values.host ? `SSH: ${values.host}` : 'SSH Host'
      await api.createIntegration({ type: 'ssh', name, config, secrets })
      removeNewDraft(key)
      refresh()
    } catch (err) {
      setStatusMsg((prev) => ({ ...prev, [key]: err instanceof ApiError ? err.message : 'Save failed' }))
    } finally {
      setBusyFlag(key, false)
    }
  }

  async function handleTest(host: Integration) {
    setBusyFlag(host.id, true)
    try {
      const result = await api.testIntegration(host.id)
      setStatusMsg((prev) => ({ ...prev, [host.id]: result.message }))
      refresh()
    } catch (err) {
      setStatusMsg((prev) => ({ ...prev, [host.id]: err instanceof ApiError ? err.message : 'Test failed' }))
    } finally {
      setBusyFlag(host.id, false)
    }
  }

  async function handleDelete(host: Integration) {
    setBusyFlag(host.id, true)
    try {
      await api.deleteIntegration(host.id)
      refresh()
    } catch (err) {
      setStatusMsg((prev) => ({ ...prev, [host.id]: err instanceof ApiError ? err.message : 'Delete failed' }))
      setBusyFlag(host.id, false)
    }
  }

  function renderFields(
    fields: FieldDef[],
    values: Record<string, string>,
    onChange: (fieldKey: string, value: string) => void,
    idForReveal: number,
    existing: Integration | undefined,
    excludeHostId?: number,
  ) {
    return fields.map((f) => {
      const key = `${idForReveal}-${f.key}`
      if (f.key === 'jumpHostIntegrationId') {
        const options = (hosts ?? []).filter((h) => h.id !== excludeHostId)
        const savedValue = existing?.config[f.key] ?? ''
        const value = values[f.key] ?? savedValue
        return (
          <div key={key}>
            <label style={labelStyle}>{f.label}</label>
            <select style={inputStyle} value={value} onChange={(e) => onChange(f.key, e.target.value)}>
              <option value="">None</option>
              {options.map((h) => (
                <option key={h.id} value={String(h.id)}>
                  {h.name}
                </option>
              ))}
            </select>
          </div>
        )
      }
      if (f.key === 'sessionLogging') {
        const savedValue = existing?.config[f.key] === 'true'
        const value = values[f.key] !== undefined ? values[f.key] === 'true' : savedValue
        return (
          <div key={key} className="flex items-end pb-1.5">
            <label className="flex items-center gap-2 text-xs" style={{ color: '#E8E6E0' }}>
              <input type="checkbox" checked={value} onChange={(e) => onChange(f.key, e.target.checked ? 'true' : 'false')} />
              {f.label}
            </label>
          </div>
        )
      }
      const isRevealed = revealed.has(key)
      const savedValue = f.secret ? '' : existing?.config[f.key] ?? ''
      const value = values[f.key] ?? savedValue
      return (
        <div key={key}>
          <label style={labelStyle}>{f.label}</label>
          <div className="relative">
            <input
              style={inputStyle}
              type={f.secret && !isRevealed ? 'password' : 'text'}
              value={value}
              onChange={(e) => onChange(f.key, e.target.value)}
              placeholder={f.secret && existing ? '••••••••••••' : 'Not configured'}
            />
            {f.secret && (
              <button
                onClick={() => toggleReveal(key)}
                className="absolute cursor-pointer border-none bg-transparent"
                style={{ right: '8px', top: '50%', transform: 'translateY(-50%)', color: '#7A7D85' }}
              >
                {isRevealed ? <EyeOff size={13} /> : <Eye size={13} />}
              </button>
            )}
          </div>
        </div>
      )
    })
  }

  if (!hosts) {
    return (
      <div style={cardBase}>
        <p style={{ fontSize: '12px', color: '#7A7D85' }}>Loading SSH hosts…</p>
      </div>
    )
  }

  return (
    <div className="flex flex-col gap-4">
      {hosts.map((host) => {
        const online = host.status === 'connected'
        const draft = drafts[host.id] ?? {}
        return (
          <div key={host.id} style={cardBase}>
            <div className="flex items-center justify-between" style={{ marginBottom: '16px' }}>
              <div className="flex items-center gap-2.5">
                <span
                  style={{
                    width: '8px',
                    height: '8px',
                    borderRadius: '50%',
                    backgroundColor: online ? '#2ECC71' : '#4A4D55',
                    boxShadow: online ? '0 0 6px rgba(46,204,113,0.6)' : 'none',
                  }}
                />
                <span style={{ fontSize: '13px', color: '#E8E6E0', fontWeight: 600 }}>{host.name}</span>
              </div>
              <div className="flex items-center gap-2">
                {statusMsg[host.id] && <span style={{ fontSize: '11px', color: '#7A7D85' }}>{statusMsg[host.id]}</span>}
                <button
                  onClick={() => handleSaveExisting(host)}
                  disabled={busy.has(host.id)}
                  className="cursor-pointer border-none"
                  style={{ fontSize: '11px', fontWeight: 600, color: '#0A0B0D', backgroundColor: '#C8A434', borderRadius: '6px', padding: '6px 12px', opacity: busy.has(host.id) ? 0.6 : 1 }}
                >
                  Save
                </button>
                <button
                  onClick={() => handleTest(host)}
                  disabled={busy.has(host.id)}
                  className="cursor-pointer border-none"
                  style={{ fontSize: '11px', fontWeight: 600, color: '#C8A434', backgroundColor: 'rgba(200,164,52,0.08)', border: '1px solid rgba(200,164,52,0.2)', borderRadius: '6px', padding: '6px 12px', opacity: busy.has(host.id) ? 0.6 : 1 }}
                >
                  Test Connection
                </button>
                <button
                  onClick={() => handleDelete(host)}
                  disabled={busy.has(host.id)}
                  className="cursor-pointer border-none"
                  style={{ fontSize: '11px', fontWeight: 600, color: '#E74C3C', backgroundColor: 'transparent', border: '1px solid rgba(231,76,60,0.3)', borderRadius: '6px', padding: '6px 12px', opacity: busy.has(host.id) ? 0.6 : 1 }}
                >
                  <Trash2 size={12} />
                </button>
              </div>
            </div>
            <div className="grid grid-cols-3 gap-4">
              {renderFields(fieldsWithJumpHost(), draft, (k, v) => setDraftField(host.id, k, v), host.id, host, host.id)}
            </div>
          </div>
        )
      })}

      {newDrafts.map((d) => (
        <div key={d.key} style={cardBase}>
          <div className="flex items-center justify-between" style={{ marginBottom: '16px' }}>
            <span style={{ fontSize: '13px', color: '#E8E6E0', fontWeight: 600 }}>New SSH Host</span>
            <div className="flex items-center gap-2">
              {statusMsg[d.key] && <span style={{ fontSize: '11px', color: '#7A7D85' }}>{statusMsg[d.key]}</span>}
              <button
                onClick={() => handleSaveNew(d.key, d.values)}
                disabled={busy.has(d.key)}
                className="cursor-pointer border-none"
                style={{ fontSize: '11px', fontWeight: 600, color: '#0A0B0D', backgroundColor: '#C8A434', borderRadius: '6px', padding: '6px 12px', opacity: busy.has(d.key) ? 0.6 : 1 }}
              >
                Save
              </button>
              <button
                onClick={() => removeNewDraft(d.key)}
                className="cursor-pointer border-none"
                style={{ fontSize: '11px', fontWeight: 600, color: '#7A7D85', backgroundColor: 'transparent', border: '1px solid rgba(255,255,255,0.08)', borderRadius: '6px', padding: '6px 12px' }}
              >
                Cancel
              </button>
            </div>
          </div>
          <div className="grid grid-cols-3 gap-4">
            {renderFields(fieldsWithJumpHost(), d.values, (k, v) => setNewDraftField(d.key, k, v), d.key, undefined)}
          </div>
        </div>
      ))}

      <button
        onClick={addNewHost}
        className="cursor-pointer border-none self-start"
        style={{ fontSize: '12px', fontWeight: 600, color: '#C8A434', backgroundColor: 'rgba(200,164,52,0.08)', border: '1px solid rgba(200,164,52,0.2)', borderRadius: '8px', padding: '9px 16px' }}
      >
        + Add SSH Host
      </button>
    </div>
  )
}

type NewIntegrationDraft = { id: number; type: string; values: Record<string, string> }

function IntegrationsSection() {
  const [integrations, setIntegrations] = useState<Integration[] | null>(null)
  const [revealed, setRevealed] = useState<Set<string>>(new Set())
  const [editDrafts, setEditDrafts] = useState<Record<number, Record<string, string>>>({})
  const [newDrafts, setNewDrafts] = useState<NewIntegrationDraft[]>([])
  const [statusMsg, setStatusMsg] = useState<Record<string, string>>({})
  const [busy, setBusy] = useState<Set<string>>(new Set())
  const nextDraftId = useRef(-1)

  useEffect(() => {
    api.listIntegrations().then(({ integrations }) => setIntegrations(integrations))
  }, [])

  function toggleReveal(key: string) {
    setRevealed((prev) => {
      const next = new Set(prev)
      if (next.has(key)) next.delete(key)
      else next.add(key)
      return next
    })
  }

  function setBusyFlag(rowKey: string, value: boolean) {
    setBusy((prev) => {
      const next = new Set(prev)
      if (value) next.add(rowKey)
      else next.delete(rowKey)
      return next
    })
  }

  function setEditField(integrationId: number, fieldKey: string, value: string) {
    setEditDrafts((prev) => ({ ...prev, [integrationId]: { ...prev[integrationId], [fieldKey]: value } }))
  }

  function setNewDraftField(draftId: number, fieldKey: string, value: string) {
    setNewDrafts((prev) => prev.map((d) => (d.id === draftId ? { ...d, values: { ...d.values, [fieldKey]: value } } : d)))
  }

  function addNewDraft(type: string) {
    const id = nextDraftId.current--
    setNewDrafts((prev) => [...prev, { id, type, values: {} }])
  }

  function removeNewDraft(id: number) {
    setNewDrafts((prev) => prev.filter((d) => d.id !== id))
  }

  function buildPayload(def: (typeof integrationTypeDefs)[number], values: Record<string, string>) {
    const config: Record<string, string> = {}
    const secrets: Record<string, string> = {}
    for (const f of def.fields) {
      const value = values[f.key]
      if (value === undefined) continue
      if (f.secret) secrets[f.key] = value
      else config[f.key] = value
    }
    return { config, secrets }
  }

  async function handleSaveExisting(def: (typeof integrationTypeDefs)[number], existing: Integration) {
    const rowKey = `e-${existing.id}`
    setBusyFlag(rowKey, true)
    setStatusMsg((prev) => ({ ...prev, [rowKey]: '' }))
    try {
      const { config, secrets } = buildPayload(def, editDrafts[existing.id] ?? {})
      const { integration } = await api.updateIntegration(existing.id, { config, secrets })
      setIntegrations((prev) => (prev ?? []).map((i) => (i.id === integration.id ? integration : i)))
      setStatusMsg((prev) => ({ ...prev, [rowKey]: 'Saved' }))
    } catch (err) {
      setStatusMsg((prev) => ({ ...prev, [rowKey]: err instanceof ApiError ? err.message : 'Save failed' }))
    } finally {
      setBusyFlag(rowKey, false)
    }
  }

  async function handleSaveNew(def: (typeof integrationTypeDefs)[number], draft: NewIntegrationDraft) {
    const rowKey = `n-${draft.id}`
    setBusyFlag(rowKey, true)
    setStatusMsg((prev) => ({ ...prev, [rowKey]: '' }))
    try {
      const { config, secrets } = buildPayload(def, draft.values)
      const { integration } = await api.createIntegration({ type: def.type, name: def.name, config, secrets })
      setIntegrations((prev) => [...(prev ?? []), integration])
      removeNewDraft(draft.id)
    } catch (err) {
      setStatusMsg((prev) => ({ ...prev, [rowKey]: err instanceof ApiError ? err.message : 'Save failed' }))
    } finally {
      setBusyFlag(rowKey, false)
    }
  }

  async function handleTest(existing: Integration) {
    const rowKey = `e-${existing.id}`
    setBusyFlag(rowKey, true)
    try {
      const result = await api.testIntegration(existing.id)
      setStatusMsg((prev) => ({ ...prev, [rowKey]: result.message }))
      const { integrations } = await api.listIntegrations()
      setIntegrations(integrations)
    } catch (err) {
      setStatusMsg((prev) => ({ ...prev, [rowKey]: err instanceof ApiError ? err.message : 'Test failed' }))
    } finally {
      setBusyFlag(rowKey, false)
    }
  }

  async function handleDelete(existing: Integration) {
    if (!window.confirm(`Remove this ${existing.name} integration?`)) return
    const rowKey = `e-${existing.id}`
    setBusyFlag(rowKey, true)
    try {
      await api.deleteIntegration(existing.id)
      setIntegrations((prev) => (prev ?? []).filter((i) => i.id !== existing.id))
    } catch (err) {
      setStatusMsg((prev) => ({ ...prev, [rowKey]: err instanceof ApiError ? err.message : 'Delete failed' }))
      setBusyFlag(rowKey, false)
    }
  }

  if (!integrations) {
    return (
      <div style={cardBase}>
        <p style={{ fontSize: '12px', color: '#7A7D85' }}>Loading integrations…</p>
      </div>
    )
  }

  function renderFields(def: (typeof integrationTypeDefs)[number], rowKey: string, getValue: (f: FieldDef) => string, onChange: (f: FieldDef, value: string) => void, placeholderForSecret: string) {
    return (
      <div className="grid grid-cols-3 gap-4">
        {def.fields.map((f) => {
          const key = `${rowKey}-${f.key}`
          const isRevealed = revealed.has(key)
          return (
            <div key={key}>
              <label style={labelStyle}>{f.label}</label>
              <div className="relative">
                <input
                  style={inputStyle}
                  type={f.secret && !isRevealed ? 'password' : 'text'}
                  value={getValue(f)}
                  onChange={(e) => onChange(f, e.target.value)}
                  placeholder={f.secret ? placeholderForSecret : f.placeholder ?? 'Not configured'}
                />
                {f.secret && (
                  <button
                    onClick={() => toggleReveal(key)}
                    className="absolute cursor-pointer border-none bg-transparent"
                    style={{ right: '8px', top: '50%', transform: 'translateY(-50%)', color: '#7A7D85' }}
                  >
                    {isRevealed ? <EyeOff size={13} /> : <Eye size={13} />}
                  </button>
                )}
              </div>
              {f.hint && (
                <p style={{ fontSize: '10.5px', color: '#7A7D85', marginTop: '4px', lineHeight: 1.4, maxWidth: '260px' }}>{f.hint}</p>
              )}
            </div>
          )
        })}
      </div>
    )
  }

  return (
    <div className="flex flex-col gap-4">
      <div>
        <h3 style={sectionTitle}>SSH Hosts</h3>
        <SshHostsSection />
      </div>
      <div>
        <h3 style={sectionTitle}>Other Integrations</h3>
      </div>
      {integrationTypeDefs.map((def) => {
        const existingRows = integrations.filter((i) => i.type === def.type)
        const draftRows = newDrafts.filter((d) => d.type === def.type)
        const canAddAnother = def.multiInstance || existingRows.length + draftRows.length === 0

        return (
          <div key={def.type} className="flex flex-col gap-3">
            {existingRows.map((existing) => {
              const rowKey = `e-${existing.id}`
              const online = existing.status === 'connected'
              const draft = editDrafts[existing.id] ?? {}
              return (
                <div key={existing.id} style={cardBase}>
                  <div className="flex items-center justify-between" style={{ marginBottom: '16px' }}>
                    <div className="flex items-center gap-2.5">
                      <span
                        style={{
                          width: '8px',
                          height: '8px',
                          borderRadius: '50%',
                          backgroundColor: online ? '#2ECC71' : '#4A4D55',
                          boxShadow: online ? '0 0 6px rgba(46,204,113,0.6)' : 'none',
                        }}
                      />
                      <span style={{ fontSize: '13px', color: '#E8E6E0', fontWeight: 600 }}>{existing.name || def.name}</span>
                      {existing.config.baseUrl || existing.config.hostname ? (
                        <span style={{ fontSize: '11px', color: '#7A7D85' }}>{existing.config.baseUrl || existing.config.hostname}</span>
                      ) : null}
                    </div>
                    <div className="flex items-center gap-2">
                      {statusMsg[rowKey] && (
                        <span style={{ fontSize: '11px', color: '#7A7D85' }}>{statusMsg[rowKey]}</span>
                      )}
                      <button
                        onClick={() => handleSaveExisting(def, existing)}
                        disabled={busy.has(rowKey)}
                        className="cursor-pointer border-none"
                        style={{ fontSize: '11px', fontWeight: 600, color: '#0A0B0D', backgroundColor: '#C8A434', borderRadius: '6px', padding: '6px 12px', opacity: busy.has(rowKey) ? 0.6 : 1 }}
                      >
                        Save
                      </button>
                      <button
                        onClick={() => handleTest(existing)}
                        disabled={busy.has(rowKey)}
                        className="cursor-pointer border-none"
                        style={{ fontSize: '11px', fontWeight: 600, color: '#C8A434', backgroundColor: 'rgba(200,164,52,0.08)', border: '1px solid rgba(200,164,52,0.2)', borderRadius: '6px', padding: '6px 12px', opacity: busy.has(rowKey) ? 0.6 : 1 }}
                      >
                        Test Connection
                      </button>
                      <button
                        onClick={() => handleDelete(existing)}
                        disabled={busy.has(rowKey)}
                        className="cursor-pointer border-none"
                        style={{ fontSize: '11px', fontWeight: 600, color: '#E74C3C', backgroundColor: 'rgba(231,76,60,0.08)', border: '1px solid rgba(231,76,60,0.2)', borderRadius: '6px', padding: '6px 12px', opacity: busy.has(rowKey) ? 0.6 : 1 }}
                      >
                        Remove
                      </button>
                    </div>
                  </div>
                  {renderFields(
                    def,
                    rowKey,
                    (f) => draft[f.key] ?? (f.secret ? '' : existing.config[f.key] ?? ''),
                    (f, value) => setEditField(existing.id, f.key, value),
                    '••••••••••••',
                  )}
                </div>
              )
            })}

            {draftRows.map((draft) => {
              const rowKey = `n-${draft.id}`
              return (
                <div key={draft.id} style={cardBase}>
                  <div className="flex items-center justify-between" style={{ marginBottom: '16px' }}>
                    <span style={{ fontSize: '13px', color: '#E8E6E0', fontWeight: 600 }}>New {def.name}</span>
                    <div className="flex items-center gap-2">
                      {statusMsg[rowKey] && (
                        <span style={{ fontSize: '11px', color: '#7A7D85' }}>{statusMsg[rowKey]}</span>
                      )}
                      <button
                        onClick={() => handleSaveNew(def, draft)}
                        disabled={busy.has(rowKey)}
                        className="cursor-pointer border-none"
                        style={{ fontSize: '11px', fontWeight: 600, color: '#0A0B0D', backgroundColor: '#C8A434', borderRadius: '6px', padding: '6px 12px', opacity: busy.has(rowKey) ? 0.6 : 1 }}
                      >
                        Save
                      </button>
                      <button
                        onClick={() => removeNewDraft(draft.id)}
                        className="cursor-pointer border-none"
                        style={{ fontSize: '11px', fontWeight: 600, color: '#7A7D85', backgroundColor: 'rgba(255,255,255,0.04)', border: '1px solid rgba(255,255,255,0.1)', borderRadius: '6px', padding: '6px 12px' }}
                      >
                        Cancel
                      </button>
                    </div>
                  </div>
                  {renderFields(
                    def,
                    rowKey,
                    (f) => draft.values[f.key] ?? '',
                    (f, value) => setNewDraftField(draft.id, f.key, value),
                    '',
                  )}
                </div>
              )
            })}

            {existingRows.length === 0 && draftRows.length === 0 && (
              <button
                onClick={() => addNewDraft(def.type)}
                className="cursor-pointer self-start"
                style={{ fontSize: '12px', fontWeight: 600, color: '#C8A434', backgroundColor: 'rgba(200,164,52,0.08)', border: '1px solid rgba(200,164,52,0.2)', borderRadius: '8px', padding: '9px 16px' }}
              >
                + Add {def.name}
              </button>
            )}
            {canAddAnother && (existingRows.length > 0 || draftRows.length > 0) && (
              <button
                onClick={() => addNewDraft(def.type)}
                className="cursor-pointer self-start"
                style={{ fontSize: '12px', fontWeight: 600, color: '#C8A434', backgroundColor: 'rgba(200,164,52,0.08)', border: '1px solid rgba(200,164,52,0.2)', borderRadius: '8px', padding: '9px 16px' }}
              >
                + Add Another {def.name}
              </button>
            )}
          </div>
        )
      })}
    </div>
  )
}

function NotificationsSection() {
  const [enabled, setEnabled] = useState(true)
  const [email, setEmail] = useState(true)
  const [push, setPush] = useState(false)
  const [sound, setSound] = useState(true)

  return (
    <div style={cardBase}>
      <h3 style={sectionTitle}>Notifications</h3>

      <div className="flex items-center justify-between" style={{ marginBottom: '20px' }}>
        <span style={{ fontSize: '13px', color: '#E8E6E0' }}>Enable Notifications</span>
        <Toggle on={enabled} onClick={() => setEnabled((v) => !v)} />
      </div>

      <div style={{ marginBottom: '20px' }}>
        <label style={labelStyle}>Alert Threshold</label>
        <select style={{ ...inputStyle, width: '220px' }} defaultValue="all">
          <option value="all">All</option>
          <option value="critical">Critical Only</option>
          <option value="warning">Warning & Above</option>
        </select>
      </div>

      <div className="flex items-center justify-between" style={{ marginBottom: '16px' }}>
        <span style={{ fontSize: '13px', color: '#E8E6E0' }}>Email Notifications</span>
        <Toggle on={email} onClick={() => setEmail((v) => !v)} />
      </div>

      <div className="flex items-center justify-between" style={{ marginBottom: '16px' }}>
        <span style={{ fontSize: '13px', color: '#E8E6E0' }}>Browser Push</span>
        <Toggle on={push} onClick={() => setPush((v) => !v)} />
      </div>

      <div className="flex items-center justify-between" style={{ marginBottom: '8px' }}>
        <span style={{ fontSize: '13px', color: '#E8E6E0' }}>Sound</span>
        <Toggle on={sound} onClick={() => setSound((v) => !v)} />
      </div>
      {sound && (
        <input type="range" min={0} max={100} defaultValue={70} className="w-full" style={{ accentColor: '#C8A434' }} />
      )}
    </div>
  )
}

function DataBackupSection() {
  const [busy, setBusy] = useState(false)
  const [message, setMessage] = useState<string | null>(null)
  const [error, setError] = useState<string | null>(null)
  const importRef = useRef<HTMLInputElement | null>(null)

  async function handleExport() {
    setBusy(true)
    setError(null)
    setMessage(null)
    try {
      const data = await api.exportData()
      const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' })
      const url = URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = url
      a.download = `archnest-backup-${new Date().toISOString().slice(0, 10)}.json`
      a.click()
      URL.revokeObjectURL(url)
      setMessage(`Exported ${data.integrations.length} integrations, ${data.bookmarks.length} bookmarks, ${data.tunnels.length} tunnels.`)
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Export failed')
    } finally {
      setBusy(false)
    }
  }

  async function handleImportFile(file: File) {
    setBusy(true)
    setError(null)
    setMessage(null)
    try {
      const text = await file.text()
      const parsed = JSON.parse(text)
      const result = await api.importData(parsed)
      const c = result.imported
      setMessage(`Imported ${c.integrations} integrations, ${c.bookmarkCategories} categories, ${c.bookmarks} bookmarks, ${c.tunnels} tunnels.`)
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Import failed — is this a valid ArchNest backup file?')
    } finally {
      setBusy(false)
    }
  }

  return (
    <div style={cardBase}>
      <h3 style={sectionTitle}>Data & Backup</h3>
      <p style={{ fontSize: '12px', color: '#7A7D85', marginBottom: '16px', maxWidth: '460px' }}>
        Export a portable backup of all integrations (including their credentials), bookmarks, and tunnels as a single JSON file, or
        import one into this instance. Imports are additive — existing data is kept and the backup's items are added alongside it.
        The backup contains plaintext credentials, so store it securely.
      </p>
      <div className="flex flex-col gap-3" style={{ maxWidth: '460px' }}>
        <div className="flex items-center justify-between">
          <span style={{ fontSize: '13px', color: '#E8E6E0' }}>Export all data (JSON)</span>
          <GoldButton onClick={handleExport} disabled={busy}>
            <Download size={13} /> Export
          </GoldButton>
        </div>
        <div className="flex items-center justify-between">
          <span style={{ fontSize: '13px', color: '#E8E6E0' }}>Import from backup (JSON)</span>
          <GoldButton onClick={() => importRef.current?.click()} disabled={busy}>
            <Upload size={13} /> Import
          </GoldButton>
          <input
            ref={importRef}
            type="file"
            accept="application/json,.json"
            className="hidden"
            onChange={(e) => {
              const file = e.target.files?.[0]
              if (file) handleImportFile(file)
              e.target.value = ''
            }}
          />
        </div>
        {message && <p style={{ fontSize: '12px', color: '#2ECC71' }}>{message}</p>}
        {error && <p style={{ fontSize: '12px', color: '#E74C3C' }}>{error}</p>}
      </div>
    </div>
  )
}

function AboutSection() {
  const rows: [string, string][] = [
    ['App', 'ArchNest Dashboard v1.0.0'],
    ['Author', 'Samuel James'],
    ['Repo', 'github.com/SamuelSJames/archnest'],
    ['Stack', 'React 19, Vite, TypeScript'],
    ['License', 'MIT'],
  ]
  return (
    <div style={cardBase}>
      <h3 style={sectionTitle}>About</h3>
      <div className="flex flex-col gap-3">
        {rows.map(([label, value]) => (
          <div key={label} className="flex items-center justify-between">
            <span style={{ fontSize: '12px', color: '#7A7D85' }}>{label}</span>
            <span style={{ fontSize: '12px', color: '#E8E6E0' }}>{value}</span>
          </div>
        ))}
      </div>
    </div>
  )
}

const sectionComponents: Record<string, () => React.ReactElement> = {
  profile: ProfileSection,
  appearance: AppearanceSection,
  integrations: IntegrationsSection,
  notifications: NotificationsSection,
  data: DataBackupSection,
  about: AboutSection,
}

export default function Settings() {
  const [active, setActive] = useState('profile')
  const ActiveSection = sectionComponents[active]

  return (
    <div className="flex h-full w-full gap-5">
      {/* Settings nav */}
      <div className="flex flex-col gap-1 shrink-0" style={{ width: '200px' }}>
        {navSections.map((s) => {
          const Icon = s.icon
          const isActive = active === s.id
          return (
            <button
              key={s.id}
              onClick={() => setActive(s.id)}
              className="flex items-center gap-2.5 cursor-pointer border-none bg-transparent transition-colors"
              style={{
                fontSize: '13px',
                fontWeight: 500,
                padding: '10px 14px',
                borderRadius: '8px',
                color: isActive ? '#C8A434' : '#7A7D85',
                backgroundColor: isActive ? 'rgba(200,164,52,0.1)' : 'transparent',
              }}
            >
              <Icon size={15} />
              {s.label}
            </button>
          )
        })}
      </div>

      {/* Content */}
      <div className="flex-1 overflow-y-auto" style={{ scrollbarWidth: 'none' }}>
        <ActiveSection />
      </div>
    </div>
  )
}
