import { loadBackendAuthTokens, loadBackendBaseUrl } from '../../utils/backendAuth'
import { getEventPlay, launchEvent, type BackendCourseVariantSummary, type BackendEventPlayResult } from '../../utils/backendApi'
import { adaptBackendLaunchResultToEnvelope } from '../../utils/backendLaunchAdapter'
import { formatBackendPlayActionText, formatBackendPlayStatusText } from '../../utils/backendPlayCopy'
import { prepareMapPageUrlForLaunch } from '../../utils/gameLaunch'
import { HeartRateController } from '../../engine/sensor/heartRateController'

const PREFERRED_HEART_RATE_DEVICE_STORAGE_KEY = 'cmr.preferredHeartRateDevice'
const DEBUG_MOCK_CHANNEL_ID_STORAGE_KEY = 'cmr.debug.mockChannelId.v1'
const DEBUG_MOCK_AUTO_CONNECT_STORAGE_KEY = 'cmr.debug.autoConnectMockSources.v1'

type EventPreparePageData = {
  eventId: string
  loading: boolean
  titleText: string
  summaryText: string
  releaseText: string
  actionText: string
  statusText: string
  assignmentMode: string
  variantModeText: string
  variantSummaryText: string
  presentationText: string
  contentBundleText: string
  runtimePlaceText: string
  runtimeMapText: string
  runtimeVariantText: string
  runtimeRouteCodeText: string
  selectedVariantId: string
  selectedVariantText: string
  selectableVariants: Array<{
    id: string
    name: string
    routeCodeText: string
    descriptionText: string
    selected: boolean
  }>
  locationStatusText: string
  heartRateStatusText: string
  heartRateDeviceText: string
  heartRateScanText: string
  heartRateConnected: boolean
  showHeartRateDevicePicker: boolean
  locationPermissionGranted: boolean
  locationBackgroundPermissionGranted: boolean
  heartRateDiscoveredDevices: Array<{
    deviceId: string
    name: string
    rssiText: string
    preferred: boolean
    connected: boolean
  }>
  mockSourceStatusText: string
}

function formatAssignmentMode(mode?: string | null): string {
  if (mode === 'manual') {
    return '手动选择'
  }
  if (mode === 'random') {
    return '随机分配'
  }
  if (mode === 'server-assigned') {
    return '后台指定'
  }
  return '默认单赛道'
}

function formatVariantSummary(result: BackendEventPlayResult): string {
  const variants = result.play.courseVariants || []
  if (!variants.length) {
    return '当前未声明额外赛道版本，启动时按默认赛道进入。'
  }

  const preview = variants.map((item) => {
    const title = item.routeCode || item.name
    return item.selectable === false ? `${title}(固定)` : title
  }).join(' / ')

  if (result.play.assignmentMode === 'manual') {
    return `当前活动支持 ${variants.length} 条赛道。本阶段前端先展示赛道信息，最终绑定以后端 launch 返回为准：${preview}`
  }

  if (result.play.assignmentMode === 'random') {
    return `当前活动支持 ${variants.length} 条赛道，进入地图前由后端随机绑定：${preview}`
  }

  if (result.play.assignmentMode === 'server-assigned') {
    return `当前活动赛道由后台预先指定：${preview}`
  }

  return preview
}

function formatPresentationSummary(result: BackendEventPlayResult): string {
  const currentPresentation = result.currentPresentation
  if (!currentPresentation) {
    return '当前未声明展示版本'
  }

  return `${currentPresentation.presentationId || '--'} / ${currentPresentation.templateKey || '--'} / ${currentPresentation.version || '--'}`
}

function formatContentBundleSummary(result: BackendEventPlayResult): string {
  const currentContentBundle = result.currentContentBundle
  if (!currentContentBundle) {
    return '当前未声明内容包版本'
  }

  return `${currentContentBundle.bundleId || '--'} / ${currentContentBundle.bundleType || '--'} / ${currentContentBundle.version || '--'}`
}

