<template>
  <div class="pptist-student-viewer" :class="{ 'fullscreen': isFullscreen, 'laser-pen': laserPen }">
    <!-- Loading状态显示 -->
    <div v-if="isLoading" class="loading-overlay">
      <div class="loading-content">
        <div class="loading-spinner"></div>
        <div class="loading-text">正在加载课程内容...</div>
      </div>
    </div>
    <!-- 左侧导航栏 -->
    <div class="layout-content-left" v-show="type == '1'">
      <div class="thumbnails">
        <div class="viewer-header">
          <h3>幻灯片导航</h3>
        </div>

        <div class="thumbnail-list">
          <div v-for="(slide, index) in slides" :key="slide.id" class="thumbnail-item"
            :class="{ 'active': slideIndex === index }" @click="goToSlide(index)">
            <div class="label">{{ fillDigit(index + 1, 2) }}</div>
            <ThumbnailSlide class="thumbnail" :slide="slide" :size="168" :visible="true" @click="goToSlide(index)" />
          </div>
        </div>

        <!-- <div class="page-number">幻灯片 {{ slideIndex + 1 }} / {{ slides.length }}</div>
                <div class="progress-bar">
                    <div class="progress-fill" :style="{ width: `${((slideIndex + 1) / slides.length) * 100}%` }"></div>
                </div> -->
      </div>
    </div>

    <!-- 中间放映区域 -->
    <div class="layout-content-center">
      <div class="viewer-header" :class="{ 'hidden': isFullscreen }">
        <div class="slide-title">幻灯片 {{ slideIndex + 1 }}</div>
        <div class="viewer-controls">
          <button @click="previousSlide" :disabled="slideIndex === 0" title="上一页">
            <IconLeftTwo class="control-icon" />
          </button>
          <button @click="nextSlide" :disabled="slideIndex === slides.length - 1" title="下一页">
            <IconRightTwo class="control-icon" />
          </button>
          <!-- <button @click="resetZoom" title="重置缩放">
                        <IconUndo class="control-icon" />
                    </button> -->
          <button @click="enterFullscreen" title="全屏">
            <IconFullScreenOne class="control-icon" />
          </button>
          <!-- <button @click="backToEditor" class="back-btn" title="返回编辑">
                        <IconEdit class="control-icon" />
                    </button> -->
        </div>
      </div>

      <div class="viewer-canvas" ref="viewerCanvasRef">

        <!-- 全屏时：使用放映功能 -->
        <!-- <ScreenSlideList :slideWidth="slideWidth"
                    :slideHeight="slideHeight" :animationIndex="0" :turnSlideToId="() => { }"
                    :manualExitFullscreen="() => { }" /> -->

        <!-- 不全屏时：使用编辑模式的显示比例和居中逻辑 -->
        <div class="slide-list-wrap" :style="{
          width: isFullscreen ? '100%' : (slideWidth * canvasScale) + 'px',
          height: isFullscreen ? '100%' : (slideHeight * canvasScale) + 'px',
          left: isFullscreen ? '0' : `${(containerWidth - slideWidth * canvasScale) / 2}px`,
          top: isFullscreen ? '0' : `${(containerHeight - slideHeight * canvasScale) / 2}px`
        }">
          <div class="viewport" v-if="false">
            <div class="background" :style="backgroundStyle"></div>

            <ScreenElement v-for="(element, index) in elementList" :key="element.id" :elementInfo="element"
              :elementIndex="index + 1" :animationIndex="0" :turnSlideToId="() => { }"
              :manualExitFullscreen="() => { }" />
          </div>

          <ScreenSlideList :slideWidth="slideWidth * canvasScale" :slideHeight="slideHeight * canvasScale"
            :animationIndex="0" :turnSlideToId="() => { }" :manualExitFullscreen="() => { }" />
        </div>
        <!-- 全屏时的左右下角工具按钮 -->
        <div v-if="isFullscreen" class="tools-left">
          <IconLeftTwo class="tool-btn" theme="two-tone" :fill="['#111', '#fff']" @click="previousSlide" />
          <IconRightTwo class="tool-btn" theme="two-tone" :fill="['#111', '#fff']" @click="nextSlide" />
        </div>

        <!-- 作业提交按钮 - 当当前幻灯片包含iframe时显示 -->
        <div v-if="currentSlideHasIframe" class="homework-submit-btn" :class="{ 'submitting': isSubmitting }"
          :style="{ right: getHomeworkButtonRight() + 'px' }" @click="handleHomeworkSubmit"
          v-tooltip="isSubmitting ? '作业提交中...' : '作业提交'">
          <IconEdit v-if="!isSubmitting" class="tool-btn" />
          <div v-else class="loading-spinner"></div>
          <span class="btn-text">{{ isSubmitting ? '提交中...' : '作业提交' }}</span>
        </div>

        <!-- 功能组件 -->
        <SlideThumbnails v-if="slideThumbnailModelVisible" :turnSlideToIndex="goToSlide"
          @close="slideThumbnailModelVisible = false" />

        <WritingBoardTool :slideWidth="slideWidth" :slideHeight="slideHeight" v-if="writingBoardToolVisible"
          @close="writingBoardToolVisible = false" />

        <CountdownTimer v-if="timerlVisible" @close="timerlVisible = false" />

        <div v-if="isFullscreen" class="tools-right" :class="{ 'visible': rightToolsVisible }"
          @mouseleave="rightToolsVisible = false" @mouseenter="rightToolsVisible = true">
          <div class="content">
            <div class="tool-btn page-number" @click="slideThumbnailModelVisible = true">幻灯片 {{ slideIndex +
              1 }} / {{ slides.length }}</div>
            <IconWrite class="tool-btn" v-tooltip="'画笔工具'" @click="writingBoardToolVisible = true" />
            <IconMagic class="tool-btn" v-tooltip="'激光笔'" :class="{ 'active': laserPen }" @click="toggleLaserPen" />
            <IconStopwatchStart class="tool-btn" v-tooltip="'计时器'" @click="timerlVisible = !timerlVisible" />
            <IconOffScreenOne class="tool-btn" v-tooltip="'退出全屏'" @click="enterFullscreen" />
          </div>
        </div>
      </div>
    </div>
    <div class="layout-content-right" v-show="type == '1'" :class="{ collapsed: workPanelCollapsed }">
      <div class="thumbnails">
        <div class="viewer-header homework-header">
          <h3 v-show="!workPanelCollapsed">作业区</h3>
          <button class="collapse-btn" @click="workPanelCollapsed = !workPanelCollapsed" :title="workPanelCollapsed ? '展开' : '收起'">
            <span v-if="workPanelCollapsed">›</span>
            <span v-else>‹</span>
          </button>
        </div>
        <div v-show="!workPanelCollapsed">
          <div class="homework-title">已提交</div>
          <div v-if="workLoading" class="homework-loading">正在加载作业...</div>
          <div v-else>
            <div v-if="workArray && workArray.length" class="homework-grid">
              <button class="homework-btn" v-for="(work, idx) in workArray" :key="work.id ?? idx" :title="work.name" @click="openWorkModal(work)">
                <span class="homework-btn__text">{{ work.name }}</span>
              </button>
            </div>
            <div class="homework-empty" v-else>
              暂无作业提交
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>

  <ShotWorkModal v-model:visible="visibleShot" :work="selectedWork" />
  <QAWorkModal v-model:visible="visibleQA" :work="selectedWork" />
  <ChoiceWorkModal v-model:visible="visibleChoice" :work="selectedWork" />
  <AIWorkModal v-model:visible="visibleAI" :work="selectedWork" />
