/**
 * MaiSaka 实时监控 WebSocket 客户端
 *
 * 订阅 maisaka_monitor 主题，接收推理引擎各阶段的实时事件。
 */
import type { WsEventEnvelope } from './unified-ws'

import { unifiedWsClient } from './unified-ws'

// ─── 事件数据类型 ───────────────────────────────────────────────

export interface MaisakaMessage {
  role: string
  content: string | null
  tool_call_id?: string
  tool_calls?: MaisakaToolCall[]
}

export interface MaisakaToolCall {
  id: string
  name: string
  arguments?: Record<string, unknown>
  arguments_raw?: string
}

export interface SessionStartEvent {
  session_id: string
  session_name: string
  is_group_chat?: boolean
  group_id?: string | null
  user_id?: string | null
  platform?: string
  timestamp: number
}

export interface MessageIngestedEvent {
  session_id: string
  speaker_name: string
  content: string
  message_id: string
  timestamp: number
}

export interface CycleStartEvent {
  session_id: string
  cycle_id: number
  round_index: number
  max_rounds: number
  history_count: number
  timestamp: number
}

export interface TimingGateResultEvent {
  session_id: string
  cycle_id: number
  action: 'continue' | 'wait' | 'no_reply'
  content: string | null
  tool_calls: MaisakaToolCall[]
  messages: MaisakaMessage[]
  prompt_tokens: number
  selected_history_count: number
  duration_ms: number
  timestamp: number
}

export interface PlannerRequestEvent {
  session_id: string
  cycle_id: number
  messages: MaisakaMessage[]
  tool_count: number
  selected_history_count: number
  timestamp: number
}

export interface PlannerResponseEvent {
  session_id: string
  cycle_id: number
  content: string | null
  tool_calls: MaisakaToolCall[]
  prompt_tokens: number
  completion_tokens: number
  total_tokens: number
  duration_ms: number
  timestamp: number
}

export interface ToolExecutionEvent {
  session_id: string
  cycle_id: number
  tool_name: string
  tool_args: Record<string, unknown>
  result_summary: string
  success: boolean
  duration_ms: number
  timestamp: number
}

export interface MaisakaRequestBlock {
  messages: MaisakaMessage[]
  selected_history_count: number
  tool_count: number
}

export interface MaisakaPlannerBlock {
  content: string | null
  tool_calls: MaisakaToolCall[]
  prompt_tokens: number
  completion_tokens: number
  total_tokens: number
  duration_ms: number
  prompt_html_uri?: string
}

export interface MaisakaTimingGateBlock {
  request: MaisakaRequestBlock | null
  result: {
    action: 'continue' | 'wait' | 'no_reply' | null
    content: string | null
    tool_calls: MaisakaToolCall[]
    tool_results: unknown[]
    prompt_tokens: number
    completion_tokens: number
    total_tokens: number
    duration_ms: number
  }
}

export interface MaisakaFinalizedToolResult {
  tool_call_id: string
  tool_name: string
  tool_args: Record<string, unknown>
  success: boolean
  duration_ms: number
  summary: string
  detail?: unknown
}

export interface PlannerFinalizedEvent {
  session_id: string
  cycle_id: number
  timestamp: number
  timing_gate: MaisakaTimingGateBlock | null
  request: MaisakaRequestBlock | null
  planner: MaisakaPlannerBlock | null
  tools: MaisakaFinalizedToolResult[]
  final_state: {
    time_records: Record<string, number>
    agent_state: string
  }
}

export interface CycleEndEvent {
  session_id: string
  cycle_id: number
  time_records: Record<string, number>
  agent_state: string
  timestamp: number
}

export interface ReplierRequestEvent {
  session_id: string
  messages: MaisakaMessage[]
  model_name: string
  timestamp: number
}

export interface ReplierResponseEvent {
  session_id: string
  content: string | null
  reasoning: string
  model_name: string
  prompt_tokens: number
  completion_tokens: number
  total_tokens: number
  duration_ms: number
  success: boolean
  timestamp: number
}

// ─── 统一事件联合类型 ─────────────────────────────────────────

export type MaisakaMonitorEvent =
  | { type: 'session.start'; data: SessionStartEvent }
  | { type: 'message.ingested'; data: MessageIngestedEvent }
  | { type: 'cycle.start'; data: CycleStartEvent }
  | { type: 'timing_gate.result'; data: TimingGateResultEvent }
  | { type: 'planner.request'; data: PlannerRequestEvent }
  | { type: 'planner.response'; data: PlannerResponseEvent }
  | { type: 'planner.finalized'; data: PlannerFinalizedEvent }
  | { type: 'tool.execution'; data: ToolExecutionEvent }
  | { type: 'cycle.end'; data: CycleEndEvent }
  | { type: 'replier.request'; data: ReplierRequestEvent }
  | { type: 'replier.response'; data: ReplierResponseEvent }

export type MaisakaEventListener = (event: MaisakaMonitorEvent) => void

// ─── 客户端 ───────────────────────────────────────────────────

class MaisakaMonitorClient {
  private initialized = false
  private listenerIdCounter = 0
  private listeners: Map<number, MaisakaEventListener> = new Map()
  private subscriptionActive = false
  private subscriptionPromise: Promise<void> | null = null
  private deferredUnsubTimer: ReturnType<typeof setTimeout> | null = null

  private initialize(): void {
    if (this.initialized) {
      return
    }

    unifiedWsClient.addEventListener((message: WsEventEnvelope) => {
      if (message.domain !== 'maisaka_monitor') {
        return
      }

      const event: MaisakaMonitorEvent = {
        type: message.event as MaisakaMonitorEvent['type'],
        data: message.data as never,
      }

      this.listeners.forEach((listener) => {
        try {
          listener(event)
        } catch (error) {
          console.error('MaiSaka 监控事件监听器执行失败:', error)
        }
      })
    })

    this.initialized = true
  }

  private async ensureSubscribed(): Promise<void> {
    if (this.subscriptionActive) {
      return
    }

    if (this.subscriptionPromise === null) {
      this.subscriptionPromise = unifiedWsClient
        .subscribe('maisaka_monitor', 'main')
        .then(() => {
          this.subscriptionActive = true
        })
        .finally(() => {
          this.subscriptionPromise = null
        })
    }

    await this.subscriptionPromise
  }

  async subscribe(listener: MaisakaEventListener): Promise<() => Promise<void>> {
    this.initialize()
    const listenerId = ++this.listenerIdCounter
    this.listeners.set(listenerId, listener)

    // 如果有待执行的延迟退订，取消它（React StrictMode 快速卸载/重新挂载）
    if (this.deferredUnsubTimer !== null) {
      clearTimeout(this.deferredUnsubTimer)
      this.deferredUnsubTimer = null
    }

    await this.ensureSubscribed()

    return async () => {
      this.listeners.delete(listenerId)
      if (this.listeners.size === 0 && this.subscriptionActive) {
        // 延迟退订：等待短暂时间再真正退订，避免 StrictMode 导致的竞态
        this.deferredUnsubTimer = setTimeout(() => {
          this.deferredUnsubTimer = null
          if (this.listeners.size === 0 && this.subscriptionActive) {
            this.subscriptionActive = false
            void unifiedWsClient.unsubscribe('maisaka_monitor', 'main')
          }
        }, 200)
      }
    }
  }
}

export const maisakaMonitorClient = new MaisakaMonitorClient()
