import { makeAutoObservable, runInAction } from "mobx"
import {
  getBotInfo,
  createConversation,
  startChatStream,
  deleteConversation,
  interruptChat,
} from "@/server/api"
import { XStream } from "@ant-design/x"
import { uid } from "uid"
import { BubbleListRef } from "@ant-design/x/es/bubble/BubbleList"
import { createRef } from "react"
import {
  ClientEventType,
  WsChatClient,
  WsChatEventNames,
  WsToolsUtils,
  type WsChatEventData,
} from "@coze/api/ws-tools"
import {
  type ConversationAudioTranscriptCompletedEvent,
  WebsocketsEventType,
  BotInfo,
} from "@coze/api"
import { config } from "@/stores/config"
import { message } from "antd"
import { getApiUrl } from "@/utils/tools"

interface IBotInfo extends BotInfo {
  name: string
  description: string
  suggestedQuestions: string[]
}
export enum EChatModel {
  VOICE,
  TEXT,
}
export enum EStatus {
  unconnected = "未连接",
  connecting = "连接中...",
  connected = "已连接",
  disconnected = "已断开连接",
  error = "连接错误",
  waiting = "等待ai回复",
  listening = "正在聆听",
}
class TrainingStore {
  chatModel = EChatModel.VOICE
  botInfo: IBotInfo | null = null
  conversationID = ""
  isLoading = false
  messageList: any[] = []
  chatId = ""
  controller: AbortController | null = null
  uploading = false
  fileArr: any[] = []
  containerRef = createRef<BubbleListRef>()
  clientRef = createRef<WsChatClient>()
  status: EStatus = EStatus.unconnected
  isFirstDelta = true
  shwMessageList = true
  tempContent = ""
  userId = ""
  constructor() {
    makeAutoObservable(this, { isFirstDelta: false, tempContent: false }) // 自动将字段和方法转为响应式
  }

  setChatModel = async (model: EChatModel) => {
    if (model === EChatModel.VOICE) {
      this.handleConnect()
    }
    this.chatModel = model
  }

  setShowContent = () => {
    this.shwMessageList = !this.shwMessageList
  }

  initClient = async () => {
    const permission = await WsToolsUtils.checkDevicePermission()
    if (!permission.audio) {
      throw new Error("需要麦克风访问权限")
    }
    if (!config.getPat()) {
      await this.getBotToken()
    }
    
    // 确保token已获取
    const token = config.getPat()
    if (!token) {
      throw new Error("无法获取Token")
    }
    
    const client = new WsChatClient({
      token: token, // 直接使用token，不加Bearer前缀
      baseWsURL: config.getBaseWsUrl(),
      allowPersonalAccessTokenInBrowser: true, // 浏览器环境下必须设置为true才能使用PAT
      botId: config.getBotId(),
      debug: true, // 启用调试模式
    })
    
    console.log("WebSocket配置:", {
      token: `${token.substring(0, 10)}...`,
      baseWsURL: config.getBaseWsUrl(),
      botId: config.getBotId(),
    })

    // 监听连接事件
    client.on(WsChatEventNames.CONNECTED, () => {
      console.log("[chat] WebSocket connected")
      runInAction(() => {
        this.status = EStatus.connected
      })
    })

    // 监听断开连接事件  
    client.on(WsChatEventNames.DISCONNECTED, () => {
      console.log("[chat] WebSocket disconnected")
      runInAction(() => {
        this.status = EStatus.disconnected
      })
    })

    // 监听服务器错误事件
    client.on(WsChatEventNames.SERVER_ERROR, (_: string, event: unknown) => {
      console.error("[chat] server error", event)
      client.disconnect()
      this.clientRef.current = null
      runInAction(() => {
        this.status = EStatus.error
      })
    })

    // 监听所有消息事件
    client.on(WsChatEventNames.ALL, this.handleMessageEvent)
    this.clientRef.current = client
  }

