<!-- AI自主学习 -->
<template>
  <div class="self-directed-learning">
    <div class="title-section">
      <h3>和AI一起，学你想学！</h3>
    </div>
    <div class="input-section">
      <!-- 发送消息输入框 -->
      <div class="dialogue-card user-input-card">
        <div class="dialogue-content">
          <textarea
            v-model="prompt"
            class="user-input-textarea"
            placeholder=""
            @keyup.enter.exact="doSendMessage(prompt.trim())"
          ></textarea>
          <div class="dropdowns-container">
            <el-select
              v-for="dropdown in dropdowns"
              :key="dropdown.key"
              v-model="dropdown.value"
              @change="(value) => handleSelect(dropdown.key, value)"
              filterable
              class="custom-select"
              :popper-append-to-body="false"
              :teleported="false"
            >
              <template #prefix>
                <el-icon><component :is="dropdown.icon" /></el-icon>
              </template>
              <el-option
                v-for="item in dropdown.options"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
          </div>
          <button class="send-button" :class="{ 'active': prompt.trim().length > 0 && (!showNewContainer || allStepsCompleted) }" @click="doSendMessage(prompt.trim())" :disabled="!prompt.trim().length || (showNewContainer && !allStepsCompleted)">
            <Top />
          </button>
        </div>
      </div>

      <!-- 生成/进度 -->
      <div class="new-container" v-if="showNewContainer">
        <!-- 全部完成时显示成功状态 -->
        <div v-if="allStepsCompleted" class="success-container">
          <div class="success-checkmark">✓</div>
          <div class="success-text">完成</div>
        </div>
        <!-- 未完成时显示进度 -->
        <template v-else>
          <div class="left-box">
            <div class="loading-container">
              <div class="loading-spinner"></div>
              <div class="loading-text">正在生成中</div>
            </div>
          </div>
          <div class="right-box">
            <div class="progress-container">
              <div class="progress-title">正在生成课程</div>
              <div class="progress-steps">
                <div class="progress-step" v-for="(step, index) in visibleProgressSteps" :key="index" :style="{ animationDelay: `${index * 0.2}s` }">
                  <div class="step-header">
                    <span class="step-text">{{ step.text }}</span>
                    <span class="step-status" :class="{ 'completed': step.completed, 'active': step.active }">
                      <span v-if="step.completed" class="checkmark">✓</span>
                      <span v-else-if="step.active" class="loading-dot"></span>
                      <span v-else class="step-placeholder"></span>
                    </span>
                  </div>
                  <div class="step-progress" v-if="(index === 2 || index === 3) && step.visible">
                    <div class="progress-bar">
                      <div class="progress-fill" :style="{ width: `${step.progress}%` }"></div>
                    </div>
                    <span class="progress-text">{{ step.progress }}%</span>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </template>
      </div>
    </div>
  </div>

  <el-divider></el-divider>
</template>

<script setup>
import {ref, onMounted, computed, reactive, defineEmits} from "vue";

// 定义事件
const emit = defineEmits(['refreshData']);
import { Top, Search, User,Memo,ArrowUpBold,ArrowDownBold } from '@element-plus/icons-vue'
import {
  aIGenerateCourse,
  AiImageStatusEnum,
  CreateDialogue,
  CreatePainting,
  PaintingGetMys,
  sendChatMessageStream, textToSpeech
} from "@/api/questions.js";
import {Message} from "@/utils/message/Message.js";
import {teacherList} from "@/api/teachers.js";

// 本地数字人列表
const localScriptRoles = ref([])

// 发送消息输入框
const prompt = ref(""); // prompt

// 对话相关
const activeConversationId = ref(null) // 选中的对话编号
const conversationInAbortController = ref() // 对话进行中 abort 控制器(控制 stream 对话)
const conversationInProgress = ref(false) // 对话是否正在进行中。目前只有【发送】消息时，会更新为 true，避免切换对话、删除对话等操作
const enableContext = ref(true) // 是否开启上下文

// 接收 Stream 消息
const receiveMessageFullText = ref('')
const scriptDataTemp = ref(null)

// 生成状态
const isGenerating = ref(false)// 是否正在生成脚本
const isGeneratingImages = ref(false)// 是否正在生成图片
const isGeneratingVoiceovers = ref(false)// 是否正在生成语音
const generatingImageUrl = ref('')

// 图片生成相关状态
const inProgressImageMap = ref({}) // 监听的图片映射，key 为 image 编号，value 为 { sectionIndex, type: 'image'|'audio' }
const inProgressTimer = ref(null) // 生成中的图片定时器，轮询生成进展

// 小节列表
const lessonList = ref([
  {id: '1', name: '课程引入'},
  {id: '2', name: '知识讲解'},
  {id: '3', name: '课程总结'}
])
//主讲人、助讲人
const selectedMainTeacher = ref('')
const selectedAssistants = ref([''])

