import { useCallback, useEffect, useRef, useState } from 'react'
import { useShardFeed } from '../../../lib/useShardFeed.js'
import { describe } from '../../../lib/shardEvents.js'
import { ago } from '../../../lib/format.js'
import { api } from '../../../api/client.js'

// In-game staff operations: the uo-link write plane (broadcast / kick / ban /
// unban) and the help-page support queue, plus a live audit log. Open to admins
// and moderators. The acting staff member (`actor`) is attached server-side from
// the session — nothing here sends it — so every action is attributable.

function Flash({ ok, err }) {
  if (ok) return <span className="sans" style={{ color: '#7fd0a4', fontSize: '0.85rem' }}>{ok}</span>
  if (err) return <span className="sans" style={{ color: '#d98b84', fontSize: '0.85rem' }}>{err}</span>
  return null
}

// ── Broadcast ────────────────────────────────────────────────────────────────
function Broadcast() {
  const [text, setText] = useState('')
  const [hue, setHue] = useState('')
  const [busy, setBusy] = useState(false)
  const [ok, setOk] = useState('')
  const [err, setErr] = useState('')

  async function send() {
    if (!text.trim()) return setErr('Enter a message.')
    setBusy(true); setOk(''); setErr('')
    try {
      await api.admin.shardOps.broadcast({ text: text.trim(), hue: hue === '' ? undefined : Number(hue) })
      setOk('Broadcast sent.')
      setText('')
    } catch (e) {
      setErr(e.message || 'Could not broadcast.')
    } finally {
      setBusy(false)
    }
  }

  return (
    <section style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
      <h3 className="display" style={{ margin: 0, fontSize: '1.05rem', color: 'var(--head)' }}>Broadcast</h3>
      <p className="sans" style={{ margin: 0, color: 'var(--muted)', fontSize: '0.86rem' }}>
        A system message shown to everyone online right now.
      </p>
      <label style={{ display: 'block' }}>
        <span className="field-label">Message</span>
        <input type="text" value={text} onChange={(e) => setText(e.target.value)} className="input" maxLength={300} placeholder="Server restart in 5 minutes" autoComplete="off" />
      </label>
      <label style={{ display: 'block', maxWidth: 140 }}>
        <span className="field-label">Hue (optional)</span>
        <input type="number" value={hue} onChange={(e) => setHue(e.target.value)} className="input" min={0} max={3000} placeholder="53" />
      </label>
      <div style={{ display: 'flex', gap: 10, alignItems: 'center' }}>
        <button onClick={send} disabled={busy} className="btn btn-primary btn-sq">{busy ? 'Sending…' : 'Broadcast'}</button>
        <Flash ok={ok} err={err} />
      </div>
    </section>
  )
}

