/**
 * 陪练功能状态管理
 */
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { practiceApi } from '@/api/practice'
import { ElMessage } from 'element-plus'
import { CozeVoiceClient, checkMicrophonePermission } from '@/utils/cozeVoiceClient'
import type {
  Message,
  PracticeScene,
  SSEEventType,
  SSEEventData
} from '@/types/practice'

export const usePracticeStore = defineStore('practice', () => {
  // ==================== 状态 ====================
  
  /** 当前聊天模式 */
  const chatModel = ref<string>('voice')  // 默认语音模式
  
  /** 连接状态 */
  const connectionStatus = ref<string>('unconnected')
  
  /** 当前场景 */
  const currentScene = ref<PracticeScene | null>(null)
  
  /** 对话ID（由Coze返回） */
  const conversationId = ref<string>('')
  
  /** 聊天ID（由Coze返回） */
  const chatId = ref<string>('')
  
  /** 消息列表 */
  const messageList = ref<Message[]>([])
  
  /** 加载状态 */
  const isLoading = ref<boolean>(false)
  
  /** 是否显示字幕（语音模式用，始终true） */
  const showSubtitle = ref<boolean>(true)
  
  /** 用户ID */
  const userId = ref<string>('')
  
  /** 麦克风权限 */
  const audioPermission = ref<boolean>(false)
  
  /** 是否正在录音 */
  const isRecording = ref<boolean>(false)
  
  /** 会话ID */
  const sessionId = ref<string>('')
  
  /** 对话序号 */
  const dialogueSequence = ref<number>(0)
  
  /** 会话是否活跃 */
  const isSessionActive = ref<boolean>(false)
  
  /** AbortController（用于中断对话） */
  let controller: AbortController | null = null
  
  /** Coze语音客户端 */
  let voiceClient: CozeVoiceClient | null = null
  
  // ==================== 计算属性 ====================
  
  /** 是否可以发送消息 */
  const canSend = computed(() => !isLoading.value)
  
  /** 是否是首次消息 */
  const isFirstMessage = computed(() => {
    // 只有在没有conversation_id时才是首次消息
    // 一旦有了conversation_id，后续都不是首次
    return !conversationId.value
  })
  
  // ==================== 方法 ====================
  
  /**
   * 设置当前场景
   * 
   * 支持两种模式：
   * 1. 直接模式：完整的PracticeScene对象（来自数据库）
   * 2. 课程模式：Partial场景对象（来自Dify工作流，可能没有id等字段）
   */
  const setCurrentScene = (scene: PracticeScene | Partial<PracticeScene> | any) => {
    currentScene.value = scene
    // 重置对话状态
    conversationId.value = ''
    chatId.value = ''
    messageList.value = []
    logger.info(`设置当前场景: ${scene.name}`)
  }
  
  /**
   * 发送消息（SSE流式）
   */
  const sendMessage = async (userMessage: string) => {
    if (isLoading.value || !userMessage.trim()) {
      return
    }
    
    if (!currentScene.value && isFirstMessage.value) {
      ElMessage.error('请先选择陪练场景')
      return
    }
    
    // 添加用户消息到列表（仅显示用户输入，不显示场景信息）
    const userMsg: Message = {
      id: generateMessageId(),
      role: 'user',
      content: userMessage.trim(),
      timestamp: Date.now()
    }
    messageList.value.push(userMsg)
    
    // 添加AI消息占位
    const aiMsg: Message = {
      id: generateMessageId(),
      role: 'assistant',
      content: '',
      timestamp: Date.now(),
      loading: true
    }
    messageList.value.push(aiMsg)
    
    isLoading.value = true
    controller = new AbortController()
    
    try {
      // 保存当前是否首次消息的状态（在创建conversation之前判断）
      const isFirst = isFirstMessage.value
      
      // ⚠️ 关键：如果是首次消息，先创建conversation
      if (isFirst) {
        try {
          // http拦截器返回的是 {code: 200, message: "...", data: {...}}
          const result: any = await practiceApi.createConversation()
          
          if (result.code === 200 && result.data?.conversation_id) {
            conversationId.value = result.data.conversation_id
            logger.info(`✅ Conversation已创建: ${conversationId.value}`)
          } else {
            throw new Error(result.message || '创建对话失败')
          }
        } catch (error: any) {
          console.error('创建对话失败:', error)
          ElMessage.error(error.message || '创建对话失败，请重试')
          aiMsg.loading = false
          isLoading.value = false
          return
        }
      }
      
      // 构建请求参数
      const params: any = {
        user_message: userMessage,
        conversation_id: conversationId.value,
        is_first: isFirst
      }
      
      // ⚠️ 关键：首次消息时添加完整场景信息
      if (isFirst && currentScene.value) {
        Object.assign(params, {
          scene_id: currentScene.value.id,  // 课程模式可能为undefined，后端会兼容
          scene_name: currentScene.value.name,
          scene_description: currentScene.value.description,
          scene_background: currentScene.value.background,
          scene_ai_role: currentScene.value.ai_role,
          scene_objectives: currentScene.value.objectives,
          scene_keywords: currentScene.value.keywords || []
        })
        logger.info(`首次消息，发送场景信息: ${currentScene.value.name}`)
      } else {
        logger.info(`后续消息，conversation_id=${conversationId.value}`)
      }
      
      // 发起SSE请求
      const stream = await practiceApi.startPractice(params)
      
      // 处理SSE流
      await processSSEStream(stream, aiMsg)
      
    } catch (error: any) {
      if (error.name === 'AbortError') {
        aiMsg.content = '会话已中断。'
        logger.info('用户主动中断会话')
      } else {
        console.error('对话错误:', error)
        aiMsg.content = '抱歉，请求出错了，请重试。'
        ElMessage.error('对话失败')
      }
      aiMsg.loading = false
    } finally {
      isLoading.value = false
      controller = null
    }
  }
  
  /**
   * 处理SSE流
   */
  const processSSEStream = async (stream: ReadableStream, aiMessage: Message) => {
    const reader = stream.getReader()
    const decoder = new TextDecoder()
    
    while (true) {
      const { value, done } = await reader.read()
      if (done) break
      
      const chunk = decoder.decode(value)
      const lines = chunk.split('\n\n')
      
      for (const line of lines) {
        if (!line.trim() || !line.startsWith('event: ')) continue
        
        const [eventLine, dataLine] = line.split('\n')
        if (!dataLine) continue
        
        const event = eventLine.replace('event: ', '').trim() as SSEEventType
        const dataStr = dataLine.replace('data: ', '').trim()
        
        // 跳过结束标记
        if (dataStr === '[DONE]') {
          logger.info('SSE流结束')
          continue
        }
        
        try {
          const data: SSEEventData = JSON.parse(dataStr)
          handleSSEEvent(event, data, aiMessage)
        } catch (e) {
          console.error('解析SSE数据失败:', e, dataStr)
        }
      }
    }
  }
  
  /**
   * 处理SSE事件
   */
  const handleSSEEvent = (event: SSEEventType, data: SSEEventData, aiMessage: Message) => {
    switch (event) {
      case 'conversation.chat.created':
        // 保存对话ID和聊天ID
        if (data.conversation_id) {
          conversationId.value = data.conversation_id
        }
        if (data.chat_id) {
          chatId.value = data.chat_id
        }
        logger.info(`对话创建: conversation_id=${data.conversation_id}, chat_id=${data.chat_id}`)
        break
      
      case 'message.delta':
        // 消息增量（实时打字效果）
        if (data.content) {
          aiMessage.content += data.content
        }
        break
      
      case 'message.completed':
        // 消息完成
        aiMessage.loading = false
        logger.info(`消息完成，内容长度=${aiMessage.content.length}`)
        break
      
      case 'conversation.completed':
        // 对话完成
        aiMessage.loading = false
        logger.info(`对话完成，Token用量=${data.token_count}`)
        break
      
      case 'error':
        // 错误事件
        aiMessage.content = data.error || '对话失败，请重试'
        aiMessage.loading = false
        ElMessage.error(data.error || '对话失败')
        logger.error(`对话错误: ${data.error}`)
        break
    }
  }
  
  /**
   * 中断对话
   */
  const abortChat = async () => {
    // 中断HTTP请求
    if (controller) {
      controller.abort()
      logger.info('已中断HTTP请求')
    }
    
    // 调用后端中断API
    if (chatId.value && conversationId.value) {
      try {
        await practiceApi.interruptPractice({
          chat_id: chatId.value,
          conversation_id: conversationId.value
        })
        logger.info('对话已中断')
      } catch (error) {
        console.error('中断对话失败:', error)
      }
    }
  }
  
  /**
   * 重置对话状态
   */
  const resetChat = () => {
    conversationId.value = ''
    chatId.value = ''
    messageList.value = []
    isLoading.value = false
    logger.info('对话状态已重置')
  }
  
  /**
   * 切换聊天模式
   */
  const setChatModel = (model: string) => {
    chatModel.value = model
    logger.info(`切换聊天模式: ${model}`)
    
    // 如果切换到语音模式，自动连接
    if (model === 'voice' && currentScene.value) {
      connectVoice()
    }
    // 如果切换到文本模式，断开语音连接
    else if (model === 'text' && voiceClient) {
      disconnectVoice()
    }
  }
  
  /**
   * 连接语音对话（使用@coze/api直连Coze）
   */
  const connectVoice = async () => {
    try {
      if (!currentScene.value) {
        ElMessage.error('请先选择陪练场景')
        return
      }
      
      // ⚠️ 防止重复连接
      if (voiceClient && voiceClient.isConnected()) {
        logger.info('语音连接已存在，跳过重复连接')
        return
      }
      
      connectionStatus.value = 'checking_permission'
      
      // 检查麦克风权限
      const hasPermission = await checkMicrophonePermission()
      if (!hasPermission) {
        ElMessage.error('需要麦克风权限才能使用语音陪练')
        audioPermission.value = false
        connectionStatus.value = 'error'
        return
      }
      
      audioPermission.value = true
      connectionStatus.value = 'connecting'
      
      // 创建Coze语音客户端
      voiceClient = new CozeVoiceClient()
      
      // 注册事件处理器
      voiceClient.on('connected', handleConnected)
      voiceClient.on('disconnected', handleDisconnected)
      voiceClient.on('user_transcript', handleUserTranscript)
      voiceClient.on('ai_message_delta', handleAIMessageDelta)
      voiceClient.on('ai_speaking', handleAISpeaking)
      voiceClient.on('ai_speech_end', handleAISpeechEnd)
      voiceClient.on('error', handleVoiceError)
      
      // 构建场景提示词
      const scenePrompt = buildVoiceScenePrompt(currentScene.value)
      
      // 从后端获取Coze OAuth Token
      let token: string
      try {
        const tokenRes: any = await practiceApi.getCozeToken()
        if (tokenRes.code === 200 && tokenRes.data.token) {
          token = tokenRes.data.token
          logger.info('✅ 已从后端获取OAuth Token')
        } else {
          throw new Error('Token获取失败')
        }
      } catch (error) {
        logger.error(`获取Token失败: ${error}`)
        throw new Error('无法获取认证Token，请重试')
      }
      
      const botId = import.meta.env.VITE_COZE_PRACTICE_BOT_ID || '7560643598174683145'
      
      await voiceClient.connect({
        token: token,
        botId: botId,
        userId: `trainee_${Date.now()}`,
        scenePrompt: scenePrompt,  // 首次连接发送场景设定
        conversationId: conversationId.value || undefined
      })
      
      logger.info('Coze语音连接成功（直连）')
      isRecording.value = true
      connectionStatus.value = 'listening'
      
      // ⚠️ 创建会话记录
      await startSession()
      
      ElMessage.success('语音连接成功，开始对话吧！')
    } catch (error: any) {
      logger.error(`语音连接失败: ${error}`)
      ElMessage.error(`语音连接失败: ${error.message || '未知错误'}`)
      connectionStatus.value = 'error'
    }
  }
  
  /**
   * 断开语音连接
   */
  const disconnectVoice = async () => {
    if (voiceClient) {
      await voiceClient.disconnect()
      voiceClient = null
    }
    
    isRecording.value = false
    connectionStatus.value = 'disconnected'
    logger.info('语音连接已断开')
  }
  
  /**
   * 打断AI回复
   */
  const interruptAI = () => {
    if (voiceClient) {
      voiceClient.interrupt()
      logger.info('已打断AI回复')
    }
  }
  
  // ==================== 语音事件处理器 ====================
  
  /**
   * 连接成功
   */
  const handleConnected = () => {
    connectionStatus.value = 'listening'
    logger.info('Coze WebSocket连接成功')
  }
  
  /**
   * 断开连接
   */
  const handleDisconnected = () => {
    connectionStatus.value = 'disconnected'
    logger.info('Coze WebSocket已断开')
  }
  
  /**
   * 用户语音转文字
   */
  const handleUserTranscript = async (data: any) => {
    messageList.value.push({
      id: generateMessageId(),
      role: 'user',
      content: data.content,
      timestamp: Date.now(),
      loading: false
    })
    
    logger.info(`用户说: ${data.content}`)
    
    // ⚠️ 保存到数据库
    await saveDialogue('user', data.content)
  }
  
  /**
   * AI文字回复增量（字幕）
   */
  const handleAIMessageDelta = (data: any) => {
    if (data.isFirst) {
      // 创建新的AI消息
      messageList.value.push({
        id: generateMessageId(),
        role: 'assistant',
        content: data.content,
        timestamp: Date.now(),
        loading: true
      })
    } else {
      // 更新最后一条AI消息
      const lastMsg = messageList.value[messageList.value.length - 1]
      if (lastMsg && lastMsg.role === 'assistant') {
        lastMsg.content = data.fullContent
      }
    }
  }
  
  /**
   * AI正在说话
   */
  const handleAISpeaking = () => {
    connectionStatus.value = 'speaking'
  }
  
  /**
   * AI说话结束
   */
  const handleAISpeechEnd = async () => {
    // 标记最后一条AI消息为完成
    const lastMsg = messageList.value[messageList.value.length - 1]
    if (lastMsg && lastMsg.role === 'assistant') {
      lastMsg.loading = false
      
      // ⚠️ 保存到数据库
      if (lastMsg.content) {
        await saveDialogue('ai', lastMsg.content)
      }
    }
    
    connectionStatus.value = 'listening'
  }
  
  /**
   * 错误处理
   */
  const handleVoiceError = (data: any) => {
    ElMessage.error(data.error || '语音对话错误')
    connectionStatus.value = 'error'
    logger.error(`语音错误: ${data.error}`)
  }
  
  // ==================== 会话管理方法 ====================
  
  /**
   * 开始会话
   */
  const startSession = async () => {
    if (!currentScene.value) {
      logger.error('无法创建会话：场景信息不存在')
      return
    }
    
    try {
      logger.info(`创建会话: scene_name=${currentScene.value.name}, scene_id=${currentScene.value.id}`)
      
      // http拦截器已经返回ResponseModel，不需要再取.data
      const result: any = await practiceApi.createSession({
        scene_id: currentScene.value.id || undefined,  // 兼容null值
        scene_name: currentScene.value.name,
        scene_type: currentScene.value.type || undefined,
        conversation_id: conversationId.value || undefined
      })
      
      if (result.code === 200 && result.data) {
        sessionId.value = result.data.session_id
        dialogueSequence.value = 0
        isSessionActive.value = true
        logger.info(`✅ 会话已创建: ${sessionId.value}`)
      } else {
        logger.error(`创建会话失败: ${result.message || '未知错误'}`)
        // 即使会话创建失败，也生成一个临时session_id以便保存对话
        sessionId.value = `PS_TEMP_${Date.now()}`
        isSessionActive.value = true
        logger.info(`⚠️ 使用临时会话ID: ${sessionId.value}`)
      }
    } catch (error: any) {
      logger.error(`创建会话异常: ${error.message || error}`)
      console.error('创建会话完整错误:', error)
      // 容错处理：即使API失败，也生成临时session_id
      sessionId.value = `PS_TEMP_${Date.now()}`
      isSessionActive.value = true
      logger.info(`⚠️ 使用临时会话ID: ${sessionId.value}`)
    }
  }
  
  /**
   * 保存对话
   */
  const saveDialogue = async (speaker: string, content: string) => {
    if (!sessionId.value || !isSessionActive.value || !content.trim()) return
    
    try {
      dialogueSequence.value++
      
      await practiceApi.saveDialogue({
        session_id: sessionId.value,
        speaker: speaker,
        content: content,
        sequence: dialogueSequence.value
      })
      
      logger.info(`💾 对话已保存: ${speaker}, seq=${dialogueSequence.value}`)
    } catch (error: any) {
      logger.error(`保存对话失败: ${error.message || error}`)
      // 保存失败不影响对话继续，只记录日志
    }
  }
  
  /**
   * 结束会话并生成分析报告
   */
  const endSessionAndAnalyze = async () => {
    if (!sessionId.value) {
      ElMessage.error('会话不存在')
      return
    }
    
    // 检查是否是临时session_id
    if (sessionId.value.startsWith('PS_TEMP_')) {
      ElMessage.error('会话创建失败，无法生成分析报告。请重新开始陪练。')
      logger.error('无法分析临时会话')
      return
    }
    
    try {
      // 1. 结束会话
      await practiceApi.endSession(sessionId.value)
      logger.info('✅ 会话已结束')
      
      // 2. 生成分析报告（调用Dify，可能需要30-60秒）
      ElMessage({
        message: '正在生成分析报告，请稍候...',
        type: 'info',
        duration: 0,  // 不自动关闭
        showClose: true
      })
      
      // http拦截器已经返回ResponseModel
      const result: any = await practiceApi.analyzePractice(sessionId.value)
      
      if (result.code === 200) {
        ElMessage.closeAll()
        ElMessage.success('分析报告生成成功！')
        
        // 3. 跳转到报告页面
        // ⚠️ 路由是History模式（不是Hash模式），URL中没有#号
        window.location.href = `/trainee/practice-report/${sessionId.value}`
        logger.info(`✅ 跳转到报告页面: /trainee/practice-report/${sessionId.value}`)
        
        // 4. 重置会话状态
        isSessionActive.value = false
      }
    } catch (error: any) {
      ElMessage.closeAll()
      
      // 获取详细错误信息
      const errorMsg = error.message || error.toString()
      logger.error(`生成报告失败: ${errorMsg}`)
      ElMessage.error(`生成报告失败: ${errorMsg}`)
      
      console.error('完整错误对象:', error)
    }
  }
  
  /**
   * 构建语音场景提示词
   */
  const buildVoiceScenePrompt = (scene: PracticeScene): string => {
    const objectivesText = scene.objectives.map((obj, i) => `${i + 1}. ${obj}`).join('\n')
    const keywordsText = scene.keywords ? scene.keywords.join(', ') : ''
    
    return `# 语音陪练场景设定

## 场景名称
${scene.name}

## 场景描述
${scene.description || ''}

## 场景背景
${scene.background}

## AI角色要求
${scene.ai_role}

⚠️ 重要：这是语音对话模式，请注意：
- 你的回复将通过语音播放，语气要自然、口语化
- 避免过长的句子，适当断句
- 可以使用语气词（嗯、啊、哦、好的等）增强真实感
- 模拟真实对话的停顿和节奏
- 避免使用复杂的书面语表达
- 适当加入情绪表达（如语气、语调的描述）

## 练习目标
${objectivesText}

## 关键词
${keywordsText}

---

现在开始语音陪练对话。请你严格按照上述场景设定扮演角色，与学员进行实战对话练习。
不要提及"场景设定"或"角色扮演"等元信息，直接进入角色开始对话。
记住：你在进行语音对话，回复要口语化、自然化。
`
  }
  
  // ==================== 辅助函数 ====================
  
  /**
   * 生成消息ID
   */
  const generateMessageId = (): string => {
    return `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
  }
  
  /**
   * 简单日志对象
   */
  const logger = {
    info: (msg: string) => console.log(`[PracticeStore] ${msg}`),
    error: (msg: string) => console.error(`[PracticeStore] ${msg}`)
  }
  
  // ==================== 返回 ====================
  
  return {
    // 状态
    chatModel,
    connectionStatus,
    currentScene,
    conversationId,
    chatId,
    messageList,
    isLoading,
    showSubtitle,
    userId,
    audioPermission,
    isRecording,
    sessionId,
    dialogueSequence,
    isSessionActive,
    
    // 计算属性
    canSend,
    isFirstMessage,
    
    // 文本模式方法
    setCurrentScene,
    sendMessage,
    abortChat,
    resetChat,
    setChatModel,
    
    // 语音模式方法
    connectVoice,
    disconnectVoice,
    interruptAI,
    
    // 会话管理方法
    startSession,
    saveDialogue,
    endSessionAndAnalyze
  }
})