//脚本数据
const scriptData = reactive(
    {
      courseName: '', // 课程名称
      coverImage: { // 封面图
        prompt: '',
        url: '',
        generating: false
      },
      lessons: [ // 课程小节
        {
          lessonName: '课程引入', // 小节课程名称
          sections: [ // 环节
            {
              sectionName: '环节一', // 环节名称
              backgroundImage: {
                prompt: '',
                url: '',
                generating: false
              },
              backgroundAudio: {
                type: '',
                url: ''
              },
              dialogues: [
                {
                  type: 'digital',
                  roleName: '',
                  content: '',
                  voiceoverUrl: '',
                  generatingVoiceover: false
                },
                {
                  type: 'user',
                  roleName: '',
                  content: ''
                }
              ]
            }
          ]
        },
        {
          lessonName: '知识讲解', // 小节课程名称
          sections: [ // 环节
            {
              sectionName: '环节一', // 环节名称
              backgroundImage: {
                prompt: '',
                url: '',
                generating: false
              },
              backgroundAudio: {
                type: '',
                url: ''
              },
              dialogues: [
                {
                  type: 'digital',
                  roleName: '',
                  content: '',
                  voiceoverUrl: '',
                  generatingVoiceover: false
                },
                {
                  type: 'user',
                  roleName: '',
                  content: ''
                }
              ]
            }
          ]
        },
        {
          lessonName: '课程总结', // 小节课程名称
          sections: [ // 环节
            {
              sectionName: '环节一', // 环节名称
              backgroundImage: {
                prompt: '',
                url: '',
                generating: false
              },
              backgroundAudio: {
                type: '',
                url: ''
              },
              dialogues: [
                {
                  type: 'digital',
                  roleName: '',
                  content: '',
                  voiceoverUrl: '',
                  generatingVoiceover: false
                },
                {
                  type: 'user',
                  roleName: '',
                  content: ''
                }
              ]
            }
          ]
        }
      ]
    }
)

// 生成脚本
const generateScript = async () => {
  try {
    isGenerating.value = true

    const role = localScriptRoles.value.find((r) => r.name === selectedMainTeacher.value)

    let content =
        prompt.value +
        '（主讲人：' + role.name +
        ',主讲人角色定位：' + role.description +
        '；助讲有：'
    let zhujiang = []
    selectedAssistants.value.forEach((rName) => {
      const assistantRole = localScriptRoles.value.find((r) => r.name === rName)
      zhujiang.push(assistantRole.name + '[' + assistantRole.description + ']')
    })
    content += zhujiang.join('，') + '）;注意：给我的背景图提示词不允许出现主讲人和助讲人物形象。'

    // 1. 创建对话
    await createAiRoleIdConversation(13)

    //2、生成课程信息
    content += "注意：我需要让你生成"+lessonList.value.length+"节课程，";
    for (let i = 1; i <= lessonList.value.length; i++) {
      content+="第"+i+"节课程是"+lessonList.value[i-1].name+"；"
    }

    //3、生成课程小节
    progressSteps.value[0].visible = true;
    progressSteps.value[0].active = true;
    let courseLessons = [];//存储课程小节信息
    scriptData.lessons = []
    for (let i = 0; i < lessonList.value.length; i++) {
      let lesson = lessonList.value[i]
      progressSteps.value[0].next = "生成课程小节【" + lesson.name + "】..."

      content = i === 0 ? content + `现在开始生成第${i+1}节课：${lesson.name}` : content

      let lessonInfo = {courseName: lesson.name, courseLabel: lesson.id};
      await doSendMessageStream(activeConversationId.value, content, lessonInfo)
      console.log("生成课程小节信息：", lessonInfo)
      courseLessons.push(lessonInfo)
    }
    scriptData.lessons = courseLessons;
    progressSteps.value[0].completed = true;
    progressSteps.value[0].active = false;

    content = "最后请给我围绕着这几节课的课程封面图描述词(coverImage)和课程名称(courseName)，课程名字不能超过10个字。"
    progressSteps.value[1].visible = true;
    progressSteps.value[1].active = true;
    let courseInfo = {}//存储课程信息
    await doSendMessageStream(activeConversationId.value, content, courseInfo)
    console.log("生成课程信息：", courseInfo)
    scriptData.courseName = courseInfo.courseName
    scriptData.coverImage = courseInfo.coverImage
    progressSteps.value[1].completed = true;
    progressSteps.value[1].active = false;

    //4、生成全部图片
    progressSteps.value[2].visible = true;
    progressSteps.value[2].active = true;
    await generateAllImages()
    progressSteps.value[2].completed = true;
    progressSteps.value[2].active = false;

    //5、生成全部配音
    progressSteps.value[3].visible = true;
    progressSteps.value[3].active = true;
    await generateAllVoiceovers()
    progressSteps.value[3].completed = true;
    progressSteps.value[3].active = false;

    localStorage.setItem('scriptData', JSON.stringify(scriptData))
    console.log("【最终数据：】", scriptData)

    // 调用完成方法，封装数据并存储到后台
    await completeGenerate()

  } catch (error) {
    console.error('生成脚本失败:', error)
  } finally {
    isGenerating.value = false
  }
}

// 完成生成，封装数据并存储到后台
const completeGenerate = async () => {
  try {
    console.log('开始封装数据并存储到后台...')

    const courses = scriptData.lessons.map(lesson => ({
      courseName: lesson.courseName,
      courseLabel: lesson.courseLabel,
      courseContent: JSON.stringify(lesson)
    }))

    // 封装数据
    const dataToStore = {
      grade: localStorage.getItem('selectedGradeId'),
      courseName: scriptData.courseName,
      coverImage: scriptData.coverImage.url,
      courseList: courses
    }

    console.log('封装的数据:', dataToStore)

    // 调用后端API将文本转成语音
    const res = await aIGenerateCourse(dataToStore)
    if (res.code !== 0) {
      console.error('生成课程失败:', res.msg)
      Message().error('生成课程失败：' + res.msg)
      return
    }
    // 所有步骤完成后，3秒后隐藏容器
    setTimeout(() => {
      showNewContainer.value = false;
      // 通知父组件刷新数据
      emit('refreshData');
    }, 2000);
  } catch (error) {
    console.error('存储数据失败:', error)
  }
}