// ── Account actions (kick / ban / unban) ─────────────────────────────────────
function AccountActions() {
  const [account, setAccount] = useState('')
  const [durationSec, setDurationSec] = useState('')
  const [reason, setReason] = useState('')
  const [busy, setBusy] = useState('')
  const [ok, setOk] = useState('')
  const [err, setErr] = useState('')

  const acct = account.trim()
  function guard() {
    if (!acct) {
      setErr('Enter an account name.')
      return false
    }
    return true
  }

  async function run(label, fn, done) {
    if (!guard()) return
    setBusy(label); setOk(''); setErr('')
    try {
      const r = await fn()
      setOk(done(r))
    } catch (e) {
      setErr(e.message || 'Action failed.')
    } finally {
      setBusy('')
    }
  }

  const kick = () =>
    run('kick', () => api.admin.shardOps.kick({ account: acct }), (r) => {
      const n = r?.sessions != null ? r.sessions : null
      const plural = n === 1 ? '' : 's'
      const sessions = n != null ? ` (${n} session${plural})` : ''
      return `Kicked ${acct}${sessions}.`
    })
  const ban = () =>
    run(
      'ban',
      () =>
        api.admin.shardOps.ban({
          account: acct,
          durationSec: durationSec === '' ? undefined : Number(durationSec),
          reason: reason.trim() || undefined,
        }),
      () => {
        const when = durationSec ? ` for ${durationSec}s` : ' indefinitely'
        return `Banned ${acct}${when}.`
      },
    )
  const unban = () => run('unban', () => api.admin.shardOps.unban(acct), () => `Unbanned ${acct}.`)

  return (
    <section style={{ borderTop: '1px solid var(--line-soft)', paddingTop: 22, display: 'flex', flexDirection: 'column', gap: 12 }}>
      <h3 className="display" style={{ margin: 0, fontSize: '1.05rem', color: 'var(--head)' }}>Account actions</h3>
      <p className="sans" style={{ margin: 0, color: 'var(--muted)', fontSize: '0.86rem' }}>
        Kick, ban or unban a game account. Bans work even if the account is offline; the shard refuses to act on staff at or above co-owner.
      </p>
      <label style={{ display: 'block' }}>
        <span className="field-label">Account</span>
        <input type="text" value={account} onChange={(e) => setAccount(e.target.value)} className="input" placeholder="griefer42" autoComplete="off" style={{ maxWidth: 260 }} />
      </label>
      <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap' }}>
        <label style={{ display: 'block', maxWidth: 200 }}>
          <span className="field-label">Ban duration (seconds, blank = permanent)</span>
          <input type="number" value={durationSec} onChange={(e) => setDurationSec(e.target.value)} className="input" min={0} placeholder="604800" />
        </label>
        <label style={{ display: 'block', flex: 1, minWidth: 200 }}>
          <span className="field-label">Ban reason (optional)</span>
          <input type="text" value={reason} onChange={(e) => setReason(e.target.value)} className="input" maxLength={500} placeholder="harassment" autoComplete="off" />
        </label>
      </div>
      <div style={{ display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap' }}>
        <button onClick={kick} disabled={!!busy} className="btn btn-sq">{busy === 'kick' ? 'Kicking…' : 'Kick'}</button>
        <button onClick={ban} disabled={!!busy} className="btn btn-sq" style={{ borderColor: '#d98b84', color: '#d98b84' }}>{busy === 'ban' ? 'Banning…' : 'Ban'}</button>
        <button onClick={unban} disabled={!!busy} className="btn btn-sq">{busy === 'unban' ? 'Unbanning…' : 'Unban'}</button>
        <Flash ok={ok} err={err} />
      </div>
    </section>
  )
}

// ── Support (help-page) queue ────────────────────────────────────────────────
function PageRow({ page, onDone }) {
  const [message, setMessage] = useState('')
  const [busy, setBusy] = useState('')
  const [err, setErr] = useState('')

  async function respond(close) {
    if (!message.trim()) return setErr('Enter a reply first.')
    setBusy(close ? 'respond-close' : 'respond'); setErr('')
    try {
      await api.admin.shardOps.respondPage(page.pageId, { message: message.trim(), close })
      onDone()
    } catch (e) {
      setErr(e.message || 'Could not send.')
      setBusy('')
    }
  }
  async function close() {
    setBusy('close'); setErr('')
    try {
      await api.admin.shardOps.closePage(page.pageId)
      onDone()
    } catch (e) {
      setErr(e.message || 'Could not close.')
      setBusy('')
    }
  }

  return (
    <div className="panel" style={{ padding: 14, display: 'flex', flexDirection: 'column', gap: 8 }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10 }}>
        <div style={{ minWidth: 0 }}>
          <span className="sans" style={{ fontSize: '0.62rem', letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--accent)' }}>{page.type || 'Page'}</span>
          <div className="sans" style={{ color: 'var(--head)', fontSize: '0.95rem' }}>
            {page.sender?.name || page.pageId}
            {page.handled && <span className="dim" style={{ fontSize: '0.72rem' }}> · claimed{page.handler ? ` by ${page.handler}` : ''}</span>}
          </div>
        </div>
        <span className="sans dim" style={{ flex: 'none', fontSize: '0.74rem' }}>{page.sentMs ? ago(page.sentMs) : ''}</span>
      </div>
      {page.message && <p className="sans" style={{ margin: 0, color: 'var(--ink)', fontSize: '0.88rem', lineHeight: 1.5 }}>{page.message}</p>}
      <div className="sans dim" style={{ fontSize: '0.72rem' }}>
        {page.map || '—'}{page.x != null ? ` (${page.x}, ${page.y})` : ''}
      </div>
      <textarea value={message} onChange={(e) => setMessage(e.target.value)} className="input" rows={2} placeholder="A GM is on the way." style={{ resize: 'vertical' }} />
      <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
        <button onClick={() => respond(false)} disabled={!!busy} className="btn btn-sq">{busy === 'respond' ? 'Sending…' : 'Reply'}</button>
        <button onClick={() => respond(true)} disabled={!!busy} className="btn btn-primary btn-sq">{busy === 'respond-close' ? 'Sending…' : 'Reply & close'}</button>
        <button onClick={close} disabled={!!busy} className="btn btn-sq" style={{ borderColor: '#d98b84', color: '#d98b84' }}>{busy === 'close' ? 'Closing…' : 'Close'}</button>
        {err && <span className="sans" style={{ color: '#d98b84', fontSize: '0.8rem' }}>{err}</span>}
      </div>
    </div>
  )
}

function SupportQueue() {
  const [pages, setPages] = useState(null)
  const [err, setErr] = useState('')
  const pollRef = useRef(null)

  const load = useCallback(async () => {
    try {
      setPages(await api.admin.shardOps.pages())
    } catch {
      setErr('Could not load the support queue.')
    }
  }, [])

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

  let queueBody
  if (pages == null) {
    queueBody = <p className="sans dim" style={{ margin: 0, fontSize: '0.86rem' }}>Loading…</p>
  } else if (pages.length === 0) {
    queueBody = <p className="sans dim" style={{ margin: 0, fontSize: '0.86rem' }}>The queue is empty.</p>
  } else {
    queueBody = (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {pages.map((p) => <PageRow key={p.pageId} page={p} onDone={load} />)}
      </div>
    )
  }

  return (
    <section style={{ borderTop: '1px solid var(--line-soft)', paddingTop: 22, display: 'flex', flexDirection: 'column', gap: 12 }}>
      <h3 className="display" style={{ margin: 0, fontSize: '1.05rem', color: 'var(--head)' }}>Support queue</h3>
      <p className="sans" style={{ margin: 0, color: 'var(--muted)', fontSize: '0.86rem' }}>
        Open help pages from players. A reply reaches them in game (or on their next login).
      </p>
      {err && <span className="sans" style={{ color: '#d98b84', fontSize: '0.85rem' }}>{err}</span>}
      {queueBody}
    </section>
  )
}

// ── Audit log ────────────────────────────────────────────────────────────────
// Seeded from the stored admin.audit history, then kept live from the admin SSE
// channel (which carries every kind — we filter to admin.audit here).
function AuditLog() {
  const [seed, setSeed] = useState([])
  const { events } = useShardFeed({ url: api.adminShardStreamUrl, filter: new Set(['admin.audit']), max: 50 })

  useEffect(() => {
    api.admin.shardOps
      .audit(50)
      .then((rows) => setSeed(rows.map((r) => ({ ...r, _id: `seed-${r.id}` }))))
      .catch(() => setSeed([]))
  }, [])

  // Live events on top; fall back to the seed for anything older than the live tail.
  const oldestLive = events.length ? Math.min(...events.map((e) => e.t || 0)) : Infinity
  const rows = [...events, ...seed.filter((s) => (s.t || 0) < oldestLive)].slice(0, 60)

  return (
    <section style={{ borderTop: '1px solid var(--line-soft)', paddingTop: 22 }}>
      <h3 className="display" style={{ margin: 0, fontSize: '1.05rem', color: 'var(--head)', marginBottom: 12 }}>Audit log</h3>
      {rows.length === 0 ? (
        <p className="sans dim" style={{ margin: 0, fontSize: '0.86rem' }}>No moderation actions recorded yet.</p>
      ) : (
        <ul style={{ listStyle: 'none', margin: 0, padding: 0, display: 'flex', flexDirection: 'column', gap: 6, maxHeight: 320, overflowY: 'auto' }}>
          {rows.map((e) => (
            <li key={e._id} style={{ display: 'flex', alignItems: 'center', gap: 10, fontSize: '0.85rem' }}>
              <span className="sans" style={{ flex: 1, minWidth: 0, color: 'var(--ink)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{describe(e)}</span>
              <span className="sans dim" style={{ flex: 'none', fontSize: '0.74rem' }}>{ago(e.t)}</span>
            </li>
          ))}
        </ul>
      )}
    </section>
  )
}

export default function ShardOps() {
  return (
    <section style={{ maxWidth: 620, display: 'flex', flexDirection: 'column', gap: 22 }}>
      <Broadcast />
      <AccountActions />
      <SupportQueue />
      <AuditLog />
    </section>
  )
}
