<script setup lang="ts">
import AutoResizeTextarea from './components/AutoResizeTextarea.vue'
import LoadingDots from './components/LoadingDots.vue'
import AIQuestions from './components/AIQuestions.vue'
import userBubbleLight from './image/userBubbleLight.png'
import userBubbleDark from './image/userBubbleDark.png'
import robotBubbleLight from './image/robotBubbleLight.png'
import robotBubbleDark from './image/robotBubbleDark.png'
import { useThemeStore } from '@/stores/modules/theme'
import { useUserStore } from '@/stores/modules/user'
import MarkdownIt from 'markdown-it'
import 'github-markdown-css/github-markdown.css'

const userStore = useUserStore()
const md = new MarkdownIt({
  html: true,
  linkify: true,
  typographer: true,
  breaks: true
})

const renderedMessage = (content) => {
  // console.log('content', content)
  if (!content) {
    return ''
  }
  const normalized = content
    .replace(/\\n/g, '\n') // 粘贴带来的 \\n 处理
    .replace(/\r\n/g, '\n') // Windows 换行标准化
    .trim()
  return md.render(normalized)
}

const themeStore = useThemeStore()
const modalSize = ref('large')
const userQuestion = ref()

const isFooterInputFocus = ref(false)

const userBubbleImg = computed(() => {
  return themeStore.theme === 'light' ? userBubbleLight : userBubbleDark
})
const robotBubbleImg = computed(() => {
  return themeStore.theme === 'light' ? robotBubbleLight : robotBubbleDark
})

// 是否显示footer的顶部阴影
const isShowFooterShadow = ref(false)
// 是否显示header的底部阴影
const isShowHeaderShadow = ref(false)

const loadingAnswer = ref(false) // 是否正在加载答案
interface MessageItem {
  id?: string // 唯一标识
  type: 'robot' | 'user'
  content: string
  feedback?: 'Cood' | 'Not Good' | '' // 反馈结果
  isShowFeedback?: boolean // 是否展示反馈样式
  isAnswer?: boolean // 是否为用户问题的答案，是则才能展示反馈组件
  isError?: boolean // 是否为错误消息
  isCancel?: boolean // 是否为取消消息
  html?: string // 渲染后的HTML内容
}
const messages = ref<MessageItem[]>([
  {
    type: 'robot',
    isShowFeedback: false,
    content: 'You can click on Frequently Asked Questions above or type your own question'
  }
])
messages.value = JSON.parse(sessionStorage.getItem('AIChat')) || messages.value
const handleOpen = () => {
  scrollToBottom()
}

watch(
  () => messages.value,
  (newVal) => {
    // 将消息存储到 sessionStorage 中
    sessionStorage.setItem('AIChat', JSON.stringify(newVal))
  },
  { immediate: true, deep: true }
)

// 用户问题请求时间
const queryTime = ref(-1)
// 当前用户问题回复进度
const progressStatus = {
  init: 'You can click on Frequently Asked Questions above or type your own question',
  '0': 'Thinking about your question...',
  '15': 'Searching for relevant data, please wait...',
  '30': 'This query is complex and may take more time',
  '60': 'You may try simplifying your question or selecting a Frequently Asked Question',
  '120': 'Sorry, the query failed. Please try again later or select a Frequently Asked Question',
  cancel: 'You have stopped this answer'
}

const isShowTips = ref(false) // 是否展示提示信息

const parseHtmlString = (data) => {
  const lines = data.split('\n')

  function streamMarkdown() {
    const lastMsg: any = messages.value[messages.value.length - 1]
    let index = 0
    lastMsg.content = '' // 清空上一个消息的内容
    const timer = setInterval(() => {
      if (index < lines.length) {
        lastMsg.content += lines[index] + '\n'
        lastMsg.html = renderedMessage(lastMsg.content) // ✅ 每次整段渲染
        index++
        scrollToBottom() // 滚动到底部
      } else {
        clearInterval(timer)
      }
    }, 150)
  }

  streamMarkdown()
}