/** 新建聊天对话 */
const createAiRoleIdConversation = async (roleId) => {
  // 智能问答
  await CreateDialogue({ roleId: roleId })
      .then((res) => {
        console.log("创建会话：", res.data);
        activeConversationId.value = res.data;
      })
      .catch((error) => {
        console.error("请求出错:", error);
      });
}

/** 调取数字人生成脚本 */
const doSendMessageStream = async (conversationId, content, outputContent) => {
  conversationInAbortController.value = new AbortController()
  conversationInProgress.value = true
  receiveMessageFullText.value = '' // 清空之前的文本

  try {
    let isFirstChunk = true
    await sendChatMessageStream(
        conversationId,
        content,
        undefined, // contentAnswer 参数
        conversationInAbortController.value,
        enableContext.value,
        async (res) => {
          const { code, data, msg } = JSON.parse(res.data)
          if (code !== 0) {
            console.error(`对话异常! ${msg}`)
            return
          }

          if (data.eventType === 'TEXT') {
            if (data.receive?.content === '') {
              return
            }

            if (isFirstChunk) {
              isFirstChunk = false
            }

            receiveMessageFullText.value += data.receive.content
            console.log('数据加载中..')
            try {
              const parsedData = JSON.parse(receiveMessageFullText.value)
              // 将解析后的数据填充到outputContent对象中
              console.log('zuizhon..', parsedData)
              Object.assign(outputContent, parsedData)
              // updateScriptData(parsedData)
            } catch (e) {
              // 解析失败，说明数据还不完整，继续等待
            }
          }
        },
        (error) => {
          console.error(`对话异常! ${error}`)
          throw error
        },
        () => {
          try {
            if (receiveMessageFullText.value) {
              console.log('最终数据:', receiveMessageFullText.value)
              const parsedData = JSON.parse(receiveMessageFullText.value)
              console.log('最终数据json:', parsedData)
              // 将解析后的数据填充到outputContent对象中
              // updateScriptData(parsedData)
              console.log('zuizhon..', parsedData)
              Object.assign(outputContent, parsedData)
            }
          } catch (e) {
            console.error('最终数据解析失败:', e)

            // 清洗规则：移除```json、```、** 等非JSON标记，只保留中间的JSON内容
            try {
              let cleanJsonStr = receiveMessageFullText.value
              const parsedData = JSON.parse(
                  cleanJsonStr
                      .replace(/^```json\s*/, '')
                      .replace(/\s*```$/, '')
                      .replace(/\*\*/g, '')
                      .trim()
              )
              console.log('最终清洗后数据json:', parsedData)
              // 将解析后的数据填充到outputContent对象中
              console.log('zuizhon..', parsedData)
              Object.assign(outputContent, parsedData)
              // updateScriptData(parsedData)
            } catch (cleanError) {
              console.error('清洗后数据解析失败:', cleanError)
            }
          }
        }
    )
  } catch (error) {
    console.error('发送消息流失败:', error)
  } finally {
    conversationInProgress.value = false
  }
}

// 生成所有背景图
const generateAllImages = async () => {
  return new Promise(async (resolve, reject) => {
    isGeneratingImages.value = true
    try {
      // 计算总图片数
      progressCounters.value.images.total = 0
      if (scriptData.coverImage && scriptData.coverImage.prompt && !scriptData.coverImage.url) {
        progressCounters.value.images.total++
      }
      if (scriptData.lessons && scriptData.lessons.length > 0) {
        for (let lessonIndex = 0; lessonIndex < scriptData.lessons.length; lessonIndex++) {
          const lesson = scriptData.lessons[lessonIndex]
          if (lesson && lesson.sections) {
            for (let sectionIndex = 0; sectionIndex < lesson.sections.length; sectionIndex++) {
              const section = lesson.sections[sectionIndex]
              if (section && section.backgroundImage && section.backgroundImage.prompt && !section.backgroundImage.url) {
                progressCounters.value.images.total++
              }
            }
          }
        }
      }
      progressCounters.value.images.current = 0

      // 确保scriptData和coverImage存在
      if (!scriptData.coverImage) {
        scriptData.coverImage = { prompt: '', url: '', generating: false }
      }

      // 生成封面图
      if (scriptData.coverImage.prompt && !scriptData.coverImage.url) {
        await generateCoverImage()
      }

      // 生成所有环节的背景图
      if (scriptData.lessons && scriptData.lessons.length > 0) {
        for (let lessonIndex = 0; lessonIndex < scriptData.lessons.length; lessonIndex++) {
          const lesson = scriptData.lessons[lessonIndex]
          if (lesson && lesson.sections) {
            for (let sectionIndex = 0; sectionIndex < lesson.sections.length; sectionIndex++) {
              const section = lesson.sections[sectionIndex]
              // 确保section和backgroundImage存在
              if (section) {
                if (!section.backgroundImage) {
                  section.backgroundImage = { prompt: '', url: '', generating: false }
                }
                // 只处理没有背景图URL的环节
                if (section.backgroundImage.prompt && !section.backgroundImage.url) {
                  await generateImage(lessonIndex, sectionIndex)
                }
              }
            }
          }
        }
      }

      // 检查是否有图片正在生成
      if (Object.keys(inProgressImageMap.value).length === 0) {
        // 没有图片需要生成，直接resolve
        progressSteps.value[2].progress = 100
        isGeneratingImages.value = false
        resolve()
      } else {
        // 启动图片轮询
        startImagePolling()

        // 检查是否有图片正在生成
        const checkImagesComplete = setInterval(() => {
          if (Object.keys(inProgressImageMap.value).length === 0) {
            progressSteps.value[2].progress = 100
            isGeneratingImages.value = false
            clearInterval(checkImagesComplete)
            stopImagePolling()
            resolve()
          }
        }, 1000)
      }
    } catch (error) {
      console.error('生成所有背景图失败:', error)
      isGeneratingImages.value = false
      reject(error)
    }
  })
}

