import { loadBackendBaseUrl } from './backendAuth'
import { postClientLog, type BackendClientLogInput } from './backendApi'

type ClientLogLevel = BackendClientLogInput['level']

type ClientLogEntry = {
  level: ClientLogLevel
  category: string
  message: string
  eventId?: string
  releaseId?: string
  sessionId?: string
  manifestUrl?: string
  route?: string
  details?: Record<string, unknown>
}

const CLIENT_LOG_SOURCE = 'wechat-mini'
const MAX_PENDING_CLIENT_LOGS = 100

const pendingClientLogs: BackendClientLogInput[] = []
let clientLogFlushInProgress = false
let clientLogSequence = 0

function getCurrentRoute(): string {
  const pages = getCurrentPages()
  if (!pages.length) {
    return ''
  }
  const current = pages[pages.length - 1]
  return current && current.route ? current.route : ''
}

function enqueueClientLog(payload: BackendClientLogInput) {
  pendingClientLogs.push(payload)
  if (pendingClientLogs.length > MAX_PENDING_CLIENT_LOGS) {
    pendingClientLogs.shift()
  }
}

function flushNextClientLog() {
  if (clientLogFlushInProgress || !pendingClientLogs.length) {
    return
  }

  const baseUrl = loadBackendBaseUrl()
  if (!baseUrl) {
    pendingClientLogs.length = 0
    return
  }

  const payload = pendingClientLogs.shift()
  if (!payload) {
    return
  }

  clientLogFlushInProgress = true
  postClientLog({
    baseUrl,
    payload,
  }).catch(() => {
    // 联调日志不打断主流程，失败时静默丢弃。
  }).finally(() => {
    clientLogFlushInProgress = false
    if (pendingClientLogs.length) {
      flushNextClientLog()
    }
  })
}

export function reportBackendClientLog(entry: ClientLogEntry) {
  clientLogSequence += 1
  const details = entry.details ? { ...entry.details } : {}
  details.seq = clientLogSequence
  const payload: BackendClientLogInput = {
    source: CLIENT_LOG_SOURCE,
    level: entry.level,
    category: entry.category,
    message: entry.message,
    eventId: entry.eventId || '',
    releaseId: entry.releaseId || '',
    sessionId: entry.sessionId || '',
    manifestUrl: entry.manifestUrl || '',
    route: entry.route || getCurrentRoute(),
    occurredAt: new Date().toISOString(),
    details,
  }
  enqueueClientLog(payload)
  flushNextClientLog()
}
