<template>
  <div>
    <div class="chat-container" v-if="loading">
      <!-- 对话展示区域 -->
      <div class="chat-content" ref="chatContent">
        <div
          v-for="(message, index) in messages"
          :key="index"
          :class="['chat-message', message.type]"
        >
          <span class="chat-avatar">{{ message.type === 'user' ? '👤' : '🤖' }}</span>
          <div class="chat-text-wrapper">
            <div
              class="chat-text markdown-body"
              v-if="message.text"
              v-html="renderMarkdown(message.text)"
            ></div>
            <div class="chat-text" v-else-if="message.state === 'loading'">
              <a-spin :spinning="true"/>
            </div>
            <a-button
              v-if="message.sourceInfo"
              type="link"
              class="source-info-btn"
              @click="showSourceInfo(message.sourceInfo)"
            >
              查看源信息
            </a-button>
          </div>
        </div>
      </div>

      <!-- 输入框和发送按钮 -->
      <div class="chat-input-wrapper">
        <div class="chat-input">
          <a-input
            v-model="inputMessage"
            placeholder="Type your message..."
            @pressEnter="sendMessage"
          />
          <a-button type="primary" @click="sendMessage">发送</a-button>
        </div>
      </div>
    </div>
    <a-spin :spinning="!loading"/>

    <!-- 源信息弹窗 -->
    <a-modal
      v-model="sourceInfoVisible"
      title="源信息"
      :footer="null"
      width="600px"
    >
      <div class="source-info-content markdown-body" v-html="renderMarkdown(currentSourceInfo)"></div>
    </a-modal>
  </div>
</template>

<script>
import { runLogic } from '@vue2-client/services/api/common'
import { postByServiceName, startEventStreamPOST } from '@vue2-client/services/api/restTools'
import moment from 'moment/moment'
import { marked } from 'marked'

