/**
 * 系统事件总线驱动（SharedWorker + WebSocket 降级）
 * 系统事件总线
 */

export interface WSMessage {
  type: string
  timestamp?: number
  payload?: any
}

export type MessageHandler = (msg: WSMessage) => void

class EventBusDriver {
  private wsUrl = ''
  private workerPath = ''
  private handlers = new Set<MessageHandler>()
  private worker: SharedWorker | null = null
  private socket: WebSocket | null = null
  private reconnectTimer: ReturnType<typeof setTimeout> | null = null
  private initialized = false

  constructor() {
    const baseUrl = (window as any).__BASE_URL__ || ''
    const apiVersion = (window as any).__API_VERSION__ || '/api/v1'
    let host = window.location.host
    let protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'

    if (baseUrl.startsWith('http')) {
      try {
        const url = new URL(baseUrl)
        host = url.host
        protocol = url.protocol === 'https:' ? 'wss:' : 'ws:'
      } catch {
        // ignore
      }
    }

    const path = baseUrl.startsWith('http') ? '' : baseUrl
    this.wsUrl = `${protocol}//${host}${path}${apiVersion}/ws/events`
    this.workerPath = `${path}/workers/event-worker.js`.replace(/\/{2,}/g, '/').replace(':/', '://')
    if (!this.workerPath.startsWith('/') && !this.workerPath.startsWith('http')) {
      this.workerPath = `/${this.workerPath}`
    }
  }

  init() {
    if (this.initialized) return
    this.initialized = true
    if (typeof window !== 'undefined' && 'SharedWorker' in window) {
      this.initSharedWorker()
    } else {
      this.initStandardWebSocket()
    }
  }

  private initSharedWorker() {
    try {
      this.worker = new SharedWorker(this.workerPath)
      this.worker.port.postMessage({ type: 'init', data: { url: this.wsUrl } })
      this.worker.port.onmessage = (e) => this.emit(e.data)
      this.worker.port.start()
    } catch {
      this.initStandardWebSocket()
    }
  }

  private initStandardWebSocket() {
    if (this.socket) return
    try {
      this.socket = new WebSocket(this.wsUrl)
      this.socket.onmessage = (e) => {
        try {
          const data = JSON.parse(e.data)
          this.emit(data)
        } catch {
          // ignore
        }
      }
      this.socket.onclose = () => {
        this.socket = null
        this.reconnect()
      }
      this.socket.onerror = () => {
        this.socket = null
        this.reconnect()
      }
    } catch {
      this.reconnect()
    }
  }

  private reconnect() {
    if (this.reconnectTimer) clearTimeout(this.reconnectTimer)
    this.reconnectTimer = setTimeout(() => {
      this.initialized = false
      this.init()
    }, 5000)
  }

  private emit(msg: WSMessage) {
    if (!msg || !msg.type) return
    this.handlers.forEach((handler) => {
      try {
        handler(msg)
      } catch {
        // ignore handler errors
      }
    })
  }

  subscribe(handler: MessageHandler) {
    this.handlers.add(handler)
    return () => {
      this.handlers.delete(handler)
    }
  }
}

export const eventBus = new EventBusDriver()
