// 本地 ASR 会话：前端 → ws://127.0.0.1:3721/voice/local → 按需拉起 Python 语音服务（3723）并双向转发
//
// 生命周期与云端 ASR 不同：本地引擎需要懒启动 Python 进程 + 等待模型加载，
// 所以这里不做"凭证检查 → 直连"的同步路径，而是：
//   1. ensureLocalVoiceServer() 确保 Python 进程在跑（engine 变更自动重启）
//   2. waitForVoiceReady() 轮询到 running（Python 先加载模型后起 WS，等端口即等模型）
//   3. 连 3723，open 后补发 {type:'config', lang}，再排空 pending 音频队列
import { WebSocket } from 'ws'
import { ensureLocalVoiceServer, waitForVoiceReady, VOICE_WS_PORT } from './manager.js'

// 启动期音频堆积上限（防止等待模型加载时无限缓存）
const MAX_PENDING_CHUNKS = 64

// config: { engine='sensevoice', modelDir=null, lang='zh' }
// 回调：onTranscript(text, isFinal), onError(message), onClose()
// 返回 { sendAudio(pcmBuffer), flush(), close() }；引擎不可用时返回 null 并调 onError
export function createLocalASRSession(config, onTranscript, onError, onClose) {
  const { engine = 'sensevoice', modelDir = null, lang = 'zh' } = config

  const started = ensureLocalVoiceServer({ engine, modelDir })
  if (started.status === 'error') {
    onError(started.message || '本地语音服务启动失败')
    return null
  }

  let ws = null
  let closed = false
  let ready = false
  let pending = []
  let pendingFlush = false  // 连接就绪前的 flush 请求（就绪后补发，防止触发丢失）

  const session = {
    sendAudio(pcmBuffer) {
      if (closed) return
      if (!ready) {
        if (pending.length < MAX_PENDING_CHUNKS) pending.push(Buffer.from(pcmBuffer))
        return
      }
      if (ws.readyState === WebSocket.OPEN) ws.send(pcmBuffer)
    },
    flush() {
      if (closed) return
      if (!ready) {
        pendingFlush = true
        return
      }
      if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ type: 'flush' }))
    },
    close() {
      if (closed) return
      closed = true
      try { ws?.close() } catch {}
    },
  }

  // 等待 Python 进程就绪（模型加载 + WS 监听）。失败 → onError 并返回失效会话。
  ;(async () => {
    if (closed) return
    const ok = await waitForVoiceReady()
    if (!ok || closed) {
      if (!closed) onError('本地语音服务未就绪，请查看服务日志')
      return
    }
    connect()
  })()

  function connect() {
    if (closed) return
    ws = new WebSocket(`ws://127.0.0.1:${VOICE_WS_PORT}`)
    ws.on('open', () => {
      if (closed) { try { ws.close() } catch {}; return }
      ws.send(JSON.stringify({ type: 'config', lang }))
      ready = true
      const queued = pending.splice(0)
      pending = []
      for (const chunk of queued) {
        if (ws.readyState === WebSocket.OPEN) ws.send(chunk)
      }
      if (pendingFlush) {
        pendingFlush = false
        ws.send(JSON.stringify({ type: 'flush' }))
      }
    })
    ws.on('message', (data) => {
      if (closed) return
      let msg
      try { msg = JSON.parse(data.toString()) } catch { return }
      if (msg.type === 'transcript') {
        onTranscript(String(msg.text || ''), msg.is_final !== false)
      } else if (msg.type === 'error') {
        onError(String(msg.message || '本地语音服务错误'))
      }
      // config_ok / ambient_voice / sound_event 等帧当前不转发，保持与云端会话一致
    })
    ws.on('error', (err) => {
      if (!closed) onError(`本地语音服务连接失败: ${err.message}`)
    })
    ws.on('close', () => {
      ready = false
      if (!closed) onClose()
    })
  }

  return session
}