function resolveSelectedVariantId(
  currentVariantId: string,
  assignmentMode?: string | null,
  variants?: BackendCourseVariantSummary[] | null,
): string {
  if (assignmentMode !== 'manual' || !variants || !variants.length) {
    return ''
  }

  const selectable = variants.filter((item) => item.selectable !== false)
  if (!selectable.length) {
    return ''
  }

  const currentStillExists = selectable.some((item) => item.id === currentVariantId)
  if (currentVariantId && currentStillExists) {
    return currentVariantId
  }

  return selectable[0].id
}

function buildSelectableVariants(
  selectedVariantId: string,
  assignmentMode?: string | null,
  variants?: BackendCourseVariantSummary[] | null,
) {
  if (assignmentMode !== 'manual' || !variants || !variants.length) {
    return []
  }

  return variants
    .filter((item) => item.selectable !== false)
    .map((item) => ({
      id: item.id,
      name: item.name,
      routeCodeText: item.routeCode || '默认编码',
      descriptionText: item.description || '暂无赛道说明',
      selected: item.id === selectedVariantId,
    }))
}

let prepareHeartRateController: HeartRateController | null = null

function getAccessToken(): string | null {
  const app = getApp<IAppOption>()
  const tokens = app.globalData && app.globalData.backendAuthTokens
    ? app.globalData.backendAuthTokens
    : loadBackendAuthTokens()
  return tokens && tokens.accessToken ? tokens.accessToken : null
}

function loadPreferredHeartRateDeviceName(): string | null {
  try {
    const stored = wx.getStorageSync(PREFERRED_HEART_RATE_DEVICE_STORAGE_KEY)
    if (!stored || typeof stored !== 'object') {
      return null
    }
    const normalized = stored as { name?: unknown }
    return typeof normalized.name === 'string' && normalized.name.trim().length > 0
      ? normalized.name.trim()
      : '心率带'
  } catch (_error) {
    return null
  }
}

function loadStoredMockChannelId(): string {
  try {
    const stored = wx.getStorageSync(DEBUG_MOCK_CHANNEL_ID_STORAGE_KEY)
    if (typeof stored === 'string' && stored.trim().length > 0) {
      return stored.trim()
    }
  } catch (_error) {
    return 'default'
  }
  return 'default'
}

function loadMockAutoConnectEnabled(): boolean {
  try {
    return wx.getStorageSync(DEBUG_MOCK_AUTO_CONNECT_STORAGE_KEY) === true
  } catch (_error) {
    return false
  }
}