</template>

<script lang="ts" setup>
import { computed, ref, onMounted, onUnmounted, nextTick, inject, watch } from 'vue'
import { storeToRefs } from 'pinia'
import { useSlidesStore } from '@/store'
import { ElementTypes } from '@/types/slides'
import { fillDigit } from '@/utils/common'
import ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'
import ScreenSlideList from '@/views/Screen/ScreenSlideList.vue'
import ScreenElement from '@/views/Screen/ScreenElement.vue'
import SlideThumbnails from '@/views/Screen/SlideThumbnails.vue'
import WritingBoardTool from '@/views/Screen/WritingBoardTool.vue'
import CountdownTimer from '@/views/Screen/CountdownTimer.vue'
import useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'
import useImport from '@/hooks/useImport'
import message from '@/utils/message'
import api from '@/services/course'
import ShotWorkModal from './components/ShotWorkModal.vue'
import QAWorkModal from './components/QAWorkModal.vue'
import ChoiceWorkModal from './components/ChoiceWorkModal.vue'
import AIWorkModal from './components/AIWorkModal.vue'

// 定义组件props
interface Props {
  courseid?: string | null
  userid?: string | null
  oid?: string | null
  org?: string | null
  cid?: string | null
  type?: string | null
}

const props = withDefaults(defineProps<Props>(), {
  courseid: null,
  userid: null,
  oid: null,
  org: null,
  cid: null,
  type: null,
})

// 图标组件通过全局注册，无需导入

const slidesStore = useSlidesStore()
const { slides, slideIndex, currentSlide, viewportSize, viewportRatio } = storeToRefs(slidesStore)

// 添加容器引用，用于计算幻灯片尺寸
const viewerCanvasRef = ref<HTMLElement>()

// 放映相关的状态
const canvasScale = ref(1) // 画布缩放比例
const isFullscreen = ref(false) // 是否全屏
const containerWidth = ref(0) // 容器宽度
const containerHeight = ref(0) // 容器高度

// 全屏工具相关状态
const rightToolsVisible = ref(false)
const writingBoardToolVisible = ref(false)
const timerlVisible = ref(false)
const slideThumbnailModelVisible = ref(false)
const laserPen = ref(false)

// 作业提交状态
const isSubmitting = ref(false)

// 控制组件显示的开关
const showSlideList = ref(true)
const slideWidth = ref(0)
const slideHeight = ref(0)

// 添加loading状态
const isLoading = ref(false)
const workLoading = ref(false)

// 作业数组
type WorkItem = {
  id?: string | number
  name: string
  type: number | string
  [key: string]: any
}
const workArray = ref<WorkItem[]>([])

// 作业弹窗相关
const selectedWork = ref<any>(null)
const visibleShot = ref(false)
const visibleQA = ref(false)
const visibleChoice = ref(false)
const visibleAI = ref(false)

// 作业区收缩状态
const workPanelCollapsed = ref(false)

// 收缩/展开后重新计算中间画布尺寸（在 DOM 更新并完成过渡后）
watch(() => workPanelCollapsed.value, async () => {
  // 等待本次 DOM 更新
  await nextTick()
  // 先在下一帧计算一次，确保初步布局就绪
  requestAnimationFrame(() => {
    calculateScale()
  })
  // 再在过渡结束后（与右栏 width .2s 过渡一致）复算一次，确保最终尺寸
  setTimeout(() => {
    calculateScale()
  }, 220)
}, { flush: 'post' })

const openWorkModal = (work: WorkItem) => {
  selectedWork.value = work
  const t = Number(work?.type)
  if (t !== 1) {
    message.warning('暂未开发完成')
    return
  }
  visibleShot.value = false
  visibleQA.value = false
  visibleChoice.value = false
  visibleAI.value = false
  if (t === 1) {
    visibleShot.value = true
  }
  else if (t === 3) {
    visibleQA.value = true
  }
  else if (t === 8) {
    visibleChoice.value = true
  }
  else if (t === 20) {
    visibleAI.value = true
  }
  else {
    message.info('暂不支持的作业类型')
  }
}