  handleMessageEvent = (eventName: string, event: WsChatEventData) => {
    if (eventName === WsChatEventNames.CONNECTED) {
      this.messageList = []
      return
    }
    if (!event) {
      return
    }
    switch (event.event_type) {
      case WebsocketsEventType.CONVERSATION_AUDIO_TRANSCRIPT_COMPLETED: {
        const { content } = (event as ConversationAudioTranscriptCompletedEvent)
          .data
        runInAction(() => {
          this.messageList.unshift({
            id: uid(32),
            role: "user",
            content,
          })
        })
        break
      }
      case WebsocketsEventType.CONVERSATION_MESSAGE_DELTA:
        if (event.data.content) {
          const content = this.tempContent + event.data.content
          runInAction(() => {
            this.tempContent = content
          })
          if (this.isFirstDelta) {
            // 第一次增量，创建新消息
            runInAction(() => {
              this.messageList.unshift({
                id: uid(32),
                role: "assistant",
                content: event.data.content,
              })
              this.isFirstDelta = false
            })
          } else {
            this.updateMessageContent(content)
          }
        }
        break
      case WebsocketsEventType.CONVERSATION_MESSAGE_COMPLETED: {
        // 收到完成事件，重置标记，下一次将创建新消息
        runInAction(() => {
          this.isFirstDelta = true
          this.tempContent = ""
        })
        break
      }
      case WebsocketsEventType.CONVERSATION_AUDIO_DELTA: {
        runInAction(() => {
          this.status = EStatus.waiting
        })
        break
      }
      case ClientEventType.AUDIO_SENTENCE_PLAYBACK_ENDED: {
        runInAction(() => {
          this.status = EStatus.listening
        })
        break
      }
      default:
        break
    }
  }

  handleInterrupt = () => {
    try {
      this.clientRef.current?.interrupt()
    } catch (error) {
      message.error(`打断失败：${error}`)
    }
  }

  handleConnect = async () => {
    try {
      this.status = EStatus.connecting
      if (!this.clientRef.current) {
        await this.initClient()
      }
      await this.clientRef.current?.connect()
      runInAction(() => {
        this.status = EStatus.connected
      })
      // 设置初始音量
      if (this.clientRef.current) {
        this.clientRef.current.setPlaybackVolume(1)
      }
    } catch (error) {
      this.getBotToken()
      console.error(`连接错误：${(error as Error).message}`)
      this.status = EStatus.error
    }
  }

  handleDisconnect = async () => {
    try {
      await this.clientRef.current?.disconnect()
      this.clientRef.current = null
      runInAction(() => {
        this.status = EStatus.disconnected
      })
    } catch (error) {
      message.error(`断开失败：${error}`)
    }
  }

  getBotToken = async () => {
    try {
      // 仅用于本地开发：后端返回 PAT（请求后端端口）
      const url = `${getApiUrl()}/agent/v1/cozechat/get-token?modelEnum=CONSULTANT_PRACTICE`
      const resp = await fetch(url)
      if (!resp.ok) {
        throw new Error(`HTTP ${resp.status}`)
      }
      const data = await resp.json()
      if (data && data.code === 10000 && data.data) {
        localStorage.setItem("chat-x_pat", data.data)
        console.log("[chat] Token获取成功")
      } else {
        console.error("[chat] Token获取失败，响应数据:", data)
      }
    } catch (error) {
      console.error("[chat] Token获取请求失败:", error)
    }
  }

  getBotInfo = async () => {
    // 使用咨询师陪练的 bot_id，与后端配置保持一致
    const botId = "7509379008556089379"
    const res = await getBotInfo(botId)
    runInAction(() => {
      if (res.code === 10000) {
        this.userId = uid(32)
        document.title = res.data.bot.name
        this.botInfo = {
          ...res.data.bot,
          suggestedQuestions:
            res.data.bot.onboarding_info?.suggested_questions || [],
        }
        this.messageList = [
          {
            id: uid(32),
            content: res.data.bot.onboarding_info?.prologue || "你好，我是你的AI助手，有什么可以帮助你的吗？",
            role: "assistant",
            prologue: "true",
          },
        ]
      }
    })
  }

  streamingChat = (query: string) => {
    if (this.isLoading) {
      return
    }
    runInAction(() => {
      this.messageList.unshift({
        id: uid(32),
        role: "user",
        content: query,
        file_url: this.fileArr,
      })
      this.messageList.unshift({
        id: uid(32),
        role: "assistant",
        content: "",
        loading: true,
        is_answer: 1,
      })
    })
    this.creatChat(query)
  }
  // 创建一个辅助函数来更新消息内容
  updateMessageContent = (content: string) => {
    runInAction(() => {
      this.messageList[0] = {
        ...this.messageList[0],
        content: content,
        loading: false,
      }
    })
  }