const progressInterval = ref()
const serial_no = ref()
const is_FixedAnswer = ref(true) // 是否为预设问题 true是自由问题 false是预设问题
const aiChat = (question, isPresetQuestion) => {
  serial_no.value = userStore.userInfo?.uname + Date.now().toString()
  $api
    .aiChat({
      serial_no: serial_no.value,
      prompt: sessionStorage.getItem('prompt'),
      // question_type: isPresetQuestion || !is_FixedAnswer ? 'Predefined Question' : 'Free Question',
      question_type: 'Free Question',
      question_content: question,
      fixed_faq: !is_FixedAnswer ? messages.value[messages.value.length - 2].content : ''
    })
    .then((res) => {
      if (isPause.value) {
        return
      }
      if (res.code === 200) {
        clearInterval(progressInterval.value)
        const { data } = res.data
        messages.value[messages.value.length - 1] = {
          id: serial_no.value,
          type: 'robot',
          content: '',
          feedback: '',
          isShowFeedback: false,
          isAnswer: true
        }

        parseHtmlString(data)
        scrollToBottom()
        loadingAnswer.value = false
        queryTime.value = -1
      } else {
        loadingAnswer.value = false
        messages.value[messages.value.length - 1].isError = true
      }
    })
}
const handleSend = (question, isPresetQuestion = true, isExternal = false) => {
  if (!question) return
  if (
    isExternal &&
    messages.value.length === 1 &&
    messages.value[0].content === progressStatus.init
  ) {
    messages.value.pop()
  }
  if (loadingAnswer.value) {
    isShowTips.value = true
    setTimeout(() => {
      isShowTips.value = false
    }, 2000)
    return
  }
  isPause.value = false
  loadingAnswer.value = true

  aiChat(question, isPresetQuestion)
  // 将用户内容添加到消息列表
  messages.value.push({
    type: 'user',
    content: question
  })
  !isPresetQuestion ? (userQuestion.value = '') : ''
  queryTime.value = 0
  messages.value.push({
    type: 'robot',
    content: progressStatus[0]
  })
  autoScroll.value = true
  scrollToBottom()

  progressInterval.value = setInterval(() => {
    queryTime.value++
    // 定义时间点与对应状态的映射
    const timeToStatusMap = {
      15: 15,
      30: 30,
      60: 60
    }
    // 获取最后一个消息对象
    const lastMessage = messages.value[messages.value.length - 1]
    if (queryTime.value === 120) {
      clearInterval(progressInterval.value)
      lastMessage.content = progressStatus[120]
      lastMessage.isError = true
      queryTime.value = -1
      loadingAnswer.value = false
      return
    }
    if (timeToStatusMap[queryTime.value] !== undefined) {
      lastMessage.content = progressStatus[queryTime.value]
    }
  }, 1000)
}
const showScrollButton = ref(false) // 控制按钮显示
const messagesRef = ref()
const autoScroll = ref(true)

function handleScroll() {
  const el = messagesRef.value
  const threshold = 50 // 到底部的距离阈值
  const atBottom = el.scrollHeight - el.scrollTop - el.clientHeight < threshold
  autoScroll.value = atBottom

  showScrollButton.value = el.scrollHeight > el.clientHeight && !autoScroll.value

  isShowFooterShadow.value =
    messagesRef.value?.scrollTop <
    messagesRef.value?.scrollHeight - messagesRef.value?.clientHeight - 1

  isShowHeaderShadow.value = !!messagesRef.value?.scrollTop
}
function scrollToBottom() {
  nextTick(() => {
    if (messagesRef.value) {
      messagesRef.value.scrollTop = messagesRef.value.scrollHeight
    }
  })
}