// 计算幻灯片尺寸的函数
const calculateSlideSize = () => {
  const slideWrapRef = isFullscreen.value ? document.body : viewerCanvasRef.value
  const winWidth = slideWrapRef.clientWidth
  const winHeight = slideWrapRef.clientHeight

  // 根据视口比例计算最佳尺寸
  if (winHeight / winWidth === viewportRatio.value) {
    slideWidth.value = winWidth
    slideHeight.value = winHeight
  }
  else if (winHeight / winWidth > viewportRatio.value) {
    slideWidth.value = winWidth
    slideHeight.value = winWidth * viewportRatio.value
  }
  else {
    slideWidth.value = winHeight / viewportRatio.value
    slideHeight.value = winHeight
  }
}

// 使用编辑模式的缩放逻辑
const calculateScale = () => {
  console.log('calculateScale 开始执行')

  // 计算幻灯片尺寸
  calculateSlideSize()

  // 获取容器尺寸
  const container = viewerCanvasRef.value || document.querySelector('.viewer-canvas')
  if (container) {
    containerWidth.value = container.clientWidth
    containerHeight.value = container.clientHeight

    console.log('容器尺寸:', {
      width: containerWidth.value,
      height: containerHeight.value
    })

    // 计算基础尺寸
    const baseWidth = viewportSize.value
    const baseHeight = viewportSize.value * viewportRatio.value

    console.log('基础尺寸:', {
      baseWidth,
      baseHeight,
      viewportSize: viewportSize.value,
      viewportRatio: viewportRatio.value
    })

    // 计算缩放比例，让幻灯片能够合理利用空间
    const scaleX = containerWidth.value / baseWidth
    const scaleY = containerHeight.value / baseHeight

    console.log('原始缩放比例:', { scaleX, scaleY })

    // 选择较小的缩放比例，确保幻灯片完全显示且居中，留10%边距
    const scale = Math.min(scaleX, scaleY) * 0.9

    console.log('最终缩放比例:', scale)
    canvasScale.value = isFullscreen.value ? 1 : props.type == '1' ? 0.9 : 0.95
  }
  else {
    console.error('找不到容器元素')
  }
}

// 简化：直接使用放映功能的缩放逻辑
const resetZoom = () => {
  calculateScale()
}

// 背景样式
const background = computed(() => currentSlide.value?.background)
const { backgroundStyle } = useSlideBackgroundStyle(background)

// 计算当前幻灯片的元素列表
const elementList = computed(() => {
  return currentSlide.value?.elements || []
})

// 检测当前幻灯片是否包含iframe元素
const currentSlideHasIframe = computed(() => {
  console.log('elementList.value', elementList.value)
  return elementList.value.some(element => element.type === ElementTypes.FRAME)
})

// 跳转到指定幻灯片
const goToSlide = (index: number) => {
  console.log('goToSlide 被调用，目标索引:', index)
  console.log('当前索引:', slideIndex.value)
  
  if (index >= 0 && index < slides.value.length) {
    slidesStore.updateSlideIndex(index)
    console.log('更新后的索引:', slideIndex.value)
  }
  else {
    console.warn('goToSlide: 无效的索引:', index)
  }
}

// 上一页
const previousSlide = () => {
  if (slideIndex.value > 0) {
    const newIndex = slideIndex.value - 1
    console.log('上一页，从', slideIndex.value, '到', newIndex)
    slidesStore.updateSlideIndex(newIndex)
  }
}

// 下一页
const nextSlide = () => {
  if (slideIndex.value < slides.value.length - 1) {
    const newIndex = slideIndex.value + 1
    console.log('下一页，从', slideIndex.value, '到', newIndex)
    slidesStore.updateSlideIndex(newIndex)
  }
}

// 监听slideIndex变化，调用getWork
watch(() => slideIndex.value, (newIndex, oldIndex) => {
  console.log('slideIndex变化，调用getWork', { newIndex, oldIndex })
  if (newIndex !== oldIndex && typeof newIndex === 'number' && currentSlideHasIframe.value) {
    console.log('触发getWork，当前幻灯片索引:', newIndex)
    getWork()
  }
}, { immediate: false, deep: false })

// 全屏
const enterFullscreen = () => {
  if (document.fullscreenElement) {
    document.exitFullscreen()
  }
  else {
    document.documentElement.requestFullscreen()
  }
}

// 监听全屏状态变化
const handleFullscreenChange = () => {
  isFullscreen.value = !!document.fullscreenElement

  if (isFullscreen.value) {
    // 全屏时不需要计算缩放，直接使用放映功能
    console.log('进入全屏模式')
  }
  else {
    // 退出全屏时重置所有工具状态并重新计算缩放比例
    console.log('退出全屏模式，重置工具状态')

    // 重置所有工具状态
    rightToolsVisible.value = false
    writingBoardToolVisible.value = false
    timerlVisible.value = false
    slideThumbnailModelVisible.value = false
    laserPen.value = false

    // 重新计算缩放比例
    nextTick(() => {
      calculateScale()
    })
  }
}

// 切换激光笔模式
const toggleLaserPen = () => {
  laserPen.value = !laserPen.value
  console.log('激光笔状态:', laserPen.value ? '开启' : '关闭')
}

// 获取导入导出功能
const { readJSON, exportJSON2, getFile } = useImport()

// 根据iframe的URL查找对应的幻灯片索引
const findSlideIndexByIframeUrl = (iframeUrl: string): number => {
  try {
    console.log('查找iframe对应的幻灯片索引，iframe URL:', iframeUrl)

    // 遍历所有幻灯片，查找包含该iframe URL的幻灯片
    for (let i = 0; i < slides.value.length; i++) {
      const slide = slides.value[i]

      // 检查幻灯片的元素中是否有iframe
      if (slide.elements && slide.elements.length > 0) {
        for (const element of slide.elements) {
          // 检查是否是iframe元素
          if (element.type === ElementTypes.FRAME) {
            // 检查iframe的src是否匹配
            if (element.url === iframeUrl) {
              console.log(`找到匹配的幻灯片，索引: ${i}, 幻灯片ID: ${slide.id}`)
              return i
            }
          }
        }
      }
    }

    // 如果没有找到匹配的幻灯片，返回当前幻灯片索引
    console.log('未找到匹配的幻灯片，使用当前幻灯片索引:', slideIndex.value)
    return slideIndex.value
  }
  catch (error) {
    console.error('查找幻灯片索引时出错:', error)
    return slideIndex.value
  }
}

