import { StrictMode, useCallback, useEffect, useMemo, useState } from 'react'
import { createRoot } from 'react-dom/client'
import { invoke } from '@tauri-apps/api/core'
import './design-tokens.css'
import './styles.css'

type ThemeId = 'night' | 'dawn' | 'nebula' | 'candle' | 'clear'
type Panel = 'channel' | 'receipts' | 'settings' | null

interface HomeStatus {
  schema: string
  directLocalBrokerState: string
  directConnectionCount: number
  resumableSessionCount: number
  codeRepositoryMountCount: number
  pnccReceiptCount: number
  updateState: string
  automaticUpstreamUpdates: boolean
  mcpRole: string
}

interface DiscoveryTicketReceipt {
  schema: string
  state: string
  accountKey: string
  laneId: string
  clientInstanceId: string
  discoveryTicket: string
  issuedAtUnixMs: number
  receiptId: string
}

interface ReceiptEvent {
  sequence: number
  kind: string
  observedAtUnixMs: number
  eventHash: string
}

interface ReceiptProjection {
  events: ReceiptEvent[]
  returnedEventCount: number
  lastSequence: number
}

const themes: Array<{ id: ThemeId; name: string }> = [
  { id: 'night', name: '夜湖星光' },
  { id: 'dawn', name: '晨湖曦光' },
  { id: 'nebula', name: '星云紫夜' },
  { id: 'candle', name: '烛畔暖湖' },
  { id: 'clear', name: '清浅澄湖' },
]

const previewStatus: HomeStatus = {
  schema: 'hololake.home-status/preview',
  directLocalBrokerState: 'PREVIEW',
  directConnectionCount: 0,
  resumableSessionCount: 0,
  codeRepositoryMountCount: 0,
  pnccReceiptCount: 0,
  updateState: 'UNPROVISIONED_FAIL_CLOSED',
  automaticUpstreamUpdates: false,
  mcpRole: 'DISCOVERY_RECOVERY_COMPATIBILITY_ONLY',
}

function getOrCreateLocalId(key: string, prefix: string) {
  const existing = window.localStorage.getItem(key)
  if (existing) return existing
  const generated = `${prefix}-${crypto.randomUUID()}`
  window.localStorage.setItem(key, generated)
  return generated
}

function Icon({ name }: { name: 'settings' | 'arrow' | 'receipt' | 'close' | 'copy' }) {
  const paths = {
    settings: <><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .34 1.88l.06.06-1.9 1.9-.06-.06a1.7 1.7 0 0 0-1.88-.34 1.7 1.7 0 0 0-1.04 1.56V20h-2.7v-.08a1.7 1.7 0 0 0-1.05-1.56 1.7 1.7 0 0 0-1.88.34l-.06.06-1.9-1.9.06-.06A1.7 1.7 0 0 0 7.72 15a1.7 1.7 0 0 0-1.56-1.04H6v-2.7h.08A1.7 1.7 0 0 0 7.64 10a1.7 1.7 0 0 0-.34-1.88l-.06-.06 1.9-1.9.06.06a1.7 1.7 0 0 0 1.88.34A1.7 1.7 0 0 0 12.12 5V5h2.7v.08a1.7 1.7 0 0 0 1.04 1.56 1.7 1.7 0 0 0 1.88-.34l.06-.06 1.9 1.9-.06.06a1.7 1.7 0 0 0-.34 1.88 1.7 1.7 0 0 0 1.56 1.04H21v2.7h-.08A1.7 1.7 0 0 0 19.4 15Z"/></>,
    arrow: <><path d="M5 12h13"/><path d="m14 7 5 5-5 5"/></>,
    receipt: <><path d="M7 3h10v18l-2.5-1.5L12 21l-2.5-1.5L7 21Z"/><path d="M10 8h4M10 12h4"/></>,
    close: <><path d="m7 7 10 10M17 7 7 17"/></>,
    copy: <><rect x="8" y="8" width="10" height="11" rx="2"/><path d="M15 8V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h2"/></>,
  }
  return <svg viewBox="0 0 24 24" aria-hidden="true">{paths[name]}</svg>
}

