import { Button } from '@overdeck/deck-ui'
import { useEffect, useState } from 'react'
import { postCollectorAction } from '../../lib/action-client'
import { useCollectorState } from '../../lib/collector-queries'
import type { PermissionGatePanelData } from '../../lib/panel-data'

const PERMISSION_GATE_PANEL_ID = 'permission-gate'
/** Comfortably inside the collector's arm window, so a live page never lapses. */
const REFRESH_MS = 20_000

async function setArmed(state: 'on' | 'off'): Promise<void> {
  await postCollectorAction('permission.arm', { args: { state }, requestedBy: 'deck-web' })
}

/**
 * Arms the collector's permission gate. Armed, every agent tool call parks in the
 * queue below until answered here; the window self-expires, so closing this page
 * hands every session back to its terminal.
 */
export function BrowserApprovalToggle() {
  const stateQuery = useCollectorState()
  const [now, setNow] = useState(() => Date.now())
  const [pendingToggle, setPendingToggle] = useState(false)
  const [error, setError] = useState<string | null>(null)

  const panel = stateQuery.data?.panels.find((entry) => entry.id === PERMISSION_GATE_PANEL_ID)
  const gate = panel?.data as PermissionGatePanelData | undefined
  const armedUntil = gate?.armedUntil ?? null
  const armed = armedUntil !== null && armedUntil > now

  useEffect(() => {
    if (!armed) return undefined
    const id = window.setInterval(() => setNow(Date.now()), 1_000)
    return () => window.clearInterval(id)
  }, [armed])

  useEffect(() => {
    if (!armed) return undefined
    // Background tabs get their timers throttled to roughly one tick a minute,
    // which is longer than the collector's arm window. Refreshing only while
    // visible lets a hidden page lapse into terminal prompts instead of holding
    // every session against a keepalive it can no longer deliver on time.
    const id = window.setInterval(() => {
      if (document.visibilityState !== 'visible') return
      void setArmed('on').catch(() => setError('Could not refresh the approval window'))
    }, REFRESH_MS)
    return () => window.clearInterval(id)
  }, [armed])

  if (stateQuery.data && !gate) {
    return (
      <p className="text-[12px] text-fg-muted">
        Browser approvals unavailable — the collector reported no permission gate.
      </p>
    )
  }

  const toggle = async () => {
    setPendingToggle(true)
    setError(null)
    try {
      await setArmed(armed ? 'off' : 'on')
      setNow(Date.now())
      await stateQuery.refetch()
    } catch {
      setError(armed ? 'Could not turn approvals off' : 'Could not turn approvals on')
    } finally {
      setPendingToggle(false)
    }
  }

  const waitSeconds = gate ? Math.round(gate.waitMs / 1_000) : null

  return (
    <div className="flex flex-wrap items-center gap-3">
      <Button
        size="sm"
        variant={armed ? 'solid' : 'outline'}
        tone={armed ? 'accent' : 'neutral'}
        aria-pressed={armed}
        disabled={pendingToggle || !gate}
        onClick={() => void toggle()}
        data-browser-approvals={armed ? 'on' : 'off'}
      >
        {armed ? 'Browser approvals on' : 'Browser approvals off'}
      </Button>
      <span className="text-[12px] text-fg-subtle">
        {armed
          ? `Agent tool calls wait here${waitSeconds === null ? '' : ` up to ${waitSeconds}s`} — unanswered calls fall back to the terminal.`
          : 'Off — every session uses its terminal prompt. Turn on to approve tool calls from this page.'}
      </span>
      {error === null ? null : <span className="text-[12px] text-danger">{error}</span>}
    </div>
  )
}