// 处理iframe链接，为包含workPage的iframe添加必要参数
// 处理iframe链接，为包含workPage的iframe添加必要参数
const processIframeLinks = async () => {
  try {
    console.log('开始处理iframe链接')
    console.log('当前props:', { courseid: props.courseid, userid: props.userid })

    // 从slides数据中查找包含iframe的元素
    let hasIframe = false
    // 由于有异步操作，需整体用Promise.all处理
    const updatedSlides = await Promise.all(
      slides.value.map(async (slide, slideIndex) => {
        if (slide.elements && slide.elements.length > 0) {
          // 这里不能直接用async map，否则会导致类型不对
          const updatedElements = await Promise.all(
            slide.elements.map(async (element) => {
              // 检查是否是iframe元素
              if (element.type === ElementTypes.FRAME && element.url) {
                const iframeSrc = element.url

                if (iframeSrc.includes('workPage')) {
                  hasIframe = true
                  console.log(`处理幻灯片 ${slideIndex + 1} 中的iframe链接:`, iframeSrc)

                  try {
                    // 解析URL，处理hash部分
                    let baseUrl = iframeSrc
                    let hashPart = ''

                    // 分离base URL和hash部分
                    if (iframeSrc.includes('#')) {
                      const parts = iframeSrc.split('#')
                      baseUrl = parts[0]
                      hashPart = parts[1]
                    }

                    // 构建新的hash部分，添加参数
                    // 使用当前幻灯片索引作为task参数
                    let newHash = hashPart
                    if (newHash.includes('?')) {
                      // 如果hash中已经有查询参数，添加&
                      newHash += `&courseid=${props.courseid || ''}&userid=${props.userid || ''}&stage=0&task=${slideIndex}&tool=0`
                    } 
                    else {
                      // 如果hash中没有查询参数，添加?
                      newHash += `?courseid=${props.courseid || ''}&userid=${props.userid || ''}&stage=0&task=${slideIndex}&tool=0`
                    }

                    // 构建新的URL
                    const newUrl = `${baseUrl}#${newHash}`

                    console.log(`幻灯片 ${slideIndex + 1} 的iframe链接已更新:`, newUrl)

                    // 返回更新后的元素
                    return {
                      ...element,
                      url: newUrl
                    }
                  } 
                  catch (error) {
                    console.error(`处理幻灯片 ${slideIndex + 1} 的iframe链接时出错:`, error)
                    return element
                  }
                } 
                else if (iframeSrc.includes('.html') || iframeSrc.includes('.htm')) {
                  hasIframe = true
                  const html = await api.getHTML(iframeSrc)
                  // const html = await api.getHTML('https://knowledge.cocorobo.cn/zh-CN/story-telling/a7fa08b8-cf60-11ef-93e3-12e77c4cb76b')
                  console.log('html', html)
                  console.log(`处理幻灯片 ${slideIndex + 1} 中的iframe链接:`, iframeSrc)
                  return {
                    ...element,
                    isHTML: true,
                    url: html
                  }
                }
              }

              // 不是iframe元素或不需要处理，直接返回
              return element
            })
          )

          // 返回更新后的幻灯片
          return {
            ...slide,
            elements: updatedElements
          }
        }

        // 没有元素的幻灯片直接返回
        return slide
      })
    )

    if (hasIframe) {
      console.log('找到iframe元素，更新slides数据')
      // 更新store中的slides数据
      slidesStore.setSlides(updatedSlides)
      console.log('slides数据更新完成')
    }
    else {
      console.log('未找到包含workPage的iframe元素')
    }

    console.log('iframe链接处理完成')
  }
  catch (error) {
    console.error('处理iframe链接时出错:', error)
  }
}

// 导入JSON功能
const importJSON = (jsonData: any) => {
  try {
    console.log('Student importJSON 开始执行')

    const result = readJSON(jsonData, true)

    if (result.success) {
      console.log('Student importJSON 成功，开始重新渲染')

      // 强制重新渲染：先隐藏组件
      showSlideList.value = false

      // 重新计算画布尺寸和缩放比例
      nextTick(() => {
        calculateScale()

        // 延迟500ms后重新显示组件，确保重新渲染完成
        setTimeout(() => {
          showSlideList.value = true
          console.log('组件重新渲染完成')
        }, 500)
      })

      return true
    }

    console.error('Student importJSON 失败:', result.error)
    return false

  }
  catch (error) {
    console.error('Student importJSON 执行失败:', error)
    return false
  }
}

// 导出JSON功能
const exportJSON = () => {
  try {
    console.log('Student exportJSON 开始执行，调用 useImport.exportJSON2')

    // 直接调用 useImport 中的 exportJSON2 函数
    const exportData = exportJSON2()

    if (exportData) {

      return exportData
    }
    console.error('Student exportJSON 失败: exportJSON2 返回空数据')
    return false

  }
  catch (error) {
    console.error('Student exportJSON 执行失败:', error)
    return false
  }
}

// 返回编辑器
const backToEditor = () => {
  // 通过路由跳转到编辑模式
  window.location.href = '/'
}