// 生成封面图
const generateCoverImage = async () => {
  scriptData.coverImage.generating = true
  try {
    const response = await CreatePainting({
      "modelId": 56,
      "prompt": scriptData.coverImage.prompt,
      "width": 1024,
      "height": 1024
    })
    console.log("生成封面图", response)
    let imageId = response.data
    // 处理不同格式的响应
    if (typeof imageId === 'object' && imageId !== null) {
      // 如果是对象，尝试获取id属性
      imageId = imageId.id || imageId.imageId || imageId.data
    }
    // 转换为数字
    imageId = Number(imageId)
    if (!isNaN(imageId)) {
      inProgressImageMap.value[imageId] = {
        type: 'cover'
      }
    } else {
      console.error('无效的图片ID:', response.data)
      scriptData.coverImage.generating = false
    }
  } catch (error) {
    console.error('生成封面图失败:', error)
    scriptData.coverImage.generating = false
  }
}

// 生成图片
const generateImage = async (lessonIndex, sectionIndex) => {
  const lesson = scriptData.lessons[lessonIndex]
  if (!lesson) return

  const section = lesson.sections[sectionIndex]
  if (!section) return

  const media = section.backgroundImage

  media.generating = true

  try {
    const res = await CreatePainting({
      "modelId": 56,
      "prompt": media.prompt,
      "width": 1024,
      "height": 1024
    })
    console.log("生成图片", res)
    let imageId = res.data
    // 处理不同格式的响应
    if (typeof imageId === 'object' && imageId !== null) {
      // 如果是对象，尝试获取id属性
      imageId = imageId.id || imageId.imageId || imageId.data
    }
    // 转换为数字
    imageId = Number(imageId)
    if (!isNaN(imageId)) {
      inProgressImageMap.value[imageId] = {
        lessonIndex: lessonIndex,
        sectionIndex: sectionIndex,
        type: 'image'
      }
    } else {
      console.error('无效的图片ID:', res.data)
      media.generating = false
    }
  } catch (error) {
    console.error('生成图片失败:', error);
    media.generating = false
  }
}

// 启动图片轮询
const startImagePolling = () => {
  if (inProgressTimer.value) {
    clearInterval(inProgressTimer.value)
  }
  inProgressTimer.value = setInterval(refreshWatchImages, 3000)
}

// 停止图片轮询
const stopImagePolling = () => {
  if (inProgressTimer.value) {
    clearInterval(inProgressTimer.value)
    inProgressTimer.value = null
  }
}

// 轮询生成中的图片列表
const refreshWatchImages = async () => {
  const imageIds = Object.keys(inProgressImageMap.value)
    .map(Number)
    .filter(id => !isNaN(id))
  if (imageIds.length === 0) {
    return
  }

  try {
    const list = await PaintingGetMys(imageIds)
    const newWatchImages = {}
    let completedCount = 0
    // 遍历所有正在生成的图片
    Object.keys(inProgressImageMap.value).forEach((key) => {
      const imageId = Number(key)
      const info = inProgressImageMap.value[key]
      // 查找对应的图片状态
      const image = list.data.find(item => item.id === imageId)
      if (image) {
        if (image.status === AiImageStatusEnum.IN_PROGRESS) {
          // 图片正在生成中，保留在map中
          newWatchImages[key] = info
        } else if (image.status === AiImageStatusEnum.SUCCESS && image.picUrl) {
          // 图片生成成功
          completedCount++
          if (info.type === 'cover') {
            // 处理封面图
            scriptData.coverImage.url = image.picUrl
            scriptData.coverImage.generating = false
          } else {
            // 处理课程小节背景图
            const lesson = scriptData.lessons[info.lessonIndex]
            if (lesson) {
              const section = lesson.sections[info.sectionIndex]
              if (section) {
                section.backgroundImage.url = image.picUrl
                section.backgroundImage.generating = false
              }
            }
          }
          // 更新生成中的图片预览
          generatingImageUrl.value = image.picUrl

          localStorage.setItem('scriptData', JSON.stringify(scriptData))
          console.log("【最终数据，生成图片成功】", scriptData)
        } else if (image.status === AiImageStatusEnum.FAIL) {
          // 图片生成失败
          completedCount++
          if (info.type === 'cover') {
            // 处理封面图失败
            scriptData.coverImage.generating = false
          } else {
            // 处理课程小节背景图失败
            const lesson = scriptData.lessons[info.lessonIndex]
            if (lesson) {
              const section = lesson.sections[info.sectionIndex]
              if (section) {
                section.backgroundImage.generating = false
              }
            }
          }
        }
      } else {
        // 图片不存在于返回列表中，可能已经处理完成或超时，从map中移除
        completedCount++
        if (info.type === 'cover') {
          scriptData.coverImage.generating = false
        } else {
          const lesson = scriptData.lessons[info.lessonIndex]
          if (lesson) {
            const section = lesson.sections[info.sectionIndex]
            if (section) {
              section.backgroundImage.generating = false
            }
          }
        }
      }
    })
    inProgressImageMap.value = newWatchImages
    
    // 更新进度
    progressCounters.value.images.current = completedCount
    if (progressCounters.value.images.total > 0) {
      progressSteps.value[2].progress = Math.round((completedCount / progressCounters.value.images.total) * 100)
    }
  } catch (error) {
    console.error('轮询图片状态失败:', error)
  }
}

