// useTerminalSocket 封装管理员终端的双向 WebSocket，结构照搬 useRunStream：
//   - connect + 自动重连（指数退避 1s/3s，最多 2 次）
//   - server→client：二进制帧 = shell 输出，回调喂给 xterm
//   - client→server：二进制帧 = stdin 原始字节；文本帧 JSON = resize 控制
// 浏览器原生 WS 不支持自定义 header，token 经 ?token= 传递（同 run/acp WS 约定）。
import { ref, onScopeDispose, type Ref } from 'vue'
import { useAuthStore } from '@/stores/auth'

export type TerminalStatus = 'idle' | 'connecting' | 'open' | 'closed' | 'error'

export interface UseTerminalSocketOptions {
  // onData 接收 shell 输出（已解码为字符串）。
  onData: (text: string) => void
  // 首次连接的初始窗口尺寸。
  initialRows?: number
  initialCols?: number
}

export interface UseTerminalSocketReturn {
  status: Ref<TerminalStatus>
  sendInput: (data: string) => void
  sendResize: (rows: number, cols: number) => void
  reconnect: () => void
  close: () => void
}

function wsURL(rows: number, cols: number, token: string): string {
  const proto = window.location.protocol === 'https:' ? 'wss' : 'ws'
  const host = window.location.host
  return (
    `${proto}://${host}/api/v1/admin/terminal/stream` +
    `?rows=${rows}&cols=${cols}&token=${encodeURIComponent(token)}`
  )
}

export function useTerminalSocket(opts: UseTerminalSocketOptions): UseTerminalSocketReturn {
  const status = ref<TerminalStatus>('idle')
  const rows = ref(opts.initialRows ?? 24)
  const cols = ref(opts.initialCols ?? 80)

  let ws: WebSocket | null = null
  let retried = 0
  let manualClose = false
  let reconnectTimer: ReturnType<typeof setTimeout> | null = null

  const auth = useAuthStore()
  const decoder = new TextDecoder()
  const encoder = new TextEncoder()

  function connect() {
    if (ws || manualClose) return
    status.value = 'connecting'
    const token = auth.token ?? ''
    const sock = new WebSocket(wsURL(rows.value, cols.value, token))
    sock.binaryType = 'arraybuffer'
    ws = sock

    sock.onopen = () => {
      status.value = 'open'
      retried = 0
    }

    sock.onmessage = (ev: MessageEvent) => {
      if (ev.data instanceof ArrayBuffer) {
        opts.onData(decoder.decode(new Uint8Array(ev.data)))
      } else if (typeof ev.data === 'string') {
        // 兼容性兜底：服务端目前只发二进制帧。
        opts.onData(ev.data)
      }
    }

    sock.onerror = () => {
      status.value = 'error'
    }

    sock.onclose = () => {
      ws = null
      if (manualClose) {
        status.value = 'closed'
        return
      }
      if (retried < 2) {
        const delay = retried === 0 ? 1000 : 3000
        retried += 1
        reconnectTimer = setTimeout(connect, delay)
      } else {
        status.value = 'closed'
      }
    }
  }

  function sendInput(data: string) {
    if (!ws || ws.readyState !== WebSocket.OPEN) return
    ws.send(encoder.encode(data))
  }

  function sendResize(r: number, c: number) {
    rows.value = r
    cols.value = c
    if (!ws || ws.readyState !== WebSocket.OPEN) return
    ws.send(JSON.stringify({ type: 'resize', rows: r, cols: c }))
  }

  function reconnect() {
    if (ws) ws.close()
    retried = 0
    manualClose = false
    connect()
  }

  function close() {
    manualClose = true
    if (reconnectTimer) {
      clearTimeout(reconnectTimer)
      reconnectTimer = null
    }
    if (ws) ws.close()
    status.value = 'closed'
  }

  connect()
  onScopeDispose(close)

  return { status, sendInput, sendResize, reconnect, close }
}