const submitWork = async (slideIndex: number, atool: string, content: string, type: string) => {
  const res = await api.submitWork({
    uid: props.userid as string,
    cid: props.courseid as string,
    stage: '0',
    task: String(slideIndex), // 转为字符串
    tool: '0',
    atool: atool,
    content: content,
    type: type
  })
  getWork()
  console.log(res)
}
// 文件上传到AWS S3的函数
const uploadFile = (file: File): Promise<string> => {
  return new Promise((resolve, reject) => {
    try {
      // 检查AWS SDK是否可用
      if (!(window as any).AWS) {
        reject(new Error('AWS SDK not loaded'))
        return
      }

      const credentials = {
        accessKeyId: 'AKIATLPEDU37QV5CHLMH',
        secretAccessKey: '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'
      }

      // 配置AWS
      ;(window as any).AWS.config.update(credentials)
      ;(window as any).AWS.config.region = 'cn-northwest-1'

      // 创建S3实例
      const bucket = new (window as any).AWS.S3({ params: { Bucket: 'ccrb' } })

      if (file) {
        // 生成唯一的文件名
        const fileExtension = file.name.split('.').pop()
        const fileName = `${file.name.split('.')[0]}_${Date.now()}.${fileExtension}`

        const params = {
          Key: fileName,
          ContentType: file.type,
          Body: file,
          ACL: 'public-read'
        }

        const options = {
          partSize: 2048 * 1024 * 1024, // 2GB分片
          queueSize: 2,
          leavePartsOnError: true
        }

        bucket
          .upload(params, options)
          .on('httpUploadProgress', (evt: any) => {
            // 这里可以添加进度条逻辑
            const progress = Math.round((evt.loaded * 100) / evt.total)
            console.log(`Uploaded: ${progress}%`)
          })
          .send((err: any, data: any) => {
            if (err) {
              console.error('Upload failed:', err)
              message.error('文件上传失败')
              reject(err)
            }
            else {
              console.log('Upload successful:', data.Location)
              resolve(data.Location)
            }
          })
      }
      else {
        reject(new Error('No file provided'))
      }
    }
    catch (error) {
      console.error('Upload error:', error)
      reject(error)
    }
  })
}
// 作业提交功能（优化版）
const handleHomeworkSubmit = async () => {
  console.log('作业提交按钮被点击')

  // 防抖：如果正在提交中，直接返回
  if (isSubmitting.value) {
    console.log('作业正在提交中，忽略重复点击')
    return
  }

  isSubmitting.value = true

  try {
    // 获取所有iframe元素
    const iframes = document.querySelectorAll('.viewer-canvas .screen-slide')[slideIndex.value].querySelectorAll('iframe')
    console.log('找到iframe元素数量:', iframes.length)

    if (iframes.length === 0) {
      message.warning('当前页面没有找到iframe元素')
      return
    }

    let hasSubmitWork = false

    for (let i = 0; i < iframes.length; i++) {
      const iframe = iframes[i] as HTMLIFrameElement
      const iframeSrc = iframe.src
      console.log(`iframe ${i + 1} 链接:`, iframeSrc)

      // 检查iframe链接是否包含workPage
      if (iframeSrc && iframeSrc.includes('workPage')) {
        console.log('找到包含workPage的iframe，尝试执行submitWork')

        try {
          const iframeWindow = iframe.contentWindow as Window & { submitWork?: (...args: any[]) => unknown }

          if (iframeWindow && typeof iframeWindow.submitWork === 'function') {
            console.log('执行iframe中的submitWork方法，参数可变')
            const iframeSlideIndex = slideIndex.value
            const submitArgs = [iframeSlideIndex]

            // 支持同步和异步submitWork
            const result = await iframeWindow.submitWork(...submitArgs)
            if (result instanceof Promise) {
              await result
              console.log('submitWork异步执行完成')
            } 
            else {
              console.log('submitWork同步执行完成')
              message.success('作业提交成功')
              hasSubmitWork = true
            }

            break
          } 
          else {
            console.log('iframe中没有找到submitWork方法')
          }
        } 
        catch (error) {
          console.error('访问iframe内容时出错:', error)
        }
      } 
      else if (iframeSrc && (iframeSrc.includes('aichat.cocorobo') || iframeSrc.includes('knowledge.cocorobo'))) {
        console.log('找到包含aichat.cocorobo或knowledge.cocorobo的iframe，尝试执行submitWork')
        // 由于TS类型检查，需通过 any 绕过类型限制
        const iframeWindow = iframe.contentWindow as any
        if (iframeWindow && iframeWindow.exposed_outputs) {
          console.log('执行iframe中的submitWork方法，参数可变')
          const iframeSlideIndex = slideIndex.value
          const Cow = JSON.stringify(iframeWindow.exposed_outputs)
          // 这里假设 submitWork 是全局可用的函数
          await submitWork(iframeSlideIndex, '72', Cow, '20')
          message.success('作业提交成功')
          hasSubmitWork = true
        }
      }
      else {
        // message.warning('当前页面暂不支持作业提交')
        console.log('尝试截图当前页面并提交')
        // return
        try {
          // 尝试使用html2canvas，对iframe支持更好
          let imageData: string
          const screenSlides = document.querySelectorAll('.viewer-canvas .screen-slide')
          let iframe: HTMLElement | null = null
          if (
            screenSlides &&
            screenSlides[slideIndex.value] &&
            screenSlides[slideIndex.value].querySelector('iframe') &&
            (screenSlides[slideIndex.value].querySelector('iframe') as HTMLIFrameElement).contentWindow &&
            (screenSlides[slideIndex.value].querySelector('iframe') as HTMLIFrameElement).contentWindow!.document &&
            (screenSlides[slideIndex.value].querySelector('iframe') as HTMLIFrameElement).contentWindow!.document.body
          ) {
            iframe = (screenSlides[slideIndex.value].querySelector('iframe') as HTMLIFrameElement).contentWindow!.document.body as HTMLElement
          }
          else {
            throw new Error('未能获取到iframe的body元素，无法截图')
          }
          try {
            // 首先尝试使用html2canvas
            const html2canvas = await import('html2canvas')
            const canvas = await html2canvas.default(iframe, {
              useCORS: true,
              allowTaint: true,
              scale: 1,
              backgroundColor: '#ffffff',
              logging: false,
              // 尝试截取iframe内容
              foreignObjectRendering: true,
              removeContainer: true
            })
            imageData = canvas.toDataURL('image/png', 0.95)
            console.log('使用html2canvas截图成功')
          }
          catch (html2canvasError) {
            console.log('html2canvas截图失败，回退到html-to-image:', html2canvasError)
            
            // 回退到html-to-image
            const { toPng } = await import('html-to-image')
            imageData = await toPng(iframe, {
              quality: 0.95,
              backgroundColor: '#ffffff'
            })
            console.log('使用html-to-image截图成功')
          }
          
          // 将base64字符串转换为File对象
          const base64ToFile = (base64String: string, filename: string): File => {
            const arr = base64String.split(',')
            const mime = arr[0].match(/:(.*?);/)?.[1] || 'image/png'
            const bstr = atob(arr[1])
            let n = bstr.length
            const u8arr = new Uint8Array(n)
            while (n--) {
              u8arr[n] = bstr.charCodeAt(n)
            }
            return new File([u8arr], filename, { type: mime })
          }
          
          const imageFile = base64ToFile(imageData, `screenshot_${Date.now()}.png`)
          const imageUrl = await uploadFile(imageFile)
          // 提交截图
          await submitWork(slideIndex.value, '73', imageUrl, '1') // 73表示截图工具，21表示图片类型
          message.success('页面截图提交成功')
          hasSubmitWork = true
        }
        catch (error) {
          console.error('截图提交失败:', error)
          message.error('截图提交失败')
        }
      }
    }

    if (!hasSubmitWork) {
      message.info('未找到可用的作业提交功能')
      isSubmitting.value = false
    }
  }
  catch (error) {
    console.error('作业提交过程中出错:', error)
    message.error('作业提交失败')
    isSubmitting.value = false
  }
  finally {
    isSubmitting.value = false
  }
}