export default {
  inject: {
    getSelectedId: {
      default: () => () => {
        console.warn('getSelectedId is not provided.')
        return null
      },
    },
    setGlobalData: {
      default: () => () => {
        console.warn('setGlobalData is not provided.')
        return null
      },
    },
    getGlobalData: {
      default: () => () => {
        console.warn('getGlobalData is not provided.')
        return null
      },
    },
    getSelectedData: {
      default: () => () => {
        console.warn('getSelectedData is not provided.')
        return null
      },
    },
    getMixinData: {
      default: () => () => {
        console.warn('getMixinData is not provided.')
        return {}
      },
    },
    getOutEnv: {
      default: () => () => {
        console.warn('getOutEnv is not provided.')
        return {}
      },
    },
    currUser: {
      default: () => () => {
        console.warn('currUser is not provided.')
        return {}
      },
    }
  },
  name: 'XConversation',
  props: {
    prompt: {
      type: String,
      default: undefined
    }
  },
  data () {
    return {
      serviceName: undefined,
      // 组件加载状态
      loading: false,
      // 配置内容
      renderConfig: {
        // 请求logic 名称
        logicName: '',
        // 请求api 地址
        api: '',
        // 请求流式api 地址
        streamApi: '',
        // 聊天室id 当type为AI 时必传
        chatId: '',
        // ai 模型 当type为AI 时必传
        aiModel: '',
        type: ''
      },
      // 用户输入的内容
      inputMessage: '',
      additionalInfo: {},
      stopConnection: undefined,
      messages: [ // 消息列表
        { type: 'bot', text: '你好! 今天有什么能帮到您的?' },
      ],
      sourceInfoVisible: false,
      currentSourceInfo: '',
    }
  },
  methods: {
    renderMarkdown (text) {
      if (!text) return ''

      // 预处理文本，处理特殊字符
      const processedText = text

      try {
        // 配置 marked 选项
        marked.setOptions({
          breaks: true, // 支持换行符
          gfm: true, // 启用 GitHub 风格的 Markdown
          headerIds: false, // 禁用标题 ID
          mangle: false, // 禁用标题 ID 混淆
          sanitize: false // 允许 HTML 标签
        })
        const rendered = marked(processedText)
        this.scrollToBottom()
        return rendered
      } catch (error) {
        console.error('Markdown 渲染错误:', error)
        return processedText
      }
    },
    setAddtionalInfo (params) {
      this.additionalInfo = params
    },
    init (params) {
      this.renderConfig = params
      this.loading = true
      this.serviceName = params.serviceName || process.env.VUE_APP_SERVICE_NAME
    },
    scrollToBottom () {
      this.$nextTick(() => {
        const chatContent = this.$refs.chatContent
        if (chatContent) {
          chatContent.scrollTop = chatContent.scrollHeight
        }
      })
    },
    async sendMessage () {
      if (this.renderConfig.type === 'AI') {
        // 验证 chatId 和 aiModel
        if (!this.renderConfig.chatId || !this.renderConfig.aiModel) {
          this.$message.error('chatId 和 aiModel 不能为空,请检查调用逻辑')
          return
        }
      }
      if (!this.inputMessage.trim()) return

      // 添加用户消息
      this.messages.push({ type: 'user', text: this.inputMessage })
      this.scrollToBottom()

      // 清空输入框
      const userMessage = this.inputMessage
      this.inputMessage = ''

      // 通过logic获取消息
      if (this.renderConfig.logicName) {
        const response = await runLogic(this.renderConfig.logicName, {
          question: userMessage,
          additionalInfo: this.additionalInfo
        }, this.serviceName)

        // 遍历并保存 additionalInfo
        console.log(response)
        if (response.additionalInfo) {
          Object.entries(response.additionalInfo).forEach(([key, value]) => {
            // 如果值是字符串类型，尝试转换为数字
            if (typeof value === 'string' && !isNaN(value)) {
              const numberValue = Number(value)
              // 检查转换后的值是否是有限数字
              if (isFinite(numberValue)) {
                this.additionalInfo[key] = numberValue
              } else {
                this.additionalInfo[key] = value
              }
            } else {
              this.additionalInfo[key] = value
            }
          })
        }
        console.log(this.additionalInfo)
        if (typeof response.value === 'string') {
          try {
            response.value = JSON.parse(response.value)
          } catch (e) {
            console.error('JSON解析失败:', e)
          }
        }
        console.log(response.value)
        this.messages.push({
          type: 'bot',
          text: response.value,
          sourceInfo: response.sourceInfo || ''
        })
      } else if (this.renderConfig.api) {
        // 通过api获取消息
        this.messages.push({ type: 'bot', state: 'loading', sourceInfo: '' })
        this.messages[this.messages.length - 1].text = await postByServiceName(this.renderConfig.api, {
          userMessage,
          additionalInfo: this.additionalInfo,
          model: this.renderConfig.aiModel,
          chatId: this.renderConfig.chatId || moment().format('YYYYMMDDHHmmss'),
          prompt: this.prompt
        }, this.serviceName)
        this.$forceUpdate()
      } else if (this.renderConfig.streamApi) {
        // 通过流式api 获取消息
        this.messages.push({ type: 'bot', state: 'loading', sourceInfo: '' })

        // 如果存在之前的连接，先关闭它
        if (this.stopConnection) {
          this.stopConnection()
        }

        let currentMessage = ''
        this.stopConnection = startEventStreamPOST(
          this.renderConfig.streamApi,
          {
            userMessage,
            model: this.renderConfig.aiModel,
            chatId: this.renderConfig.chatId || moment().format('YYYYMMDDHHmmss'),
            prompt: this.prompt,
            additionalInfo: this.additionalInfo
          },
          {},
          (data, type) => {
            // 处理 additionalInfo 事件
            if (type === 'additionalInfo') {
              console.log('收到 additionalInfo:', data)
              if (data) {
                // 更新 additionalInfo
                this.additionalInfo = {
                  ...this.additionalInfo,
                  ...data
                }
                // 触发全局数据更新
                this.setGlobalData?.(this.additionalInfo)
              }
              return
            }

            if (type === 'sourceInfo') {
              console.log('收到 sourceInfo:', data)
              if (data) {
                // 更新 sourceInfo
                this.messages[this.messages.length - 1].sourceInfo = data.replace(/<br\s*\/?>/gi, '\n')
              }
              return
            }
            // 处理普通消息
            if (this.messages[this.messages.length - 1].state === 'loading') {
              this.messages[this.messages.length - 1].state = undefined
            }
            currentMessage += data
            this.messages[this.messages.length - 1].text = currentMessage.replace(/<br\s*\/?>/gi, '\n')
            this.renderMarkdown(this.messages[this.messages.length - 1].text)
            this.$forceUpdate()
          },
          (error) => {
            console.error('流式请求错误:', error)
            this.messages[this.messages.length - 1].state = undefined
            this.messages[this.messages.length - 1].text = '抱歉，消息发送失败，请重试。'
            this.$forceUpdate()
          }
        )
      }
    },
    setHistoryMessages (messages) {
      console.log(messages)
      // 清空现有消息
      this.messages = []
      // 添加历史消息
      messages.forEach(msg => {
        this.messages.push({
          type: msg.role === 'user' ? 'user' : 'bot',
          text: msg.content
        })
      })
      this.scrollToBottom()
    },
    showSourceInfo (sourceInfo) {
      this.currentSourceInfo = typeof sourceInfo === 'string'
        ? sourceInfo
        : JSON.stringify(sourceInfo, null, 2)
      this.sourceInfoVisible = true
    },
  },
  mounted () {
    this.setAddtionalInfo(this.getMixinData())
  },
  beforeDestroy () {
    if (this.stopConnection) {
      this.stopConnection()
    }
  },
  watch: {
    messages: {
      handler () {
        this.scrollToBottom()
      },
      deep: true
    }
  }
}
</script>

