import { ElMessage } from 'element-plus'
import { ImClient, type ImMessage, init as initSdk } from '@xuqm/vue3-sdk'
import client from '@/api/client'

// Initialize the SDK global so ImClient.sendSync() can send the /app/chat.sync frame.
// Only appKey is required; no secret is exposed here.
initSdk({ appKey: 'ak_409e217e4aa14254ad73ad3c' })

export interface StoreReviewRefreshEvent {
  event: string
  appKey: string
  versionId?: string
  storeType?: string
  reviewState?: string
  reviewReason?: string
  stage?: string
  batchId?: string
  publishStatus?: string
  source?: string
  timestamp?: number
}

export interface ServiceActivationRefreshEvent {
  event: string
  appKey: string
  serviceType: string
  status: string
  reviewNote: string
  timestamp?: number
}

interface PlatformEventTokenResponse {
  userId: string
  token: string
}

// Single shared connection — all platform event types go through one WebSocket.
let imClient: ImClient | null = null
let activeAppKey = ''
let storeReviewHandler: ((event: StoreReviewRefreshEvent) => void) | null = null
let serviceActivationHandler: ((event: ServiceActivationRefreshEvent) => void) | null = null
// Tracks when a message was last received over the IM WebSocket (any type).
// Used by callers to decide whether IM is healthy enough to skip HTTP polling.
let lastImMessageAt = 0

function sdkWsUrl() {
  return import.meta.env.VITE_IM_WS_URL ?? ''
}

function parseAnyEvent(message: ImMessage): StoreReviewRefreshEvent | ServiceActivationRefreshEvent | null {
  try {
    const raw = JSON.parse(message.content) as Record<string, unknown>
    const payload = (raw?.payload && typeof raw.payload === 'object' ? raw.payload : raw) as Record<string, unknown>
    const event = String(payload.event ?? raw?.event ?? '')
    const appKey = String(payload.appKey ?? raw?.appKey ?? '')
    if (!appKey) return null

    if (event === 'store_review_update') {
      return {
        event,
        appKey,
        versionId: String(payload.versionId ?? raw?.versionId ?? ''),
        storeType: String(payload.storeType ?? raw?.storeType ?? ''),
        reviewState: String(payload.reviewState ?? raw?.reviewState ?? ''),
        reviewReason: String(payload.reviewReason ?? raw?.reviewReason ?? ''),
        stage: String(payload.stage ?? raw?.stage ?? ''),
        batchId: String(payload.batchId ?? raw?.batchId ?? ''),
        publishStatus: String(payload.publishStatus ?? raw?.publishStatus ?? ''),
        source: String(payload.source ?? raw?.source ?? ''),
        timestamp: Number(payload.timestamp ?? raw?.timestamp ?? Date.now()),
      }
    }

    if (event === 'service_activation_update') {
      return {
        event,
        appKey,
        serviceType: String(payload.serviceType ?? raw?.serviceType ?? ''),
        status: String(payload.status ?? raw?.status ?? ''),
        reviewNote: String(payload.reviewNote ?? raw?.reviewNote ?? ''),
        timestamp: Number(payload.timestamp ?? raw?.timestamp ?? Date.now()),
      }
    }

    return null
  } catch {
    return null
  }
}

function disconnectAll() {
  if (imClient) {
    imClient.disconnect()
    imClient = null
  }
  activeAppKey = ''
}

async function ensureConnection(appKey: string) {
  if (imClient && activeAppKey === appKey) return
  disconnectAll()
  activeAppKey = appKey

  const res = await client.get<{ data: PlatformEventTokenResponse }>('/im/platform-events/token', {
    params: { appKey },
  })
  const tokenData = res.data.data ?? (res.data as unknown as PlatformEventTokenResponse)
  const platformToken = tokenData.token

  if (import.meta.env.DEV) {
    console.debug('[tenant-platform][IM] platform event connection established', {
      appKey,
      userId: tokenData.userId,
    })
  }

  const wsUrl = sdkWsUrl() || undefined
  const clientInstance = new ImClient({ tokenSupplier: () => platformToken, wsUrl })
  clientInstance.on('message', (message) => {
    lastImMessageAt = Date.now()
    const event = parseAnyEvent(message)
    if (!event || event.appKey !== activeAppKey) return
    if (event.event === 'store_review_update' && storeReviewHandler) {
      storeReviewHandler(event as StoreReviewRefreshEvent)
    } else if (event.event === 'service_activation_update' && serviceActivationHandler) {
      serviceActivationHandler(event as ServiceActivationRefreshEvent)
    }
  })
  clientInstance.on('error', (error) => {
    if (import.meta.env.DEV) {
      console.warn('[tenant-platform][IM] platform event error', error)
    }
  })
  clientInstance.connect()
  imClient = clientInstance
}

/**
 * Returns true if the IM WebSocket received a message within the last 90 seconds,
 * meaning the connection is healthy and polling can be skipped.
 */
export function isStoreReviewRealtimeConnected(): boolean {
  return imClient !== null && Date.now() - lastImMessageAt < 90_000
}

export async function connectStoreReviewRealtime(appKey: string, onEvent: (event: StoreReviewRefreshEvent) => void) {
  if (!appKey) return
  storeReviewHandler = onEvent
  await ensureConnection(appKey)
}

export function disconnectStoreReviewRealtime() {
  storeReviewHandler = null
  if (!serviceActivationHandler) disconnectAll()
}

export function notifyStoreReviewRefresh(appKey: string) {
  if (appKey && appKey === activeAppKey) {
    ElMessage.info('检测到审核状态更新，正在刷新...')
  }
}

export async function connectServiceActivationRealtime(
  appKey: string,
  onEvent: (event: ServiceActivationRefreshEvent) => void,
) {
  if (!appKey) return
  serviceActivationHandler = onEvent
  await ensureConnection(appKey)
}

export function disconnectServiceActivationRealtime() {
  serviceActivationHandler = null
  if (!storeReviewHandler) disconnectAll()
}