// 生成所有语音
const generateAllVoiceovers = async () => {
  isGeneratingVoiceovers.value = true
  try {
    // 计算总语音数
    progressCounters.value.voiceovers.total = 0
    if (scriptData.lessons && scriptData.lessons.length > 0) {
      for (let lessonIndex = 0; lessonIndex < scriptData.lessons.length; lessonIndex++) {
        const lesson = scriptData.lessons[lessonIndex]
        if (lesson && lesson.sections) {
          for (let sectionIndex = 0; sectionIndex < lesson.sections.length; sectionIndex++) {
            const section = lesson.sections[sectionIndex]
            if (section && section.dialogues) {
              for (let dialogueIndex = 0; dialogueIndex < section.dialogues.length; dialogueIndex++) {
                const dialogue = section.dialogues[dialogueIndex]
                if (dialogue && dialogue.type !== 'user' && !dialogue.voiceoverUrl && dialogue.content) {
                  progressCounters.value.voiceovers.total++
                }
              }
            }
          }
        }
      }
    }
    progressCounters.value.voiceovers.current = 0

    // 确保scriptData和lessons存在
    if (scriptData.lessons && scriptData.lessons.length > 0) {
      for (let lessonIndex = 0; lessonIndex < scriptData.lessons.length; lessonIndex++) {
        const lesson = scriptData.lessons[lessonIndex]
        if (lesson && lesson.sections) {
          for (let sectionIndex = 0; sectionIndex < lesson.sections.length; sectionIndex++) {
            const section = lesson.sections[sectionIndex]
            if (section && section.dialogues) {
              for (let dialogueIndex = 0; dialogueIndex < section.dialogues.length; dialogueIndex++) {
                const dialogue = section.dialogues[dialogueIndex]
                // 只处理没有语音URL且有内容的对话
                if (dialogue && dialogue.type !== 'user' && !dialogue.voiceoverUrl && dialogue.content) {
                  await generateVoiceover(lessonIndex, sectionIndex, dialogueIndex)
                  // 更新进度
                  progressCounters.value.voiceovers.current++
                  if (progressCounters.value.voiceovers.total > 0) {
                    progressSteps.value[3].progress = Math.round((progressCounters.value.voiceovers.current / progressCounters.value.voiceovers.total) * 100)
                  }
                }
              }
            }
          }
        }
      }
    }
    // 完成后设置为100%
    progressSteps.value[3].progress = 100
  } catch (error) {
    console.error('生成所有语音失败:', error)
  } finally {
    isGeneratingVoiceovers.value = false
  }
}

// 文本转语音API调用
// 生成单个语音
const generateVoiceover = async (lessonIndex, sectionIndex, dialogueIndex) => {
  const lesson = scriptData.lessons[lessonIndex]
  if (!lesson) return

  const section = lesson.sections[sectionIndex]
  if (!section) return

  const dialogue = section.dialogues[dialogueIndex]

  // 只处理数字人对话和提问
  if (dialogue.type === 'user') {
    return
  }

  dialogue.generatingVoiceover = true

  let role = localScriptRoles.value.find((r) => r.name === dialogue.roleName)
  if (!role) {
    console.error('未找到角色:', dialogue.roleName)
    dialogue.generatingVoiceover = false
    return
  }
  try {
    // 调用后端API将文本转成语音
    const response = await textToSpeech({
      roleId: role.id,
      content: dialogue.content
    })

    // 将返回的URL赋值给对话
    dialogue.voiceoverUrl = response.data
    localStorage.setItem('scriptData', JSON.stringify(scriptData))
    localStorage.setItem('【最终数据，生成语音成功】', scriptData)
  } catch (error) {
    console.error('生成语音失败:', error)
  } finally {
    dialogue.generatingVoiceover = false
  }
}

// 控制生成进度显示状态
const showNewContainer = ref(false);

// 生成进度步骤
const progressSteps = ref([
  { text: '生成课程脚本...', completed: false, active: false, visible: false, progress: 0 },
  { text: '生成课程小节...', completed: false, active: false, visible: false, progress: 0 },
  { text: '生成背景图...', completed: false, active: false, visible: false, progress: 0 },
  { text: '生成配音...', completed: false, active: false, visible: false, progress: 0 }
]);

// 进度计数器
const progressCounters = ref({
  images: { total: 0, current: 0 },
  voiceovers: { total: 0, current: 0 }
});