const isPause = ref(false) // 是否暂停回答
// 暂停回答
const handlePause = () => {
  $api
    .pauseAiChat({
      serial_no: serial_no.value
    })
    .then((res) => {
      if (res.code === 200) {
        clearInterval(progressInterval.value)
        is_FixedAnswer.value = true
        queryTime.value = -1
        messages.value[messages.value.length - 1].isCancel = true
        messages.value[messages.value.length - 1].content = progressStatus.cancel
        isPause.value = true
        loadingAnswer.value = false
        scrollToBottom()
      }
    })
}

// 评价
const handleFeedback = (index, feedback) => {
  const message = messages.value[index]
  message.feedback = feedback
  $api
    .feedbackAiChat({
      serial_no: message.id,
      feedback: feedback
    })
    .then((res) => {
      if (res.code === 200) {
        messages.value[index].isShowFeedback = false
      }
    })
}

const emit = defineEmits(['close'])
// 关闭聊天窗口
const handleClose = () => {
  // progressInterval.value && clearInterval(progressInterval.value)
  emit('close')
}

defineExpose({
  handleSend,
  handleOpen
})
</script>

<template>
  <div class="ai-robot" :style="{ width: modalSize === 'large' ? '1000px' : '484px' }">
    <div class="top-section" :class="[isShowHeaderShadow ? 'box-shadow' : '']">
      <div class="header">
        <span class="welcome">Hi! I'm your Freight Assistant</span>
        <div class="option-icon">
          <span
            v-if="modalSize === 'large'"
            class="font_family icon-icon_sidebar__window_b"
            @click="modalSize = 'small'"
          ></span>
          <span
            v-else-if="modalSize !== 'large'"
            class="font_family icon-icon_maximized__window_b"
            @click="modalSize = 'large'"
          ></span>
          <span @click="handleClose" class="font_family icon-icon_collapsed__to_widget_b"></span>
        </div>
      </div>
      <AIQuestions :modalSize="modalSize" @question="handleSend"></AIQuestions>
      <div class="warning-tips" v-if="isShowTips">
        <div class="warning-bg">
          <span class="warning-icon font_family icon-icon_warning_fill_b"></span>
        </div>
        <span>Answer in progress, please wait.</span>
      </div>
    </div>
    <div class="chat-messages" ref="messagesRef" @scroll="handleScroll">
      <div
        class="message-item"
        :class="[
          msg.type === 'user' ? 'user-bubble' : 'robot-bubble',
          (queryTime > -1 && queryTime < 120 && index === messages.length - 1) || msg.isCancel
            ? 'query-style'
            : ''
        ]"
        :style="{
          maxWidth: modalSize === 'large' ? 'calc(100% - 20px)' : 'calc(100% - 16px)'
        }"
        v-for="(msg, index) in messages"
        :key="index"
        @mouseenter="msg.isShowFeedback = true"
        @mouseleave="msg.isShowFeedback = false"
      >
        <!-- 请求失败后的提示icon   -->
        <div class="pause-bg" v-if="msg.isError">
          <span class="pause-icon font_family icon-icon_warning_fill_b"></span>
        </div>
        <!-- loading icon -->
        <img
          class="loading-img"
          v-if="queryTime > -1 && queryTime < 120 && index === messages.length - 1"
          src="./image/icon_loading.png"
          alt=""
        />
        <div style="display: inline-block; max-width: 100%">
          <div v-html="msg.html || renderedMessage(msg.content)" class="markdown-body"></div>
        </div>
        <LoadingDots
          v-if="index === messages.length - 1 && msg.isAnswer && loadingAnswer"
        ></LoadingDots>
        <!-- 评价  -->
        <div class="review" v-if="msg.isShowFeedback && msg.isAnswer">
          <el-button
            v-if="msg.feedback !== 'Cood'"
            class="el-button--text"
            @click="handleFeedback(index, 'Cood')"
          >
            <span class="font_family icon-icon_good_b"></span>
          </el-button>
          <div v-if="msg.feedback === 'Cood'" style="width: 16px; text-align: center">
            <span
              style="color: var(--color-theme); font-size: 14px"
              class="font_family icon-icon_good__filled_b"
            ></span>
          </div>
          <el-button
            v-if="msg.feedback !== 'Not Good'"
            class="el-button--text"
            @click="handleFeedback(index, 'Not Good')"
          >
            <span class="font_family icon-icon_notgood_b"></span>
          </el-button>
          <div v-if="msg.feedback === 'Not Good'" style="width: 16px; text-align: center">
            <span
              style="color: var(--color-theme); font-size: 14px"
              class="font_family icon-icon_notgood__filled_b"
            ></span>
          </div>
        </div>

        <img class="robot-bubble-img" v-if="msg.type === 'robot'" :src="robotBubbleImg" alt="" />
        <img class="user-bubble-img" v-else-if="msg.type === 'user'" :src="userBubbleImg" alt="" />
        <!-- 暂停回答 icon -->
        <div
          class="pause-btn"
          v-if="index === messages.length - 1 && queryTime > 29 && queryTime < 120"
          @click="handlePause"
        >
          <div class="dot"></div>
        </div>
      </div>
      <!-- 滚动到底部icon -->
      <div v-if="showScrollButton" class="scroll-to-bottom-btn" @click="scrollToBottom">
        <span class="font_family icon-icon_movedown_b"></span>
      </div>
    </div>

    <div
      class="footer"
      :class="[isFooterInputFocus ? 'focus-style' : '', isShowFooterShadow ? 'box-shadow' : '']"
    >
      <div class="footer-input">
        <AutoResizeTextarea
          style="flex: 1"
          v-model="userQuestion"
          :placeholder="'Type your question here...'"
          @focus="isFooterInputFocus = true"
          @blur="isFooterInputFocus = false"
        />
        <div
          class="input-icon"
          :class="[!userQuestion || queryTime !== -1 ? 'disable' : '']"
          @click="handleSend(userQuestion, false)"
        >
          <span class="font_family icon-icon_send_b"></span>
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.ai-robot {
  position: absolute;
  top: 74px;
  right: 24px;
  height: calc(100% - 98px);
  z-index: 4000;
  display: flex;
  flex-direction: column;
  border-radius: 12px;
  border: 1px solid var(--color-border);
  box-shadow: 4px 4px 32px 0px rgba(0, 0, 0, 0.2);
  background-color: var(--color-dialog-body-bg);
  overflow: hidden;
  .top-section {
    position: relative;
    padding-bottom: 16px;
    background: linear-gradient(
      to bottom,
      var(--color-ai-chat-header-bg-gradient-begin) 10%,
      var(--color-ai-chat-header-bg-gradient-begin) 10%,
      var(--color-ai-chat-header-bg-gradient-end) 100%
    );
    &.box-shadow {
      box-shadow: -2px 0px 12px rgba(0, 0, 0, 0.1);
    }
    .header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      height: 64px;
      margin-bottom: 6px;
      padding: 0 16px;
      .welcome {
        font-size: 18px;
        font-weight: 700;
      }
      .option-icon {
        display: flex;
        align-items: center;
        gap: 6px;
        .font_family {
          font-size: 16px;
          cursor: pointer;
          &:hover {
            color: var(--color-theme);
          }
        }
      }
    }
    .warning-tips {
      position: absolute;
      top: 60px;
      left: 17px;
      width: calc(100% - 32px);
      height: 40px;
      padding-top: 14px;
      background-color: var(--color-warning-tips-bg);
      border-radius: 6px;
      text-align: center;
      .warning-bg {
        position: relative;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        height: 12px;
        width: 12px;
        margin-right: 6px;
        border-radius: 50%;
        background-color: #fff;
      }
      .warning-icon {
        position: absolute;
        top: -3px;
        border-radius: 50%;
        border: none;
      }
      span {
        color: #edb82f;
      }
    }
  }

  .chat-messages {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding: 0 16px 18px;
    overflow: auto;
    .message-item {
      position: relative;
      display: inline-block;
      padding: 11px 8px;
      margin-bottom: 7px;
      border-radius: 12px;
      background-color: var(--scoring-bg-color);
      .review {
        position: absolute;
        bottom: -24px;
        left: 0;
        display: flex;
        align-items: center;
        gap: 13px;
        width: 100%;
        height: 30px;
        margin-top: 10px;
        padding-left: 30px;
        padding-top: 5px;

        button.el-button + .el-button {
          margin-left: 0px;
        }
      }
      .pause-bg {
        position: relative;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        height: 12px;
        width: 12px;
        margin-right: 6px;
        border-radius: 50%;
        background-color: #fff;
      }
      .pause-icon {
        position: absolute;
        top: -2px;
        color: #c9353f;
        border-radius: 50%;
        border: none;
      }
      .el-button--text {
        height: 16px;
        width: 16px;
        span {
          color: var(--color-neutral-2);
          font-size: 14px;
        }
        &:hover {
          span {
            color: var(--color-theme);
          }
        }
      }

      .loading-img {
        width: 16px;
        height: 16px;
        margin-top: -1px;
        margin-right: 4px;
        animation: loading-rotate 2s linear infinite;
      }

      .pause-btn {
        position: absolute;
        right: -22px;
        top: 50%;
        transform: translateY(-50%);
        display: flex;
        align-items: center;
        justify-content: center;
        height: 16px;
        width: 16px;
        border-radius: 50%;
        background-color: var(--color-customize-column-right-section-bg);
        .dot {
          height: 5px;
          width: 5px;
          border-radius: 1px;
          background-color: var(--color-theme);
        }
      }
    }
    .query-style {
      span {
        color: #b5b9bf;
      }
    }
    .robot-bubble {
      background: var(--scoring-bg-color);
      align-self: flex-start;
      .robot-bubble-img {
        position: absolute;
        left: -1px;
        bottom: -7px;
      }
    }
    .user-bubble {
      align-self: flex-end;
      background: linear-gradient(
        to right,
        var(--color-ai-user-bubble-bg-gradient-begin),
        var(--color-ai-user-bubble-bg-gradient-end)
      );
      .user-bubble-img {
        position: absolute;
        right: 0;
        bottom: -7px;
      }
    }
    .scroll-to-bottom-btn {
      position: absolute;
      right: 50%;
      transform: translateX(50%);
      bottom: 58px;
      display: flex;
      justify-content: center;
      align-items: center;
      height: 32px;
      width: 32px;
      border-radius: 50%;
      // background-color: #f5f4f4;
      background: rgba(255, 255, 255, 0.6); /* 半透明背景色 */
      box-shadow: 2px 2px 12px 0px rgba(0, 0, 0, 0.3);
      backdrop-filter: blur(1px); /* 应用10px的模糊效果 */
      span {
        color: #2b2f36;
      }
      cursor: pointer;
      &:hover {
        background-color: #fceee3;
        span {
          color: var(--color-theme);
        }
      }
    }
  }
  .footer {
    padding: 12px 16px;
    &.box-shadow {
      box-shadow: 0px 2px 12px rgba(0, 0, 0, 0.1);
    }
    &.focus-style {
      .footer-input {
        border: 1px solid var(--color-theme);
      }
      .input-icon {
        background-color: var(--color-theme);
        span {
          color: #fff;
        }
        &:hover {
          background-color: #d56200;
        }
      }
    }
  }
  .footer-input {
    display: flex;
    align-items: flex-end;
    gap: 12px;
    padding: 4px 12px;
    padding-right: 4px;
    border: 1px solid var(--input-border);
    border-radius: 20px;
    box-sizing: border-box;

    .input-icon {
      display: flex;
      justify-content: center;
      align-items: center;
      height: 32px;
      width: 32px;
      padding: 1px 0 0 2px;
      border-radius: 50%;
      cursor: pointer;
      &.disable {
        cursor: not-allowed;
      }
    }
  }

  @keyframes loading-rotate {
    0% {
      transform: rotate(0deg);
    }

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