<style scoped>
.chat-container {
  display: flex;
  flex-direction: column;
  height: 600px; /* 设置最小高度 */
  border: 1px solid #d9d9d9;
  border-radius: 4px;
  overflow: hidden;
  position: relative;
}

.chat-content {
  flex: 1;
  padding: 16px;
  overflow-y: auto;
  background: #f5f5f5;
  padding-bottom: 60px; /* 为底部输入框留出空间 */
}

.chat-message {
  display: flex;
  align-items: flex-start;
  margin-bottom: 10px;
}

.chat-message.user {
  justify-content: flex-end;
}

.chat-message.bot {
  justify-content: flex-start;
}

.chat-avatar {
  margin: 0 8px;
}

.chat-text-wrapper {
  display: flex;
  flex-direction: column;
  max-width: 70%;
}

.chat-text {
  padding: 8px 12px;
  border-radius: 4px;
  background-color: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.chat-message.user .chat-text {
  background-color: #e6f7ff;
}

.chat-input-wrapper {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: #fff;
  border-top: 1px solid #d9d9d9;
  padding: 8px;
}

.chat-input {
  display: flex;
  gap: 10px;
}

.chat-input a-input {
  flex: 1;
}

code {
  background-color: #f5f5f5;
  border-radius: 4px;
  padding: 2px 4px;
  font-size: 90%;
}

/* 添加 Markdown 样式 */
.markdown-body {
  font-size: 14px;
  line-height: 1.6;
}

.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
  margin-top: 16px;
  margin-bottom: 8px;
  font-weight: 600;
}

.markdown-body pre {
  background-color: #f6f8fa;
  border-radius: 6px;
  padding: 16px;
  overflow: auto;
}

.markdown-body code {
  background-color: #f6f8fa;
  border-radius: 3px;
  padding: 0.2em 0.4em;
  font-size: 85%;
}

.markdown-body p {
  margin-bottom: 16px;
}

.markdown-body ul,
.markdown-body ol {
  padding-left: 2em;
  margin-bottom: 16px;
}

/* 按钮样式 */
.markdown-body :deep(button) {
  display: inline-block;
  padding: 4px 15px;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.5715;
  text-align: center;
  white-space: nowrap;
  background: #fff;
  border: 1px solid #d9d9d9;
  border-radius: 2px;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
  user-select: none;
  touch-action: manipulation;
  margin: 4px 8px 4px 0;
}

.markdown-body :deep(button:hover) {
  color: #40a9ff;
  border-color: #40a9ff;
  background: #fff;
}

.markdown-body :deep(button:active) {
  color: #096dd9;
  border-color: #096dd9;
  background: #fff;
}

/* Markdown 按钮样式 */
.markdown-button {
  display: inline-block;
  padding: 4px 15px;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.5715;
  text-align: center;
  white-space: nowrap;
  background: #fff;
  border: 1px solid #d9d9d9;
  border-radius: 2px;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
  user-select: none;
  touch-action: manipulation;
  margin: 4px 8px 4px 0;
}

.markdown-button:hover {
  color: #40a9ff;
  border-color: #40a9ff;
  background: #fff;
}

.markdown-button:active {
  color: #096dd9;
  border-color: #096dd9;
  background: #fff;
}

.source-info-btn {
  font-size: 12px;
  padding: 0;
  margin-top: 4px;
  align-self: flex-start;
}

.source-info-content {
  background-color: #f5f5f5;
  padding: 16px;
  border-radius: 4px;
  max-height: 400px;
  overflow-y: auto;
  white-space: pre-wrap;
  word-break: break-all;
}

.source-info-content :deep(pre) {
  background-color: #f6f8fa;
  border-radius: 6px;
  padding: 16px;
  overflow: auto;
  margin: 0;
}

.source-info-content :deep(code) {
  background-color: #f6f8fa;
  border-radius: 3px;
  padding: 0.2em 0.4em;
  font-size: 85%;
}
</style>