  creatChat = async (query: string, id?: string) => {
    this.controller = new AbortController()
    const fileIds = this.fileArr.map((item) => item.id)
    try {
      runInAction(() => {
        this.isLoading = true
        this.fileArr = []
      })
      
      // 如果没有对话ID，先创建对话
      if (!this.conversationID) {
        const conversationRes = await createConversation({ bot_id: "7509379008556089379" })
        if (conversationRes.code === 10000) {
          this.conversationID = conversationRes.data.id
        }
      }
      
      const historyMessages = this.messageList
        .filter((val) => val.content !== "" && !val.prologue)
        .map((item) => {
          return {
            role: item.role,
            content: item.content,
            file_ids:
              item.file_url && item.file_url.length
                ? item.file_url.map((item: any) => item.id)
                : [],
          }
        })
      const response = await startChatStream(
        {
          conversation_id: this.conversationID,
          content: query,
          bot_id: "7509379008556089379",
          file_ids: fileIds,
          user_id: this.userId,
          history_messages: historyMessages,
        },
        this.controller.signal
      )
      let currentContent = ""
      let chatId = ""
      for await (const part of XStream({
        readableStream: response,
      })) {
        if (this.controller?.signal.aborted) {
          // Check if aborted during iteration
          break
        }
        if (typeof part === "string") {
          continue
        }
        // 去除事件名称前后的空格
        const eventName = part.event?.trim() || ""
        if (
          eventName === "conversation.chat.created" ||
          eventName === "conversation.message.delta" ||
          eventName === "conversation.message.completed"
        ) {
          part.data = JSON.parse(part.data)
        }
        console.log("🔄 SSE Event received:", `"${part.event}"`, "->", `"${eventName}"`, part.data)
        runInAction(() => {
          if (eventName === "conversation.chat.created") {
            this.conversationID = part.data.conversation_id
          } else if (eventName === "conversation.message.delta") {
            currentContent += part.data.content
            chatId = part.data.chat_id
            this.updateMessageContent(currentContent)
            if (chatId && this.chatId !== chatId) {
              this.chatId = chatId
            }
          }
          if (
            eventName === "conversation.chat.failed" ||
            eventName === "error"
          ) {
            if (this.messageList[0].role === "assistant") {
              // 如果内容为空，添加错误消息
              if (!this.messageList[0].content) {
                this.messageList[0].content = "抱歉，请求出错了，请重试。"
              }
              this.messageList[0] = {
                ...this.messageList[0],
                loading: false,
              }
            }
          }
        })
      }
    } catch (error) {
      if ((error as Error).name === "CanceledError") {
        runInAction(() => {
          if (this.messageList[0].role === "assistant") {
            // 如果内容为空，添加错误消息
            if (!this.messageList[0].content) {
              this.messageList[0].content = "会话已中断。"
            }
            this.messageList[0] = {
              ...this.messageList[0],
              loading: false,
            }
          }
        })
      } else {
        console.error("Error during chat stream:", error)
        // 在错误情况下更新UI状态
        runInAction(() => {
          if (this.messageList[0].role === "assistant") {
            // 如果内容为空，添加错误消息
            if (!this.messageList[0].content) {
              this.messageList[0].content = "抱歉，请求出错了，请重试。"
            }
            this.messageList[0] = {
              ...this.messageList[0],
              loading: false,
            }
          }
        })
      }
    } finally {
      this.complateChat()
      this.controller = null
    }
  }

  abortChat = async () => {
    if (this.chatId && this.conversationID) {
      await interruptChat({
        chat_id: this.chatId,
        conversation_id: this.conversationID,
      })
    }
    this.controller?.abort()
    this.complateChat()
  }

  complateChat = () => {
    runInAction(() => {
      this.isLoading = false
      if (this.messageList[0] && this.messageList[0].is_answer) {
        this.messageList[0] = {
          ...this.messageList[0],
          is_answer: 0,
        }
      }
    })
  }

  deleteMessage = async (id: string) => {
    // 暂时简化消息删除功能
    runInAction(() => {
      if (this.messageList.length > 0) {
        this.messageList = this.messageList.filter((item) => item.id !== id)
      }
    })
  }

  reGenerate = () => {
    const content = this.messageList[1]?.content
    const chatId = this.chatId || this.messageList[0]?.chat_id
    this.messageList[0] = {
      id: uid(32),
      role: "assistant",
      content: "",
      loading: true,
      is_answer: 1,
    }
    this.creatChat(content, chatId)
  }

  getBase64(img: any, callback: any) {
    const reader = new FileReader()
    reader.addEventListener("load", () => callback(reader.result))
    reader.readAsDataURL(img)
  }

  onRemoveFile = (fileId: string) => {
    const fileList = this.fileArr.filter((file: any) => file.id !== fileId)
    this.fileArr = fileList
  }

  handleUploadFile = async (file?: any) => {
    if (!file) {
      this.fileArr = []
      return
    }
    // 暂时简化文件上传功能
    this.uploading = false
  }

  scrollToBottom = () => {
    requestAnimationFrame(() => {
      this.containerRef.current?.scrollTo({
        offset: this.containerRef.current?.nativeElement.scrollHeight + 100,
        block: "nearest",
        behavior: "smooth",
      })
    })
  }
}
export default new TrainingStore()
