import { useCallback, useEffect, useMemo, useState } from 'react'
import { numberedInvoke } from './numbered-ipc'

export interface DirectSessionProjection {
  sessionId: string
  laneId: string
  clientInstanceId: string
  state: 'LIVE' | 'RESUMABLE'
  openedAtUnixMs: number
  observedAtUnixMs: number
  lastEventSequence: number
}

interface AuthorizationRequest {
  requestId: string
  action: 'OPEN_MAINTENANCE' | 'UNMOUNT' | 'PROMOTE_VERSION' | 'RETIRE'
  targetNumber: string
  targetKind: string
  targetLabel: string
  reason: string
  impact: string
  rollbackPlan: string
  requesterLabel: string
  state: 'PENDING_HUMAN' | 'APPROVED' | 'DENIED' | 'EXPIRED' | 'CONSUMED'
  createdAtUnixMs: number
  expiresAtUnixMs: number
  humanNumber?: string
  decidedAtUnixMs?: number
  ticketId?: string
  ticketExpiresAtUnixMs?: number
  consumedAtUnixMs?: number
  receiptHash: string
}

interface AuthorizationCenterSnapshot {
  state: string
  pendingCount: number
  requests: AuthorizationRequest[]
  purgeEnabled: boolean
}

interface Props {
  brokerState: string
  activeConnectionCount: number
  sessions: DirectSessionProjection[]
}

const actionLabels: Record<AuthorizationRequest['action'], string> = {
  OPEN_MAINTENANCE: '打开受控维护区',
  UNMOUNT: '从当前频道卸载',
  PROMOTE_VERSION: '登记并启用新版本',
  RETIRE: '停用并保留历史坐标',
}

const stateLabels: Record<AuthorizationRequest['state'], string> = {
  PENDING_HUMAN: '等待你决定', APPROVED: '已同意 · 等待执行体领取', DENIED: '已拒绝',
  EXPIRED: '已过期', CONSUMED: '票据已领取一次',
}

function time(value?: number) {
  return value ? new Date(value).toLocaleString('zh-CN', { hour12: false }) : '—'
}