// 获取作业提交按钮的右侧位置
const getHomeworkButtonRight = () => {
  if (isFullscreen.value) {
    return 30 // 全屏时按钮在右侧30px
  }
  if (props.type === '1') {
    // 展开作业区：按钮更靠左；收起时：按钮更靠右侧
    return workPanelCollapsed.value ? 60 : 430
  }
  return 30 // type=2时按钮在右侧30px
}


// 键盘快捷键
const handleKeydown = (e: KeyboardEvent) => {
  switch (e.key) {
    case 'ArrowLeft':
    case 'PageUp':
      e.preventDefault()
      previousSlide()
      break
    case 'ArrowRight':
    case 'PageDown':
    case ' ':
      e.preventDefault()
      nextSlide()
      break
    case 'F11':
      e.preventDefault()
      enterFullscreen()
      break
    case 'Escape':
      if (document.fullscreenElement) {
        document.exitFullscreen()
      }
      break
    default:
      break
  }
}

// 事件处理函数
const handleSlidesDataUpdated = () => {
  console.log('收到 slidesDataUpdated 事件')

  // 强制重新渲染：先隐藏组件
  showSlideList.value = false

  nextTick(() => {
    calculateScale()

    // 延迟500ms后重新显示组件，确保重新渲染完成
    setTimeout(() => {
      showSlideList.value = true
      console.log('组件重新渲染完成')

      // 重新处理iframe链接
      processIframeLinks()
    }, 500)

    console.log('slidesDataUpdated 事件处理完成')
  })
}

const handleViewportSizeUpdated = (event: any) => {
  console.log('收到 viewportSizeUpdated 事件:', event.detail)

  // 重新计算缩放比例
  nextTick(() => {
    calculateScale()
    console.log('viewportSizeUpdated 事件处理完成')
  })
}

const getCourseDetail = async () => {
  isLoading.value = true
  try {
    const res = await api.getCourseDetail(props.courseid as string)
    console.log(res)
    const courseDetail = res[0][0]
    const pptJSONUrl = JSON.parse(courseDetail.chapters).pptData ? JSON.parse(courseDetail.chapters).pptData : ''
    console.log(pptJSONUrl)
    
    if (pptJSONUrl) { 
      const pptdata = await getFile(pptJSONUrl)
      // pptdata.data 是 ArrayBuffer，需要先转成字符串再解析为 JSON
      let jsonStr = ''
      if (pptdata && pptdata.data) {
        // 先将 ArrayBuffer 转为字符串
        const uint8Array = new Uint8Array(pptdata.data)
        jsonStr = new TextDecoder('utf-8').decode(uint8Array)
        try {
          const jsonObj = JSON.parse(jsonStr)
          importJSON(jsonObj)
        }
        catch (e) {
          console.error('解析pptdata.data失败:', e)
        }
      }
    }
  }
  catch (error) {
    console.error('获取课程详情失败:', error)
    message.error('获取课程详情失败')
    isLoading.value = false
  }
  finally {
    isLoading.value = false
  }
}

const getWork = async () => {
  try {
    workLoading.value = true
    console.log('getWork 开始执行，参数:', {
      courseid: props.courseid,
      slideIndex: slideIndex.value,
      type: props.type
    })
    
    if (!props.courseid) {
      console.warn('getWork: courseid 未提供，跳过执行')
      workLoading.value = false
      return
    }
    
    const res = await api.selectSWorks(props.courseid, '0', slideIndex.value.toString())
    console.log('getWork 执行成功，结果:', res)
    const frame = elementList.value.find(element => element.type === ElementTypes.FRAME)
    console.log('frame:', frame)
    const toolType = frame?.toolType ?? ''
    workArray.value = props.cid
      ? res[0].filter((work: any) => {
        return work.type === 1 || (work.type === 2 && work.classid.includes(props.cid)) && (work.atool === toolType || !toolType)
      })
      : res[0]
    console.log('getWork 执行成功，结果:', workArray.value)
  }
  catch (error) {
    console.error('getWork 执行失败:', error)
    message.error('获取作业信息失败')
  }
  finally {
    workLoading.value = false
  }
}