// 计算主讲下拉框选项
const teacherOptions = computed(() => {
  const roles = localScriptRoles.value.length > 0 ? localScriptRoles.value : localScriptRoles.value;
  return roles.map(role => ({
    label: role.name,
    value: role.name
  }));
});

// 计算助教下拉框选项
const assistantOptions = computed(() => {
  const roles = localScriptRoles.value.length > 0 ? localScriptRoles.value : localScriptRoles.value;
  return roles.map(role => ({
    label: role.name,
    value: role.name
  }));
});

// 计算生成主题下拉框选项，基于 lessonList 动态生成
const courseOptions = computed(() => {
  // 提取 lessonList 中的课程名称
  const lessonNames = lessonList.value.map(lesson => lesson.name).join('、');
  return [
    {
      label: `诗词课（${lessonNames}）`,
      value: '诗词课'
    }
  ];
});

/**
 * 获取角色列表
 * @returns {Promise<void>}
 */
const getRoleList = async () => {
  try {
    let grade = localStorage.getItem('selectedGrade')
    grade = grade ? grade : '小学低年级'
    // 获取小学低年级AI数据
    const listAiRes = await teacherList({ category: grade + 'AI' })
    const listRes = await teacherList({ category: grade })
    const listAi = listAiRes.data.list || []
    const list = listRes.data.list || []
    listAi.push(...list)
    localScriptRoles.value = listAi
  } catch (error) {
    console.error('获取角色数据失败:', error)
  }
}

// 下拉框配置
const dropdowns = ref([
  {
    key: 'course',
    value: '生成主题',
    visible: false,
    icon: Search,
    options: courseOptions.value
  },
  {
    key: 'teacher',
    value: '主讲',
    visible: false,
    icon: User,
    options: teacherOptions.value
  },
  {
    key: 'assistant',
    value: '助教',
    visible: false,
    icon: Memo,
    options: assistantOptions.value
  }
]);

// 下拉框配置映射，用于生成内容和正则表达式
const dropdownConfig = {
  course: {
    prefix: '诗词课',
    default: '诗词课',
    regex: /诗词课[^,]+/g
  },
  teacher: {
    prefix: '主讲为',
    default: '主讲',
    regex: /主讲为[^,]+/g
  },
  assistant: {
    prefix: '助教为',
    default: '助教',
    regex: /助教为[^,]+/g
  }
};

// 处理下拉框选择
const handleSelect = (key, command) => {
  const dropdown = dropdowns.value.find(item => item.key === key);
  if (dropdown && dropdownConfig[key]) {
     // 更新下拉框显示值
    dropdown.value = command;
    // 如果选择的是主讲，更新selectedMainTeacher
    if (key === 'teacher') {
      selectedMainTeacher.value = command;
    }
    // 如果选择的是助教，更新selectedAssistants
    else if (key === 'assistant') {
      selectedAssistants.value = [command];
    }
    // const config = dropdownConfig[key];

    // // 生成新内容，仅当选择的值与默认值不同时添加
    // const newContent = command === config.default
    //   ? config.prefix
    //   : `${config.prefix}${command}`;

    // // 检查输入框中是否已存在该类型的内容
    // if (config.regex.test(prompt.value)) {
    //   // 替换已存在的内容
    //   prompt.value = prompt.value.replace(config.regex, newContent);
    // } else {
    //   // 添加到输入框，用逗号隔开
    //   if (prompt.value.trim()) {
    //     prompt.value += `, ${newContent}`;
    //   } else {
    //     prompt.value = newContent;
    //   }
    // }
  }
};

// 处理下拉框可见性变化
const handleVisibleChange = (key, visible) => {
  const dropdown = dropdowns.value.find(item => item.key === key);
  if (dropdown) {
    dropdown.visible = visible;
  }
};

/** 处理来自 keydown 的发送消息 */
const handleSendByKeydown = async (event) => {
  const content = prompt.value?.trim();
  if (event.key === "Enter") {
    if (event.shiftKey) {
      // 插入换行
      prompt.value += "\r\n";
      event.preventDefault(); // 防止默认的换行行为
    } else {
      // 发送消息
      await doSendMessage(content);
      event.preventDefault(); // 防止默认的提交行为
    }
  }
};

/** 生成操作 */
const doSendMessage = async (content) => {
  // 校验
  if (content.length < 1) {
    console.error("发送失败，原因：内容为空！");
    return;
  }

  showNewContainer.value = true;

  // 调用生成脚本方法
  await generateScript();

};

// 计算属性：返回可见的进度步骤
const visibleProgressSteps = computed(() => {
  return progressSteps.value.filter(step => step.visible);
});

// 计算属性：检查是否所有步骤都已完成
const allStepsCompleted = computed(() => {
  return progressSteps.value.every(step => step.completed);
});

// 组件挂载时
onMounted(async () => {
  // 初始状态下不显示生成进度
  showNewContainer.value = false;
  
  await getRoleList();

  // 初始化生成主题下拉框选项
  dropdowns.value[0].options = courseOptions.value;
  // 初始化主讲下拉框选项
  dropdowns.value[1].options = teacherOptions.value;
  // 初始化助教下拉框选项
  dropdowns.value[2].options = assistantOptions.value;
});
</script>

<style scoped lang="scss">
@use "sass:math";
// 定义rpx转换函数
@function rpx($px) {
  @return math.div($px, 750) * 100vw;
}

