import { useCallback, useEffect, useRef, useState } from 'react'
import { Loading, ErrorState } from '../../../components/PageState.jsx'
import { api } from '../../../api/client.js'

// Discord bot control panel (Phase 1). The bot token is write-only over this
// API — stored encrypted in the DB, never returned — same convention as the
// Google/Discord login-SSO secrets on the Authentication page. Saving pushes
// the config straight to the bot process, so Enabled takes effect immediately
// with no redeploy.

function Toggle({ checked, onChange, label }) {
  return (
    <label className="sans" style={{ display: 'inline-flex', alignItems: 'center', gap: 10, cursor: 'pointer', fontSize: '0.9rem', color: 'var(--ink)' }}>
      <input type="checkbox" checked={checked} onChange={(e) => onChange(e.target.checked)} />
      {label}
    </label>
  )
}

const STATUS_COLOR = {
  connected: '#7fd0a4',
  connecting: '#e0b070',
  error: '#d98b84',
  disconnected: 'var(--muted)',
}

function StatusPanel({ config }) {
  const color = STATUS_COLOR[config.status] || 'var(--muted)'
  return (
    <div style={{ border: '1px solid var(--line)', borderRadius: 10, padding: 16, display: 'flex', flexDirection: 'column', gap: 6 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
        <span style={{ width: 9, height: 9, borderRadius: '50%', background: color, boxShadow: `0 0 8px ${color}` }} />
        <span className="sans" style={{ fontSize: '0.9rem', color: 'var(--ink)', textTransform: 'capitalize' }}>
          {config.status || 'disconnected'}
        </span>
      </div>
      {config.statusDetail && (
        <p className="sans" style={{ margin: 0, fontSize: '0.82rem', color: 'var(--muted)' }}>{config.statusDetail}</p>
      )}
      {config.lastConnectedAt && (
        <p className="sans dim" style={{ margin: 0, fontSize: '0.78rem' }}>
          Last connected: {new Date(config.lastConnectedAt).toLocaleString()}
        </p>
      )}
    </div>
  )
}

export default function DiscordBotAdmin() {
  const [config, setConfig] = useState(null)
  const [error, setError] = useState('')
  const [guildId, setGuildId] = useState('')
  const [token, setToken] = useState('')
  const [enabled, setEnabled] = useState(false)
  const [busy, setBusy] = useState(false)
  const [msg, setMsg] = useState('')
  const [saveError, setSaveError] = useState('')
  const pollRef = useRef(null)

  // Only the very first load seeds the editable fields (guildId/enabled).
  // Every subsequent poll tick updates `config` (status/hasToken/etc.) so the
  // live-status panel stays fresh, but must NOT touch the form state — doing
  // so would silently overwrite whatever the admin is mid-typing/toggling
  // before they get a chance to hit Save.
  const initializedRef = useRef(false)

  const load = useCallback(async () => {
    try {
      const c = await api.admin.getDiscordBotConfig()
      setConfig(c)
      if (!initializedRef.current) {
        setGuildId(c.guildId || '')
        setEnabled(c.enabled)
        initializedRef.current = true
      }
    } catch {
      setError('Could not load Discord bot config.')
    }
  }, [])

  useEffect(() => {
    load()
    pollRef.current = setInterval(load, 5000)
    return () => clearInterval(pollRef.current)
  }, [load])

  async function save() {
    setBusy(true)
    setMsg('')
    setSaveError('')
    try {
      const body = { guildId, enabled }
      if (token) body.token = token // only send a new token when entered
      const saved = await api.admin.saveDiscordBotConfig(body)
      setConfig(saved)
      setToken('')
      setMsg('Saved.')
    } catch (err) {
      setSaveError(err.message || 'Could not save.')
    } finally {
      setBusy(false)
    }
  }

  if (error) return <ErrorState message={error} />
  if (!config) return <Loading />

  return (
    <section style={{ maxWidth: 560, display: 'flex', flexDirection: 'column', gap: 20 }}>
      <h2 className="display" style={{ margin: 0, fontSize: '1.2rem', color: 'var(--head)' }}>
        Discord Bot
      </h2>

      <StatusPanel config={config} />

      <Toggle checked={enabled} onChange={setEnabled} label="Enable the bot" />

      <label style={{ display: 'block' }}>
        <span className="field-label">Guild (server) ID</span>
        <input
          type="text"
          value={guildId}
          onChange={(e) => setGuildId(e.target.value)}
          className="input"
          autoComplete="off"
          placeholder="123456789012345678"
        />
      </label>

      <label style={{ display: 'block' }}>
        <span className="field-label">Bot Token</span>
        <input
          type="password"
          value={token}
          onChange={(e) => setToken(e.target.value)}
          className="input"
          autoComplete="new-password"
          placeholder={config.hasToken ? '•••••••• configured — leave blank to keep' : 'Bot token'}
        />
      </label>

      <div style={{ display: 'flex', gap: 10, alignItems: 'center', marginTop: 4 }}>
        <button onClick={save} disabled={busy} className="btn btn-primary btn-sq">
          {busy ? 'Saving…' : 'Save changes'}
        </button>
        {msg && <span className="sans" style={{ color: '#7fd0a4', fontSize: '0.85rem' }}>{msg}</span>}
        {saveError && <span className="sans" style={{ color: '#d98b84', fontSize: '0.85rem' }}>{saveError}</span>}
      </div>
    </section>
  )
}