onMounted(() => {
  document.addEventListener('keydown', handleKeydown)

  // 处理URL参数
  if (props.courseid || props.type) {
    console.log('收到URL参数:', { courseid: props.courseid, type: props.type })

    // 这里可以根据courseid和type进行相应的处理
    // 比如加载特定的课程数据、设置特定的显示模式等
    if (props.courseid) {
      console.log('课程ID:', props.courseid)
      // TODO: 根据courseid加载对应的课程数据
    }

    if (props.type) {
      console.log('类型:', props.type)
      // TODO: 根据type设置特定的显示模式或功能
    }
  }
  getCourseDetail()
  getWork()

  // 计算初始缩放比例
  nextTick(() => {
    calculateScale()

    // 处理iframe链接
    processIframeLinks()
  })

  // 监听窗口大小变化
  window.addEventListener('resize', calculateScale)

  // 监听全屏状态变化
  document.addEventListener('fullscreenchange', handleFullscreenChange)

  // 监听幻灯片数据更新事件（来自useImport的readJSON）
  window.addEventListener('slidesDataUpdated', handleSlidesDataUpdated)

  // 监听视口尺寸更新事件
  window.addEventListener('viewportSizeUpdated', handleViewportSizeUpdated)

  // 将导入导出功能暴露到window上，方便调试和外部调用
  ; (window as any).PPTistStudent = {
    importJSON,
    exportJSON,
    slides: slidesStore.slides,
    currentSlide: computed(() => slidesStore.currentSlide),
    slideIndex: computed(() => slidesStore.slideIndex),
    goToSlide,
    previousSlide,
    nextSlide,
    enterFullscreen,
    toggleLaserPen,
    // 添加URL参数到全局对象中
    courseid: props.courseid,
    type: props.type
  }

  console.log('PPTist Student View 已加载，可通过 window.PPTistStudent 访问功能')
  console.log('URL参数:', { courseid: props.courseid, type: props.type })
})


onUnmounted(() => {
  document.removeEventListener('keydown', handleKeydown)
  window.removeEventListener('resize', calculateScale)
  document.removeEventListener('fullscreenchange', handleFullscreenChange)

  // 移除幻灯片数据更新事件监听器
  window.removeEventListener('slidesDataUpdated', handleSlidesDataUpdated)

  // 移除视口尺寸更新事件监听器
  window.removeEventListener('viewportSizeUpdated', handleViewportSizeUpdated)

  // 清理window上的引用
  if ((window as any).PPTistStudent) {
    delete (window as any).PPTistStudent
    console.log('PPTist Student View 已卸载，window.PPTistStudent 已清理')
  }
})
</script>

<style lang="scss" scoped>
.pptist-student-viewer {
  height: 100vh;
  display: flex;
  background-color: #f5f5f5;

  // 全屏模式样式
  &.fullscreen {
    .layout-content-left {
      display: none; // 全屏时隐藏左侧导航栏
    }

    .layout-content-right {
      display: none; // 全屏时隐藏左侧导航栏
    }

    .viewer-header {
      display: none; // 全屏时隐藏顶部标题栏
    }
  }

  // 激光笔模式样式
  &.laser-pen {
    cursor: url(data:image/png;base64,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) 20 20, default !important;
  }
}

.layout-content-left {
  width: 200px;
  height: 100%;
  background-color: #fff;
  border-right: 1px solid #e0e0e0;
  overflow-y: auto;
}

.layout-content-right {
  width: 400px;
  height: 100%;
  background-color: #fff;
  border-left: 1px solid #e0e0e0;
  overflow-y: auto;
  transition: width .2s ease;
}
.layout-content-right.collapsed {
  width: 48px;
}
.homework-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
/* 收缩时头部仅显示按钮，并保持按钮在可用宽度内水平居中 */
.layout-content-right.collapsed .homework-header {
  justify-content: center;
  padding: 8px;
}
.collapse-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: 1px solid #d9d9d9;
  border-radius: 8px;
  background: #fff;
  color: #333;
  cursor: pointer;
  line-height: 1;
  font-weight: 700;
}
.collapse-btn:hover {
  border-color: #1890ff;
  color: #1890ff;
}