export function HumanAuthorizationCenter({ brokerState, activeConnectionCount, sessions }: Props) {
  const [snapshot, setSnapshot] = useState<AuthorizationCenterSnapshot | null>(null)
  const [busy, setBusy] = useState('')
  const [message, setMessage] = useState('')

  const refresh = useCallback(async () => {
    try {
      setSnapshot(await numberedInvoke<AuthorizationCenterSnapshot>('get_authorization_center'))
      setMessage('')
    } catch (error) {
      setSnapshot(null)
      setMessage(String(error).includes('AUTHENTICATED_ACCOUNT_REQUIRED') ? '登录并完成编号验证后，授权中心才会打开。' : '授权中心当前不可读取；系统不会把未知状态当成已授权。')
    }
  }, [])

  useEffect(() => {
    void refresh()
    const timer = window.setInterval(() => { if (!document.hidden) void refresh() }, 4_000)
    return () => window.clearInterval(timer)
  }, [refresh])

  const decide = async (requestId: string, decision: 'APPROVE' | 'DENY') => {
    setBusy(requestId)
    setMessage('')
    try {
      await numberedInvoke('decide_authorization_request', { input: { requestId, decision } })
      setMessage(decision === 'APPROVE' ? '已签发一次性票据；它只对原执行会话和本次目标有效。' : '已拒绝；执行体不会获得继续通道。')
      await refresh()
    } catch {
      setMessage('这次决定没有写入。授权状态保持不变，请刷新后再看。')
    } finally {
      setBusy('')
    }
  }

  const pending = snapshot?.requests.filter((item) => item.state === 'PENDING_HUMAN') || []
  const history = snapshot?.requests.filter((item) => item.state !== 'PENDING_HUMAN').slice(0, 6) || []
  const connectionState = activeConnectionCount > 0 ? '正在直连' : sessions.some((item) => item.state === 'LIVE') ? '最近仍有心跳' : '当前没有在线执行体'
  const sessionList = useMemo(() => sessions.slice(0, 6), [sessions])

  return <div className="human-authorization-layout">
    <section className="plain-panel authorization-primary">
      <header><div><span className="kicker">HUMAN DECISION</span><h2>需要你决定的事</h2><p>人格体提出申请，系统把对象、原因、影响和退路交给你；只有你点同意，原执行会话才会收到一次性票据。</p></div><span className={pending.length ? 'status-chip attention' : 'status-chip online'}>{pending.length ? `${pending.length} 项待确认` : '没有待确认事项'}</span></header>
      {pending.length === 0 ? <div className="authorization-empty"><b>现在不需要你操作</b><span>删除、停用、维护和正式更新不会在后台静默通过。</span></div> : <div className="authorization-list">
        {pending.map((request) => <article className="authorization-card" key={request.requestId}>
          <div className="authorization-card-title"><div><small>{actionLabels[request.action]}</small><h3>{request.targetLabel}</h3><code>{request.targetNumber}</code></div><span>{stateLabels[request.state]}</span></div>
          <dl><div><dt>为什么要做</dt><dd>{request.reason}</dd></div><div><dt>会影响什么</dt><dd>{request.impact}</dd></div><div><dt>出问题怎么退</dt><dd>{request.rollbackPlan}</dd></div><div><dt>谁在申请</dt><dd>{request.requesterLabel}</dd></div><div><dt>申请到期</dt><dd>{time(request.expiresAtUnixMs)}</dd></div></dl>
          <div className="authorization-actions"><button className="secondary-button" disabled={busy === request.requestId} onClick={() => void decide(request.requestId, 'DENY')}>拒绝</button><button className="primary-button" disabled={busy === request.requestId} onClick={() => void decide(request.requestId, 'APPROVE')}>{busy === request.requestId ? '正在写入决定…' : '同意并签发一次性票据'}</button></div>
        </article>)}
      </div>}
      {message && <p className="global-message">{message}</p>}
    </section>

    <section className="plain-panel collaboration-live">
      <header><div><span className="kicker">LIVE COLLABORATION</span><h2>当前谁连着 HoloLake</h2><p>这里显示真实本机会话和最近心跳，不把“装过 Agent”冒充成“正在连接”。</p></div><span className={activeConnectionCount > 0 ? 'status-chip online' : 'status-chip'}>{connectionState}</span></header>
      <div className="collaboration-summary"><div><b>{activeConnectionCount}</b><span>当前直连</span></div><div><b>{sessions.length}</b><span>可续接会话</span></div><div><b>{brokerState === 'READY' ? '就绪' : '等待'}</b><span>本机入口</span></div></div>
      {sessionList.length ? <div className="session-projection-list">{sessionList.map((session) => <article key={session.sessionId}><i className={session.state === 'LIVE' ? 'live' : ''}/><div><b>{session.clientInstanceId}</b><span>{session.laneId} · 最近心跳 {time(session.observedAtUnixMs)}</span></div><em>{session.state === 'LIVE' ? '在线' : '可续接'}</em></article>)}</div> : <div className="authorization-empty compact"><b>还没有执行体会话</b><span>外部编程 AI 通过 HoloLake 本机连接后，会在这里出现。</span></div>}
    </section>

    {history.length > 0 && <details className="authorization-history"><summary>最近的授权回执 · {history.length}</summary><div>{history.map((request) => <article key={request.requestId}><div><b>{request.targetLabel}</b><span>{actionLabels[request.action]}</span></div><em>{stateLabels[request.state]}</em><small>{request.humanNumber ? `由 ${request.humanNumber} 决定 · ` : ''}{time(request.decidedAtUnixMs || request.createdAtUnixMs)}</small></article>)}</div></details>}
  </div>
}
