<template>
  <GuidePageFrame
    active-tab="explain"
    variant="static"
    :show-top-tabs="false"
    show-bottom-nav
    show-back
    back-label="讲解首页"
    @tab-change="handleTopTabChange"
    @back="handleBack"
  >
    <view class="explain-all-page">
      <ExplainList
        :cards="explainExhibits"
        :loading="explainLoading"
        :error="explainError"
        list-title="全部讲解"
        page-mode="all"
        :initial-render-limit="48"
        :page-size="48"
        @exhibit-click="handleExplainExhibitClick"
        @featured-click="handleExplainFeaturedClick"
        @audio-click="handleAudioClick"
        @location-click="handleExplainLocationClick"
        @hall-click="handleExplainHallClick"
      />

      <AudioPlayer
        ref="audioPlayerRef"
        :visible="showAudioPlayer"
        :audio="currentAudio"
        :auto-play="false"
        avoid-bottom-nav
        @update:visible="handleAudioVisibleChange"
        @play="handleAudioPlay"
        @pause="handleAudioPause"
        @ended="handleAudioEnded"
        @error="handleAudioError"
      />
    </view>
  </GuidePageFrame>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import GuidePageFrame from '@/components/navigation/GuidePageFrame.vue'
import ExplainList, { type Exhibit } from '@/components/explain/ExplainList.vue'
import AudioPlayer, { type AudioItem } from '@/components/audio/AudioPlayer.vue'
import {
  explainUseCase
} from '@/usecases/explainUseCase'
import {
  guideUseCase
} from '@/usecases/guideUseCase'
import {
  toExplainCardViewModel
} from '@/view-models/explainViewModels'
import {
  navigateToGuideTopTab,
  type GuideTopTab
} from '@/utils/guideTopTabs'

const explainExhibits = ref<Exhibit[]>([])
const explainLoading = ref(false)
const explainError = ref('')
const showAudioPlayer = ref(false)
const isAudioPlaying = ref(false)
const currentAudio = ref<AudioItem | null>(null)
const audioPlayerRef = ref<AudioPlayerExpose | null>(null)
let explainLoadPromise: Promise<void> | null = null

interface AudioPlayerExpose {
  play: (audio: AudioItem) => void
  pause: () => void
}

const loadExplainExhibits = async () => {
  if (explainExhibits.value.length) return
  if (explainLoadPromise) return explainLoadPromise

  explainLoading.value = true
  explainError.value = ''

  explainLoadPromise = (async () => {
    try {
      const exhibits = await explainUseCase.listExplainExhibits()
      explainExhibits.value = exhibits.map(toExplainCardViewModel)
    } catch (error) {
      console.error('加载全部讲解内容失败:', error)
      explainError.value = '讲解内容加载失败，请稍后重试'
      explainExhibits.value = []
    } finally {
      explainLoading.value = false
      explainLoadPromise = null
    }
  })()

  return explainLoadPromise
}

onLoad(() => {
  void loadExplainExhibits()
})

const handleBack = () => {
  uni.navigateBack({
    delta: 1,
    fail: () => {
      uni.reLaunch({
        url: '/pages/index/index?tab=explain'
      })
    }
  })
}

const handleTopTabChange = (tab: GuideTopTab) => {
  navigateToGuideTopTab(tab)
}

const handleExplainExhibitClick = (exhibit: Exhibit) => {
  uni.navigateTo({
    url: `/pages/exhibit/detail?id=${exhibit.id}&tab=explain`
  })
}

const handleExplainFeaturedClick = async (exhibit: Exhibit) => {
  await handleAudioClick(exhibit)
}

const handleExplainHallClick = (hallId: string) => {
  uni.navigateTo({
    url: `/pages/hall/detail?id=${encodeURIComponent(hallId)}&tab=explain`
  })
}

const handleAudioClick = async (exhibit: Exhibit) => {
  if (exhibit.audioUrl) {
    const audio: AudioItem = {
      id: `media-${exhibit.id}`,
      name: exhibit.title,
      audioUrl: exhibit.audioUrl,
      image: exhibit.coverImage,
      duration: exhibit.audioDuration
    }

    const isSameAudio = currentAudio.value?.id === audio.id
    if (showAudioPlayer.value && isSameAudio && isAudioPlaying.value) {
      audioPlayerRef.value?.pause()
      return
    }

    currentAudio.value = audio
    showAudioPlayer.value = true
    audioPlayerRef.value?.play(audio)
    return
  }

  const selection = await explainUseCase.selectAudioForExhibit(exhibit.id)

  if (!selection?.playable || !selection.media?.url) {
    uni.showToast({
      title: selection?.unavailableMessage || exhibit.audioStatusText || '该讲解暂无可播放音频',
      icon: 'none'
    })
    return
  }

  currentAudio.value = {
    id: selection.media.id,
    name: selection.track?.title || selection.exhibit.name,
    audioUrl: selection.media.url,
    image: selection.exhibit.image,
    duration: selection.media.duration
  }
  showAudioPlayer.value = true
  uni.showToast({
    title: '音频已准备好，请点击底部播放按钮',
    icon: 'none'
  })
}

const clearAudioState = () => {
  showAudioPlayer.value = false
  isAudioPlaying.value = false
  currentAudio.value = null
}

const handleAudioVisibleChange = (visible: boolean) => {
  showAudioPlayer.value = visible
  if (!visible) {
    isAudioPlaying.value = false
    currentAudio.value = null
  }
}

const handleAudioPlay = () => {
  isAudioPlaying.value = true
}

const handleAudioPause = () => {
  isAudioPlaying.value = false
}

const handleAudioEnded = () => {
  clearAudioState()
}

const handleAudioError = (_audio: AudioItem | null, message: string) => {
  console.warn('全部讲解音频不可播放:', message)
  clearAudioState()
}

const handleExplainLocationClick = async (exhibit: Exhibit) => {
  if (!exhibit.poiId) {
    uni.showToast({
      title: '该讲解暂无三维位置数据',
      icon: 'none'
    })
    return
  }

  const matchedPoi = await guideUseCase.getPoiById(exhibit.poiId)
  if (!matchedPoi) {
    uni.showToast({
      title: '该讲解位置尚未映射到当前三维导览资源',
      icon: 'none'
    })
    return
  }

  uni.navigateTo({
    url: `/pages/route/detail?facilityId=${encodeURIComponent(exhibit.poiId)}&target=${encodeURIComponent(exhibit.title)}&state=preview`
  })
}
</script>

<style scoped lang="scss">
.explain-all-page {
  position: absolute;
  inset: 0;
  background: #edf0ea;
}
</style>