.homework-title {
  padding: 12px 12px 0 12px;
  color: #333;
  font-size: 14px;
  font-weight: 600;
}
.homework-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  padding: 12px;
}
.homework-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-width: 0;
  height: 35px;
  border: 1px solid #2f80ed;
  color: #2f80ed;
  background: #fff;
  border-radius: 8px;
  cursor: pointer;
  font-weight: 600;
  overflow: hidden;
  padding: 0 10px;
  text-align: center;
}
.homework-btn__text {
  display: block;
  max-width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.homework-btn:hover {
  box-shadow: 0 2px 10px rgba(0,0,0,0.08);
}
.homework-loading {
  padding: 12px;
  color: #666;
  font-size: 13px;
}
.homework-empty {
  padding: 12px;
  color: #999;
  font-size: 13px;
}

.thumbnails {
  padding: 0;

  .viewer-header {
    margin-bottom: 16px;

    h3 {
      margin: 0;
      font-size: 16px;
      font-weight: 600;
      color: #333;
    }
  }

  .thumbnail-list {
    width: 100%;
    padding: 0 16px;
    box-sizing: border-box;

    .thumbnail-item {
      position: relative;
      margin-bottom: 12px;
      cursor: pointer;
      border-radius: 8px;
      overflow: hidden;
      transition: all 0.2s ease;
      border: 2px solid rgba(24, 144, 255, 0.2);

      &:hover {
        transform: translateY(-2px);
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
        border-color: rgba(24, 144, 255, 0.4);
      }

      &.active {
        border: 2px solid #1890ff;
        box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
      }

      .label {
        position: absolute;
        top: 8px;
        left: 8px;
        background-color: rgba(0, 0, 0, 0.6);
        color: #fff;
        padding: 2px 6px;
        border-radius: 4px;
        font-size: 12px;
        font-weight: 600;
        z-index: 1;
      }

      .thumbnail {
        width: 100%;
        height: auto;
      }
    }
  }

  .page-number {
    text-align: center;
    margin-top: 16px;
    padding: 8px;
    background-color: #f0f0f0;
    border-radius: 4px;
    font-size: 14px;
    color: #666;
  }

  .progress-bar {
    margin-top: 12px;
    height: 6px;
    background-color: #f0f0f0;
    border-radius: 3px;
    overflow: hidden;

    .progress-fill {
      height: 100%;
      background: linear-gradient(90deg, #1890ff, #40a9ff);
      border-radius: 3px;
      transition: width 0.3s ease;
    }
  }
}

.layout-content-center {
  flex: 1;
  display: flex;
  flex-direction: column;
  background-color: #000;
}

.viewer-header {
  height: 60px;
  background-color: #fff;
  border-bottom: 1px solid #e0e0e0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 24px;
  transition: transform 0.3s ease;

  &.hidden {
    transform: translateY(-100%);
  }

  .slide-title {
    font-size: 18px;
    font-weight: 600;
    color: #333;
  }

  .viewer-controls {
    display: flex;
    gap: 12px;

    button {
      padding: 8px 12px;
      border: 1px solid #d9d9d9;
      border-radius: 6px;
      background-color: #fff;
      color: #333;
      cursor: pointer;
      transition: all 0.2s ease;
      display: flex;
      align-items: center;
      justify-content: center;
      min-width: 40px;
      height: 36px;

      &:hover:not(:disabled) {
        border-color: #1890ff;
        color: #1890ff;
      }

      &:disabled {
        opacity: 0.5;
        cursor: not-allowed;
      }

      &.back-btn {
        background-color: #1890ff;
        color: #fff;
        border-color: #1890ff;

        &:hover {
          background-color: #40a9ff;
          border-color: #40a9ff;
        }
      }

      .control-icon {
        font-size: 16px;
      }
    }
  }
}

.viewer-canvas {
  flex: 1;
  position: relative;
  background-color: rgb(249, 249, 249);
  overflow: hidden;

  // 全屏时隐藏滚动条和边框
  &.fullscreen-mode {
    overflow: hidden !important;
    background-color: transparent !important;
  }
}

.slide-list-wrap {
  position: absolute;
  overflow: hidden;
  background-color: #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.01), 0 0 12px 0 rgba(0, 0, 0, 0.1);
  border-radius: 8px;

  /* 全屏时去掉圆角 */
  .pptist-student-viewer.fullscreen & {
    border-radius: 0;
  }
}

.loading-indicator {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;

  .loading-text {
    color: #666;
    font-size: 14px;
    background-color: rgba(255, 255, 255, 0.9);
    padding: 12px 20px;
    border-radius: 6px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  }
}

// 全屏模式样式
.fullscreen-slide {
  // 使用放映功能的默认样式
}

// 全屏工具按钮样式，直接复制放映功能的样式
.tools-left {
  position: fixed;
  bottom: 8px;
  left: 8px;
  font-size: 25px;
  color: #666;
  z-index: 10;

  .tool-btn {
    opacity: .3;
    cursor: pointer;
    transition: opacity 0.3s;

    &:hover {
      opacity: .95;
    }

    &+.tool-btn {
      margin-left: 8px;
    }
  }
}

.tools-right {
  height: 66px;
  position: fixed;
  bottom: -66px;
  right: 0;
  z-index: 5;
  padding: 8px;
  transition: bottom 0.3s;

  &.visible {
    bottom: 0;
  }

  &::after {
    content: '';
    width: 100%;
    height: 66px;
    position: absolute;
    left: 0;
    top: -66px;
  }

  .content {
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    border-radius: 4px;
    font-size: 25px;
    background-color: #fff;
    color: #333;
    padding: 8px 10px;
    box-shadow: 0 2px 12px 0 rgb(56, 56, 56, .2);
    border: 1px solid #e2e6ed;
  }

  .tool-btn {
    cursor: pointer;

    &:hover,
    &.active {
      color: #1890ff;
    }

    &+.tool-btn {
      margin-left: 15px;
    }
  }

  .page-number {
    font-size: 12px;
    padding: 0 12px;
    cursor: pointer;
  }
}

.viewport {
  position: relative;
  width: 100%;
  height: 100%;
  background-color: #fff;
}

.background {
  width: 100%;
  height: 100%;
  background-position: center;
  position: absolute;
}

// 响应式设计
@media (max-width: 768px) {
  .layout-content-left {
    width: 160px;
  }

  .layout-content-right {
    width: 160px;
  }

  .viewer-header {
    padding: 0 16px;

    .slide-title {
      font-size: 16px;
    }

    .viewer-controls button {
      padding: 6px 12px;
      font-size: 14px;
    }
  }
}

/* 作业提交按钮样式 */
.homework-submit-btn {
  position: fixed;
  bottom: 30px;
  z-index: 100;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  padding: 12px 20px;
  border-radius: 25px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
  transition: all 0.3s ease;
  font-size: 14px;
  font-weight: 500;

  &:hover:not(.submitting) {
    transform: translateY(-2px);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
  }

  &:active:not(.submitting) {
    transform: translateY(0);
  }

  &.submitting {
    cursor: not-allowed;
    opacity: 0.8;
    background: linear-gradient(135deg, #999 0%, #666 100%);
  }

  .btn-text {
    white-space: nowrap;
  }

  .tool-btn {
    background: transparent;
    color: white;
    width: 20px;
    height: 20px;
    font-size: 16px;

    &:hover {
      background: transparent;
      transform: none;
    }
  }

  .loading-spinner {
    width: 20px;
    height: 20px;
    border: 2px solid rgba(255, 255, 255, 0.3);
    border-top: 2px solid white;
    border-radius: 50%;
    animation: spin 1s linear infinite;
  }
}

/* Loading状态样式 */
.loading-overlay {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(255, 255, 255, 0.95);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;

    .loading-spinner {
      width: 40px;
      height: 40px;
      border: 4px solid #f3f3f3;
      border-top: 4px solid #1890ff;
      border-radius: 50%;
      animation: spin 1s linear infinite;
      margin: 0 auto 16px;
  }
}

.loading-content {
    text-align: center;
    color: #666;
}


.loading-text {
    font-size: 14px;
    color: #666;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}
</style>