function HoloLakeApp() {
  const [theme, setTheme] = useState<ThemeId>(() => (window.localStorage.getItem('hololake-theme') as ThemeId) || 'night')
  const [status, setStatus] = useState<HomeStatus>(previewStatus)
  const [panel, setPanel] = useState<Panel>(null)
  const [ticket, setTicket] = useState<DiscoveryTicketReceipt | null>(null)
  const [receipts, setReceipts] = useState<ReceiptEvent[]>([])
  const [message, setMessage] = useState('')

  const refreshStatus = useCallback(async () => {
    try {
      setStatus(await invoke<HomeStatus>('get_hololake_home_status'))
    } catch {
      setStatus(previewStatus)
    }
  }, [])

  useEffect(() => {
    void refreshStatus()
    const timer = window.setInterval(() => void refreshStatus(), 3000)
    return () => window.clearInterval(timer)
  }, [refreshStatus])

  useEffect(() => {
    document.documentElement.dataset.theme = theme
    window.localStorage.setItem('hololake-theme', theme)
  }, [theme])

  const connectionState = useMemo(() => {
    if (status.directConnectionCount > 0) return { label: '已连接', detail: `${status.directConnectionCount} 个直连通道在线`, tone: 'ready' }
    if (status.resumableSessionCount > 0) return { label: '可续接', detail: `${status.resumableSessionCount} 个会话等待续接`, tone: 'waiting' }
    return { label: '等待连接', detail: '本机直连核心已就绪', tone: 'quiet' }
  }, [status])

  const openReceipts = async () => {
    setPanel('receipts')
    try {
      const projection = await invoke<ReceiptProjection>('query_pncc_receipt_projection', { input: { afterSequence: 0, limit: 25 } })
      setReceipts(projection.events)
    } catch {
      setReceipts([])
    }
  }

  const issueInvitation = async () => {
    setMessage('')
    try {
      const receipt = await invoke<DiscoveryTicketReceipt>('issue_direct_local_discovery_ticket', {
        input: {
          accountId: getOrCreateLocalId('hololake-local-account', 'human-local'),
          laneId: 'personal-channel',
          clientInstanceId: getOrCreateLocalId('hololake-external-ai-client', 'external-ai'),
        },
      })
      setTicket(receipt)
      setMessage('连接邀请已生成。它只在这台电脑上有效。')
    } catch (error) {
      setMessage(`暂时无法生成连接邀请：${String(error)}`)
    }
  }

  const invitationText = ticket ? JSON.stringify({
    schema: 'hololake.direct-local-invitation/v1',
    transport: 'INSTALLED_HOLOLAKE_EXECUTABLE_WITH_CONNECTOR_FLAG',
    connectorArgument: '--connector',
    openSession: {
      operation: 'OPEN_SESSION',
      input: {
        accountId: window.localStorage.getItem('hololake-local-account'),
        laneId: ticket.laneId,
        clientInstanceId: ticket.clientInstanceId,
        discoveryTicket: ticket.discoveryTicket,
      },
    },
    mcpRole: 'DISCOVERY_RECOVERY_COMPATIBILITY_ONLY',
  }, null, 2) : ''

  const copyInvitation = async () => {
    try {
      await navigator.clipboard.writeText(invitationText)
      setMessage('已复制。把它交给桌面上的编程 AI 即可。')
    } catch {
      setMessage('复制没有成功，请选中下方邀请内容后复制。')
    }
  }

  return (
    <div className="world-shell">
      <div className="scene-image" aria-hidden="true" />
      <div className="nebula nebula-one" aria-hidden="true" />
      <div className="nebula nebula-two" aria-hidden="true" />
      <div className="mist" aria-hidden="true" />
      <div className="stars" aria-hidden="true">{Array.from({ length: 18 }, (_, index) => <i key={index} style={{ '--star-index': index } as React.CSSProperties} />)}</div>
      <div className="glimmers" aria-hidden="true">{Array.from({ length: 11 }, (_, index) => <i key={index} style={{ '--glimmer-index': index } as React.CSSProperties} />)}</div>

      <header className="world-header">
        <div className="world-mark">
          <span className="world-name">光湖</span>
          <span className="world-route">个人频道</span>
        </div>
        <button className="icon-button" type="button" aria-label="打开设置" onClick={() => setPanel('settings')}><Icon name="settings" /></button>
      </header>

      <main className="home-content">
        <section className="hero" aria-labelledby="home-title">
          <p className="route-kicker">HOLOLAKE · PERSONAL CHANNEL</p>
          <h1 id="home-title">语言进入这里，<br />成为可见、可续的现实。</h1>
          <p className="hero-copy">外部编程 AI 从本机进入。HoloLake 保存路线、边界与回执；五个域安静地运行在湖底。</p>
          <div className="hero-actions">
            <button className="primary-action" type="button" onClick={() => setPanel('channel')}>
              {status.directConnectionCount > 0 ? '已连接 · 查看通道' : '连接编程 AI'}
              <Icon name="arrow" />
            </button>
            <button className="secondary-action" type="button" onClick={() => void openReceipts()}><Icon name="receipt" />查看回执</button>
          </div>
        </section>

        <section className="status-cluster" aria-label="光湖运行状态">
          <article className="status-item">
            <span className={`status-light ${connectionState.tone}`} aria-hidden="true" />
            <div><h2>本机直连通道</h2><p>{connectionState.detail}</p></div>
          </article>
          <article className="status-item">
            <span className={`status-light ${status.codeRepositoryMountCount > 0 ? 'ready' : 'quiet'}`} aria-hidden="true" />
            <div><h2>代码通道仓库</h2><p>{status.codeRepositoryMountCount > 0 ? `已验证 · ${status.codeRepositoryMountCount} 个仓库` : '等待人类确认绑定'}</p></div>
          </article>
          <article className="status-item">
            <span className={`status-light ${status.updateState.startsWith('READY') ? 'ready' : 'quiet'}`} aria-hidden="true" />
            <div><h2>更新广播</h2><p>{status.updateState.startsWith('READY') ? '仅接收光湖签名广播' : '信任根未配置 · 已关闭联网'}</p></div>
          </article>
        </section>
      </main>

      <footer className="world-footer">
        <p><b>GH-AIOS</b><span>光湖人工智能操作系统</span></p>
        <p className="trust-note"><i />你的工作留在本机 · 连接与更新均需确认</p>
      </footer>

      {panel && <div className="panel-backdrop" role="presentation" onMouseDown={(event) => event.target === event.currentTarget && setPanel(null)}>
        <section className="detail-panel" role="dialog" aria-modal="true" aria-labelledby="panel-title">
          <button className="panel-close" type="button" aria-label="关闭" onClick={() => setPanel(null)}><Icon name="close" /></button>
          {panel === 'channel' && <>
            <p className="panel-kicker">个人频道</p>
            <h2 id="panel-title">让编程 AI 从本机进入</h2>
            <p className="panel-intro">MCP 只负责发现和恢复。进入后，编程 AI 使用 HoloLake 的本机直连通道；电脑不关，驻留核心就一直在。</p>
            <div className="connection-summary"><span className={`status-light ${connectionState.tone}`} /><div><b>{connectionState.label}</b><span>{connectionState.detail}</span></div></div>
            {ticket ? <>
              <button className="primary-action panel-action" type="button" onClick={() => void copyInvitation()}><Icon name="copy" />复制给编程 AI</button>
              <pre className="invitation-preview">{invitationText}</pre>
            </> : <button className="primary-action panel-action" type="button" onClick={() => void issueInvitation()}>生成一次性连接邀请<Icon name="arrow" /></button>}
            {message && <p className="panel-message" aria-live="polite">{message}</p>}
            <p className="boundary-note">连接邀请不赋予服务器权限。写入、发布与更新仍分别确认并留下回执。</p>
          </>}
          {panel === 'receipts' && <>
            <p className="panel-kicker">可核验的发生</p>
            <h2 id="panel-title">代码通道回执</h2>
            <p className="panel-intro">这里是只读投影，不是权限来源。没有回执，也不代表服务器离线。</p>
            {receipts.length ? <ol className="receipt-list">{receipts.map((receipt) => <li key={receipt.sequence}><span>{receipt.sequence.toString().padStart(2, '0')}</span><div><b>{receipt.kind === 'REPOSITORY_BINDING_REVALIDATED' ? '仓库绑定已复核' : '远端对象读取已验证'}</b><small>{new Date(Number(receipt.observedAtUnixMs)).toLocaleString('zh-CN')} · {receipt.eventHash.slice(0, 12)}</small></div></li>)}</ol> : <div className="empty-state"><i /><b>湖面还没有新回执</b><span>完成代码仓库绑定或读取后，这里会出现可核验记录。</span></div>}
          </>}
          {panel === 'settings' && <>
            <p className="panel-kicker">湖面设置</p>
            <h2 id="panel-title">选择你看见光湖的方式</h2>
            <p className="panel-intro">只改变光与色。布局、文案、连接边界和底层路由保持不变。</p>
            <div className="theme-list">{themes.map((choice) => <button key={choice.id} type="button" className={theme === choice.id ? 'selected' : ''} onClick={() => setTheme(choice.id)}><i className={`theme-swatch ${choice.id}`} /><span><b>{choice.name}</b><small>{choice.id === 'night' ? '当前定版基色' : '五色湖定版主题'}</small></span><em>{theme === choice.id ? '已选择' : ''}</em></button>)}</div>
            <p className="boundary-note">上游自动更新保持关闭。正式更新只接受 HoloLake 自有信任根的签名广播，并由你确认。</p>
          </>}
        </section>
      </div>}
    </div>
  )
}

createRoot(document.getElementById('root')!).render(<StrictMode><HoloLakeApp /></StrictMode>)