.self-directed-learning {
  width: 100%;
  display: flex;
  flex-direction: column;
  flex-grow: 1;
}

.title-section {
  display: flex;
  justify-content: center;
  align-items: center;

  h3 {
    font-size: rpx(12);
    color: black;
    font-weight: bold;
    letter-spacing: rpx(5);
  }
}

.input-section {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  margin-left: rpx(10);
  width: calc(100% - rpx(10));
}

.dialogue-card {
  background-color: #f1f0ff;
  border: rpx(1) solid #a7a4ed;
  border-radius: rpx(6);
  padding: rpx(8);
  max-width: 50%;
  min-width: rpx(200);
  width: auto;
  display: inline-block;
  z-index: 2;
}

.user-input-card {
  width: 93%;
  margin-left: rpx(20);
  max-width: none;
  animation: dialogueEnterCenter 0.6s ease forwards;
  box-sizing: border-box;
}

.user-input-card::before {
  display: none;
}

@keyframes dialogueEnterCenter {
  from {
    opacity: 0;
    transform: translateY(rpx(20));
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.dialogue-content {
  font-size: rpx(12);
  line-height: 1.2;
  color: #333;
  text-align: left;
  display: flex;
  flex-direction: column;
  position: relative;
  width: 100%;
}

.user-input-textarea {
  width: 100%;
  min-height: rpx(70);
  max-height: rpx(150);
  border: none;
  outline: none;
  background: transparent;
  font-size: rpx(8);
  line-height: 1.2;
  color: #333;
  resize: none;
  font-family: inherit;
  overflow-y: auto;
  text-align: left;
  padding: rpx(5) rpx(0);
}

.dropdowns-container {
  display: flex;
  gap: rpx(5);
  margin-top: rpx(5);
  align-self: flex-start;
}

.dropdowns-container .custom-select {
  width: auto;
  height: rpx(18);
  font-size: rpx(8);
  max-width: rpx(80);
}

.dropdowns-container .custom-select :deep(.el-select__wrapper) {
  background-color: #f1f0ff !important;
  border: rpx(1) solid #a7a4ed !important;
  border-radius: rpx(4) !important;
  height: rpx(18) !important;
}

.dropdowns-container .custom-select .el-select__input {
  font-size: rpx(8);
  color: black;
  height: rpx(18);
  line-height: rpx(18);
}

.dropdowns-container .custom-select .el-select__prefix {
  color: black;
}

.dropdowns-container .custom-select .el-select__caret {
  color: black;
}

/* 下拉菜单样式 */
.dropdowns-container .custom-select :deep(.el-select-dropdown) {
  min-width: rpx(50);
  width: auto;
  max-height: rpx(160);
  overflow-y: auto;
  border-radius: rpx(3);
  border: 1px white solid;
  background-color: rgb(255, 255, 255, 0.8);
  backdrop-filter: blur(rpx(5));
  // box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
}

.dropdowns-container .custom-select :deep(.el-select-dropdown::-webkit-scrollbar) {
  width: rpx(2);
}

.dropdowns-container .custom-select :deep(.el-select-dropdown::-webkit-scrollbar-track) {
  background: #f1f1f1;
  border-radius: rpx(2);
}

.dropdowns-container .custom-select :deep(.el-select-dropdown::-webkit-scrollbar-thumb) {
  background: #c1c1c1;
  border-radius: rpx(2);
}

.dropdowns-container .custom-select :deep(.el-select-dropdown::-webkit-scrollbar-thumb:hover) {
  background: #a8a8a8;
}

.dropdowns-container .custom-select :deep(.el-select-dropdown__item) {
  font-size: rpx(8) !important;
  color: black !important;
  border-radius: rpx(5) !important;
  width: auto !important;
  min-width: rpx(35) !important;
  height: rpx(20) !important;
  margin-bottom: rpx(8) !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  padding: 0 rpx(8) !important;
}

.dropdowns-container .custom-select :deep(.el-select-dropdown__item:hover),
.dropdowns-container .custom-select :deep(.el-select-dropdown__item:focus),
.dropdowns-container .custom-select :deep(.el-select-dropdown__item.is-active) {
  background: linear-gradient(
    to bottom,
    #fee78a,
    #ffce1b
  ) !important;
  border: none !important;
  outline: none !important;
  color: black !important;
}

/* 确保下拉框点击时也没有边框 */
.dropdowns-container .custom-select:focus,
.dropdowns-container .custom-select:active {
  outline: none;
  box-shadow: none;
}

/* 搜索输入框样式 */
.dropdowns-container .custom-select :deep(.el-select__input.is-focus) {
  color: black;
}

/* 下拉框清空按钮样式 */
.dropdowns-container .custom-select .el-select__clear {
  color: black;
}

/* 滚动条样式 */
.user-input-textarea::-webkit-scrollbar {
  width: rpx(0);
}

.user-input-textarea::-webkit-scrollbar-track {
  background: rgba(0, 0, 0, 0.05);
  border-radius: rpx(3);
}

.user-input-textarea::-webkit-scrollbar-thumb {
  background: rgba(64, 158, 255, 0.5);
  border-radius: rpx(3);
}

.user-input-textarea::-webkit-scrollbar-thumb:hover {
  background: rgba(64, 158, 255, 0.8);
}

.send-button {
  position: absolute;
  bottom: rpx(0);
  right: rpx(0);
  width: rpx(18);
  height: rpx(18);
  border-radius: 50%;
  background: transparent;
  color: #a7a4ed;
  border: rpx(1) solid #a7a4ed;
  font-size: rpx(2);
  font-weight: bold;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: not-allowed;
  transition: all 0.3s ease;
  outline: none;
  box-shadow: none;
  opacity: 0.6;
}

.send-button.active {
  background: linear-gradient(
    to bottom,
    #ffefb0,
    #ffcc00
  );
  color: white;
  border: none;
  cursor: pointer;
  opacity: 1;
}

.send-button:hover:not(.active) {
  border-color: #a7a4ed;
  color: #a7a4ed;
  transform: none;
  outline: none;
  box-shadow: none;
}

.send-button:hover.active {
  transform: scale(1.1);
  outline: none;
  box-shadow: 0 rpx(2) rpx(5) rgba(255, 204, 0, 0.3);
}

.send-button:active.active {
  transform: scale(0.95);
  outline: none;
  box-shadow: none;
}

.send-button:focus {
  outline: none;
  box-shadow: none;
}

.send-button span {
  display: block;
}

.new-container {
  width: 93%;
  margin-left: rpx(20);
  margin-top: rpx(10);
  display: flex;
  gap: rpx(5);
  background-color: #f1f0ff;
  border: rpx(1) solid #a7a4ed;
  border-radius: rpx(6);
  padding: rpx(2);
  max-width: none;
  align-self: flex-start;
  box-sizing: border-box;
  min-height: rpx(50);
}

.success-container {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: rpx(10);
  gap: rpx(5);
}

.success-checkmark {
  width: rpx(20);
  height: rpx(20);
  border-radius: 50%;
  background-color: #4caf50;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: rpx(12);
  font-weight: bold;
  animation: successScale 0.5s ease-out;
}

.success-text {
  font-size: rpx(10);
  color: #666;
  font-weight: bold;
  animation: successFadeIn 0.5s ease-out 0.2s both;
}

@keyframes successScale {
  0% {
    transform: scale(0);
    opacity: 0;
  }
  50% {
    transform: scale(1.2);
    opacity: 1;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

@keyframes successFadeIn {
  from {
    opacity: 0;
    transform: translateY(rpx(5));
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.left-box {
  flex: 0.5;
  // background-color: rgba(241, 240, 255, 0.8);
  backdrop-filter: blur(rpx(5));
  // border: rpx(1) solid rgba(167, 164, 237);
  border-radius: rpx(6);
  padding: rpx(2);
  min-height: rpx(50);
  display: flex;
  align-items: center;
  justify-content: center;
}

.loading-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: rpx(5);
}

.loading-spinner {
  width: rpx(12);
  height: rpx(12);
  border: rpx(2) solid rgba(167, 164, 237, 0.3);
  border-top: rpx(2) solid #a7a4ed;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

.loading-text {
  font-size: rpx(8);
  color: #666;
  animation: pulse 1.5s ease-in-out infinite;
}

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

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.6; }
}

.right-box {
  flex: 1;
  // background-color: rgba(241, 240, 255, 0.8);
  backdrop-filter: blur(rpx(5));
  // border: rpx(1) solid rgba(167, 164, 237, 0.5);
  border-radius: rpx(6);
  padding: rpx(8);
  min-height: rpx(50);
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
  text-align: left;
}

.progress-container {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: rpx(5);
}

.progress-title {
  font-size: rpx(10);
  font-weight: bold;
  color: #666;
  margin-bottom: rpx(3);
}

.progress-steps {
  display: flex;
  flex-direction: column;
  gap: rpx(2);
}

.progress-step {
  margin-bottom: rpx(5);
  opacity: 0;
  transform: translateY(rpx(5));
  animation: stepEnter 0.5s ease forwards;
}

@keyframes stepEnter {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.progress-step.active .step-text {
  color: #a7a4ed;
  font-weight: bold;
}

.step-header {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  text-align: left;
  font-size: rpx(8);
  color: #666;
  padding: rpx(1) 0;
  transition: all 0.3s ease;
  margin-bottom: rpx(2);
}

.step-text {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: color 0.3s ease;
}

.step-status {
  width: rpx(8);
  height: rpx(8);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  margin-left: rpx(10);
  transition: all 0.3s ease;
}

.step-placeholder {
  width: rpx(4);
  height: rpx(4);
  border-radius: 50%;
  background-color: rgba(167, 164, 237, 0.2);
}

.step-status.completed {
  background-color: #4caf50;
  color: white;
}

.step-status.active {
  background-color: rgba(167, 164, 237, 0.3);
}

.checkmark {
  font-size: rpx(6);
  font-weight: bold;
}

.loading-dot {
  width: rpx(4);
  height: rpx(4);
  background-color: #a7a4ed;
  border-radius: 50%;
  animation: pulse 1.5s ease-in-out infinite;
}

.step-progress {
  display: flex;
  align-items: center;
  gap: rpx(5);
  margin-left: rpx(0);
}

.progress-bar {
  flex: 1;
  height: rpx(2);
  background-color: rgba(167, 164, 237, 0.2);
  border-radius: rpx(1);
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  background-color: #a7a4ed;
  transition: width 0.3s ease;
}

.progress-text {
  font-size: rpx(6);
  color: #666;
  min-width: rpx(20);
  text-align: right;
}

@keyframes pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.6; transform: scale(1.2); }
}

</style>