Page({
  data: {
    eventId: '',
    loading: false,
    titleText: '开始前准备',
    summaryText: '未加载',
    releaseText: '--',
    actionText: '--',
    statusText: '待加载',
    assignmentMode: '',
    variantModeText: '--',
    variantSummaryText: '--',
    presentationText: '--',
    contentBundleText: '--',
    runtimePlaceText: '待 launch 确认',
    runtimeMapText: '待 launch 确认',
    runtimeVariantText: '待 launch 确认',
    runtimeRouteCodeText: '待 launch 确认',
    selectedVariantId: '',
    selectedVariantText: '当前无需手动指定赛道',
    selectableVariants: [],
    locationStatusText: '待进入地图后校验定位权限与实时精度',
    heartRateStatusText: '局前心率带连接入口待接入，本轮先保留骨架',
    heartRateDeviceText: '--',
    heartRateScanText: '未扫描',
    heartRateConnected: false,
    showHeartRateDevicePicker: false,
    locationPermissionGranted: false,
    locationBackgroundPermissionGranted: false,
    heartRateDiscoveredDevices: [],
    mockSourceStatusText: '模拟源调试仍在地图页调试面板中使用',
  } as EventPreparePageData,

  onLoad(query: { eventId?: string }) {
    const eventId = query && query.eventId ? decodeURIComponent(query.eventId) : ''
    if (!eventId) {
      this.setData({
        statusText: '缺少 eventId',
      })
      return
    }
    this.setData({ eventId })
    this.ensurePrepareHeartRateController()
    this.refreshPreparationDeviceState()
    this.loadEventPlay(eventId)
  },

  onShow() {
    this.refreshPreparationDeviceState()
  },

  onUnload() {
    if (prepareHeartRateController) {
      prepareHeartRateController.destroy()
      prepareHeartRateController = null
    }
  },

  async loadEventPlay(eventId?: string) {
    const targetEventId = eventId || this.data.eventId
    const accessToken = getAccessToken()
    if (!accessToken) {
      wx.redirectTo({ url: '/pages/login/login' })
      return
    }

    this.setData({
      loading: true,
      statusText: '正在加载局前准备信息',
    })

    try {
      const result = await getEventPlay({
        baseUrl: loadBackendBaseUrl(),
        eventId: targetEventId,
        accessToken,
      })
      this.applyEventPlay(result)
    } catch (error) {
      const message = error && (error as { message?: string }).message ? (error as { message: string }).message : '未知错误'
      this.setData({
        loading: false,
        statusText: `局前准备加载失败：${message}`,
      })
    }
  },

  applyEventPlay(result: BackendEventPlayResult) {
    const selectedVariantId = resolveSelectedVariantId(
      this.data.selectedVariantId,
      result.play.assignmentMode,
      result.play.courseVariants,
    )
    const selectableVariants = buildSelectableVariants(
      selectedVariantId,
      result.play.assignmentMode,
      result.play.courseVariants,
    )
    const selectedVariant = selectableVariants.find((item) => item.id === selectedVariantId) || null
    this.setData({
      loading: false,
      titleText: `${result.event.displayName} / 开始前准备`,
      summaryText: result.event.summary || '暂无活动简介',
      releaseText: result.resolvedRelease
        ? `${result.resolvedRelease.configLabel} / ${result.resolvedRelease.releaseId}`
        : '当前无可用 release',
      actionText: formatBackendPlayActionText(result.play.primaryAction, result.play.reason),
      statusText: formatBackendPlayStatusText(result.play.canLaunch, result.play.primaryAction, result.play.reason),
      assignmentMode: result.play.assignmentMode || '',
      variantModeText: formatAssignmentMode(result.play.assignmentMode),
      variantSummaryText: formatVariantSummary(result),
      presentationText: formatPresentationSummary(result),
      contentBundleText: formatContentBundleSummary(result),
      runtimePlaceText: '待 launch.runtime 确认',
      runtimeMapText: '待 launch.runtime 确认',
      runtimeVariantText: selectedVariant
        ? selectedVariant.name
        : (result.play.courseVariants && result.play.courseVariants[0]
          ? result.play.courseVariants[0].name
          : '待 launch 确认'),
      runtimeRouteCodeText: selectedVariant
        ? selectedVariant.routeCodeText
        : (result.play.courseVariants && result.play.courseVariants[0] && result.play.courseVariants[0].routeCode
          ? result.play.courseVariants[0].routeCode || '待 launch 确认'
          : '待 launch 确认'),
      selectedVariantId,
      selectedVariantText: selectedVariant
        ? `${selectedVariant.name} / ${selectedVariant.routeCodeText}`
        : '当前无需手动指定赛道',
      selectableVariants,
    })
  },

  refreshPreparationDeviceState() {
    this.refreshLocationPermissionStatus()
    this.refreshHeartRatePreparationStatus()
    this.refreshMockSourcePreparationStatus()
  },

  ensurePrepareHeartRateController() {
    if (prepareHeartRateController) {
      return prepareHeartRateController
    }

    prepareHeartRateController = new HeartRateController({
      onHeartRate: () => {},
      onStatus: (message) => {
        this.setData({
          heartRateStatusText: message,
        })
      },
      onError: (message) => {
        this.setData({
          heartRateStatusText: message,
        })
      },
      onConnectionChange: (connected, deviceName) => {
        this.setData({
          heartRateConnected: connected,
          heartRateDeviceText: connected ? (deviceName || '心率带') : (deviceName || '--'),
        })
        this.refreshHeartRatePreparationStatus()
      },
      onDeviceListChange: (devices) => {
        this.setData({
          heartRateScanText: devices.length ? `已发现 ${devices.length} 个设备` : '未扫描',
          heartRateDiscoveredDevices: devices.map((device) => ({
            deviceId: device.deviceId,
            name: device.name,
            rssiText: typeof device.rssi === 'number' ? `${device.rssi} dBm` : 'RSSI --',
            preferred: !!device.isPreferred,
            connected: !!prepareHeartRateController
              && !!prepareHeartRateController.currentDeviceId
              && prepareHeartRateController.currentDeviceId === device.deviceId
              && prepareHeartRateController.connected,
          })),
        })
      },
    })

    return prepareHeartRateController
  },

  refreshLocationPermissionStatus() {
    wx.getSetting({
      success: (result) => {
        const authSetting = result && result.authSetting
          ? result.authSetting as Record<string, boolean | undefined>
          : {}
        const hasForeground = authSetting['scope.userLocation'] === true
        const hasBackground = authSetting['scope.userLocationBackground'] === true
        let locationStatusText = '未请求定位权限'
        if (hasForeground && hasBackground) {
          locationStatusText = '已授权前后台定位'
        } else if (hasForeground) {
          locationStatusText = '已授权前台定位'
        } else if (authSetting['scope.userLocation'] === false) {
          locationStatusText = '定位权限被拒绝'
        }
        this.setData({
          locationStatusText,
          locationPermissionGranted: hasForeground,
          locationBackgroundPermissionGranted: hasBackground,
        })
      },
      fail: () => {
        this.setData({
          locationStatusText: '无法读取定位权限状态',
          locationPermissionGranted: false,
          locationBackgroundPermissionGranted: false,
        })
      },
    })
  },

  handleRequestLocationPermission() {
    wx.authorize({
      scope: 'scope.userLocation',
      success: () => {
        this.refreshLocationPermissionStatus()
        wx.showToast({
          title: '前台定位已授权',
          icon: 'none',
        })
      },
      fail: () => {
        this.refreshLocationPermissionStatus()
        wx.showToast({
          title: '请在设置中开启定位权限',
          icon: 'none',
        })
      },
    })
  },

  handleOpenLocationSettings() {
    wx.openSetting({
      success: () => {
        this.refreshLocationPermissionStatus()
      },
      fail: () => {
        wx.showToast({
          title: '无法打开设置面板',
          icon: 'none',
        })
      },
    })
  },

  refreshHeartRatePreparationStatus() {
    const controller = this.ensurePrepareHeartRateController()
    const preferredDeviceName = loadPreferredHeartRateDeviceName()
    this.setData({
      heartRateStatusText: controller.connected
        ? '局前心率带已连接'
        : preferredDeviceName
          ? `已记住首选设备：${preferredDeviceName}`
          : '未设置首选设备，可在此连接或进入地图后连接',
      heartRateDeviceText: controller.currentDeviceName || preferredDeviceName || '--',
      heartRateScanText: controller.scanning
        ? '扫描中'
        : (controller.discoveredDevices.length ? `已发现 ${controller.discoveredDevices.length} 个设备` : '未扫描'),
      heartRateConnected: controller.connected,
      heartRateDiscoveredDevices: controller.discoveredDevices.map((device) => ({
        deviceId: device.deviceId,
        name: device.name,
        rssiText: typeof device.rssi === 'number' ? `${device.rssi} dBm` : 'RSSI --',
        preferred: !!device.isPreferred,
        connected: !!controller.currentDeviceId && controller.currentDeviceId === device.deviceId && controller.connected,
      })),
    })
  },

  refreshMockSourcePreparationStatus() {
    const channelId = loadStoredMockChannelId()
    const autoConnect = loadMockAutoConnectEnabled()
    this.setData({
      mockSourceStatusText: autoConnect
        ? `自动连接已开启 / 通道 ${channelId}`
        : `自动连接未开启 / 通道 ${channelId}`,
    })
  },

  handleRefresh() {
    this.loadEventPlay()
  },

  handleBack() {
    wx.navigateBack()
  },

  handlePrepareHeartRateConnect() {
    const controller = this.ensurePrepareHeartRateController()
    controller.startScanAndConnect()
    this.refreshHeartRatePreparationStatus()
  },

  handleOpenHeartRateDevicePicker() {
    const controller = this.ensurePrepareHeartRateController()
    this.setData({
      showHeartRateDevicePicker: true,
    })
    if (!controller.scanning) {
      controller.startScanAndConnect()
    }
    this.refreshHeartRatePreparationStatus()
  },

  handleCloseHeartRateDevicePicker() {
    this.setData({
      showHeartRateDevicePicker: false,
    })
  },

  handlePrepareHeartRateDeviceConnect(event: WechatMiniprogram.BaseEvent<{ deviceId?: string }>) {
    const deviceId = event.currentTarget.dataset.deviceId
    if (!deviceId) {
      return
    }
    const controller = this.ensurePrepareHeartRateController()
    controller.connectToDiscoveredDevice(deviceId)
    this.setData({
      showHeartRateDevicePicker: false,
    })
    this.refreshHeartRatePreparationStatus()
  },

  handlePrepareHeartRateDisconnect() {
    if (!prepareHeartRateController) {
      return
    }
    prepareHeartRateController.disconnect()
    this.setData({
      heartRateConnected: false,
    })
    this.refreshHeartRatePreparationStatus()
  },

  handlePrepareHeartRateClearPreferred() {
    const controller = this.ensurePrepareHeartRateController()
    controller.clearPreferredDevice()
    this.refreshHeartRatePreparationStatus()
  },

  handleSelectVariant(event: WechatMiniprogram.BaseEvent<{ variantId?: string }>) {
    const variantId = event.currentTarget.dataset.variantId
    if (!variantId) {
      return
    }

    const selectableVariants = this.data.selectableVariants.map((item) => ({
      ...item,
      selected: item.id === variantId,
    }))
    const selectedVariant = selectableVariants.find((item) => item.id === variantId) || null
    this.setData({
      selectedVariantId: variantId,
      selectedVariantText: selectedVariant
        ? `${selectedVariant.name} / ${selectedVariant.routeCodeText}`
        : '当前无需手动指定赛道',
      runtimeVariantText: selectedVariant ? selectedVariant.name : '待 launch 确认',
      runtimeRouteCodeText: selectedVariant ? selectedVariant.routeCodeText : '待 launch 确认',
      selectableVariants,
    })
  },

  async handleLaunch() {
    const accessToken = getAccessToken()
    if (!accessToken) {
      wx.redirectTo({ url: '/pages/login/login' })
      return
    }

    if (!this.data.locationPermissionGranted) {
      this.setData({
        statusText: '进入地图前请先完成定位授权',
      })
      wx.showToast({
        title: '请先授权定位',
        icon: 'none',
      })
      return
    }

    this.setData({
      statusText: '正在创建 session 并进入地图',
    })

    try {
      const app = getApp<IAppOption>()
      if (app.globalData) {
        const pendingDeviceName = prepareHeartRateController && prepareHeartRateController.currentDeviceName
          ? prepareHeartRateController.currentDeviceName
          : loadPreferredHeartRateDeviceName()
        app.globalData.pendingHeartRateAutoConnect = {
          enabled: !!pendingDeviceName,
          deviceName: pendingDeviceName || null,
        }
      }
      if (prepareHeartRateController) {
        prepareHeartRateController.destroy()
        prepareHeartRateController = null
      }
      const result = await launchEvent({
        baseUrl: loadBackendBaseUrl(),
        eventId: this.data.eventId,
        accessToken,
        variantId: this.data.assignmentMode === 'manual' ? this.data.selectedVariantId : undefined,
        clientType: 'wechat',
        deviceKey: 'mini-dev-device-001',
      })
      const envelope = adaptBackendLaunchResultToEnvelope(result)
      wx.navigateTo({
        url: prepareMapPageUrlForLaunch(envelope),
      })
    } catch (error) {
      const message = error && (error as { message?: string }).message ? (error as { message: string }).message : '未知错误'
      this.setData({
        statusText: `launch 失败：${message}`,
      })
    }
  },
})
