<template>
    <div class="demo-test">
      <McHeader :logoImg="'/src/assets/logo.svg'" :title="'MateChat'">
        <template #operationArea>
          <div class="operations">
            <i class="icon-close" @click="closeDrawer()"></i>
          </div>
        </template>
      </McHeader>
      <div v-if="startChat" ref="conversationRef" class="conversation-area">
        <template v-for="(msg, idx) in messages" :key="idx">
          <McBubble v-if="msg.from === 'user'" :content="msg.content" :align="'right'" :avatarConfig="msg.avatarConfig"></McBubble>
          <McBubble v-else :loading="msg.loading" :avatarPosition="msg.avatarPosition" :avatarConfig="msg.avatarConfig" style="max-width: 540px">
            <RenderMarkdown v-if="msg.type === 'common'" :content="msg.content"></RenderMarkdown>
            <div :id="'demoChart'+idx" 
              draggable="true"
              v-if="msg.type === 'card'"
              @dragstart="ondragstart($event, msg)"  
              @dragover.prevent="ondragover($event)"
              @dragleave.prevent="ondragleave($event)"
              @drop.prevent="ondrop($event)" 
              :class="['content-card']"
              >
                <DemoCard :chartStr="msg.componentStr" :containerId="'demoChart'+idx"></DemoCard>
            </div>
            <template #bottom>
              <div class="bubble-bottom-operations">
                <i class="icon-copy-new"></i>
                <i class="icon-like"></i>
                <i class="icon-dislike"></i>
                <i class="icon-switch" :title="msg.type === 'card' ? '切换为代码' : '切换为组件'" @click="changeType(msg, idx)"></i>
              </div>
            </template>
          </McBubble>
        </template>
      </div>
      <div v-else class="welcome-page">
        <McIntroduction
          class="intro"
          logo-img="/src/assets/logo2x.svg"
          title="MateChat"
          sub-title="Hi，欢迎使用 MateChat"
          :description="[
            'MateChat 可以辅助研发人员编码、查询知识和相关作业信息、编写文档等。',
            '作为AI模型，MateChat 提供的答案可能不总是确定或准确的，但您的反馈可以帮助 MateChat 做的更好。',
          ]"
        ></McIntroduction>
        <!-- <McPrompt :list="introPrompt.list" :direction="'horizontal'" class="intro-prompt" @itemClick="onItemClick($event)"></McPrompt> -->
      </div>
      <div class="new-convo-button">
        <div v-if="startChat" class="prompt-list">
          <McPrompt
            class="simple-prompt"
            style="flex: 1"
            :list="simplePrompt"
            :direction="'horizontal'"
            @itemClick="onItemClick($event)"
          ></McPrompt>
        </div>
        <div v-else class="agent-knowledge">
          <d-dropdown :position="['top']" @toggle="(val) => (isAgentOpen = val)">
            <div class="agent-wrapper">
              <img src="../assets/logo.svg" />
              <span>{{ selectedAgent.label }}</span>
              <i class="icon-infrastructure"></i>
              <i :class="['icon-chevron-down-2', { 'is-open': isAgentOpen }]"></i>
            </div>
            <template #menu>
              <McList :data="agentList" @select="(val) => (selectedAgent = val)"></McList>
            </template>
          </d-dropdown>
          <span class="agent-knowledge-dividing-line"></span>
          <div class="knowledge-wrapper">
            <i class="icon-operation-log"></i>
            <span>添加知识</span>
          </div>
        </div>
        <d-button icon="stop" shape="circle" title="中止对话" size="sm" @click="stop" />
        <d-button icon="add" shape="circle" title="新建对话" size="sm" @click="onNewConvo" />
      </div>
      <div style="padding: 0 12px 12px 12px">
        <McInput :value="inputValue" :maxLength="2000" @change="(e) => (inputValue = e)" @submit="onSubmit">
          <template #extra>
            <div class="input-foot-wrapper">
              <div class="input-foot-left">
                <span v-for="(item, index) in inputFootIcons" :key="index" @click="() => onInputIconClick(item)">
                  <i :class="item.icon"></i>
                  {{ item.text }}
                </span>
                <span class="input-foot-dividing-line"></span>
                <span class="input-foot-maxlength">{{ inputValue.length }}/2000</span>
              </div>
              <div class="input-foot-right">
                <d-button icon="op-clearup" shape="round" :disabled="!inputValue" @click="inputValue = ''">清空输入</d-button>
              </div>
            </div>
          </template>
        </McInput>
      </div>
    </div>
  </template>
  
  <script>
  import { ref, defineComponent, nextTick, defineEmits, onMounted, onUnmounted, watch, onActivated, onDeactivated } from 'vue';
  import { introPrompt, simplePrompt, mockAnswer, guessQuestions } from './mock.constant';
  import DemoCard from './DemoCard/DemoCard.vue';
  import RenderMarkdown from './RenderMarkdown.vue';
  import { fetchEventSource } from '@microsoft/fetch-event-source';
  import { apiKey, apiUrl } from '../../config';

  
  export default defineComponent({
    components: {
      DemoCard, RenderMarkdown
    },
    emits: ['closeDrawer', 'chartStrChange'],
    setup(props, { emit }) {
      let abortController = null;
      const inputValue = ref('');
      const startChat = ref(false);
      const conversationRef = ref();
      const isAgentOpen = ref(false);
      const agentList = ref([
        { label: 'MateChat', value: 'matechat' },
        { label: 'InsCode', value: 'inscode', active: true },
      ]);
      const selectedAgent = ref(agentList.value[1]);
      const aiModelAvatar = {
        imgSrc: "/src/assets/logo.svg",
        width: 32,
        height: 32,
      };
      const customerAvatar = {
        name: 'Me',
        width: 32,
        height: 32,
      };
      const inputFootIcons = [
        { icon: 'icon-at', text: '智能体' },
        { icon: 'icon-standard', text: '词库' },
        { icon: 'icon-add', text: '附件' },
      ];
      const messages = ref([]);

      onActivated(() => {
        if (window.savedState) {
          messages.value = window.savedState.messages;
          inputValue.value = window.savedState.inputValue;
          startChat.value = window.savedState.startChat;

          nextTick(() => {
            if (conversationRef.value) {
              conversationRef.value.scrollTop = conversationRef.value.scrollHeight;
            }
          });
        }
      });

      onDeactivated(() => {
        window.savedState = {
          messages: [...messages.value], // 深拷贝数组
          inputValue: inputValue.value,
          startChat: startChat.value,
          scrollPosition: conversationRef.value?.scrollTop || 0
        };
        
      });

      const onInputIconClick = (e) => {
        if (e.icon === 'icon-at') {
          inputValue.value += `@${selectedAgent.value.label}`;
        }
      };
  
      const onSubmit = (e, answer = undefined, type = 'common') => { 
        if (abortController) {
          messages.value.at(-1).loading = false;
          messages.value.at(-1).content = '对话中止';
          abortController.abort();
          abortController = null;
        }
        inputValue.value = '';
        if (!messages.value.length) {
          startChat.value = true;
        }
        messages.value.push({
          from: 'user',
          content: e,
          type,
          avatarPosition: 'side-right',
          avatarConfig: { ...customerAvatar },
        });
        nextTick(() => {
          conversationRef.value?.scrollTo({
            top: conversationRef.value.scrollHeight,
            behavior: 'smooth',
          });
        });
        if (answer) {
          getMockAnswer(answer, type);
        } else {
          getAIAnswer(answer ?? e, type);
        }
      };

      const getMockAnswer = (answer, type) => {
        const aiAnswer = {
          from: 'ai-model',
          content: answer,
          type,
          avatarPosition: 'side-left',
          avatarConfig: { ...aiModelAvatar },
          loading: true,
        }
        messages.value.push(aiAnswer);
        setTimeout(() => {
          messages.value.at(-1).loading = false;
          nextTick(() => {
          conversationRef.value?.scrollTo({
              top: conversationRef.value.scrollHeight,
              behavior: 'smooth',
            });
          });
        }, 1000);
      }
  
      const getAIAnswer = (content, type) => {
        abortController = new AbortController();
        const aiAnswer = {
          from: 'ai-model',
          content: '',
          type,
          avatarPosition: 'side-left',
          avatarConfig: { ...aiModelAvatar },
          loading: true,
        }
        messages.value.push(aiAnswer);
        const source = fetchEventSource(apiUrl, {
          method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                messages: [
                  {
                    role: 'user',
                    content
                  }
                ],
                apikey: apiKey
            }),
            signal: abortController.signal,
            onopen: (response) => {
            },
            onmessage: (msg) => {
                messages.value.at(-1).loading = false;
                if (msg.data === '[DONE]') {
                  nextTick(() => {
                    conversationRef.value?.scrollTo({
                      top: conversationRef.value.scrollHeight,
                      behavior: 'smooth',
                    });
                  });
                  return;
                };
                const data = JSON.parse(msg.data);
                const responseContent = data.choices[0].delta.content;
                messages.value.at(-1).content += responseContent;
            },
            onerror: (err) => {
                messages.value.at(-1).loading = false;
                messages.value.at(-1).content = '请求失败';
                throw err;
            }
        });
      };

      const stop = () => {
        if (abortController) {
          abortController.abort();
          abortController = null;
          // 更新最后一条消息的状态
          if (messages.value.length > 0) {
            messages.value.at(-1).loading = false;
            messages.value.at(-1).content += '已中止对话';
          }
        }
      }
  
      const onNewConvo = () => {
        startChat.value = false;
        messages.value = [];
      };
  
      const onItemClick = (item) => {
        if (mockAnswer[item.value]) {
          // 使用 mock 数据
          onSubmit(item.label, mockAnswer[item.value]);
        } else {
          // 使用 AI 数据
          onSubmit(item.label);
        }
      };

      const closeDrawer = () => {
        emit('closeDrawer')
      };

      // 拖动事件
      const isDragging = ref(false);

      const handleDragOver = (e) => {
        e.preventDefault();
        if (isDragging.value) {
          e.dataTransfer.dropEffect = 'move';
        }
      };

      const handleDrop = (e) => {
        e.preventDefault();
        isDragging.value = false;
      };

      // 添加全局事件监听
      onMounted(() => {
        document.addEventListener('dragover', handleDragOver);
        document.addEventListener('drop', handleDrop);
      });

      // 清理事件监听
      onUnmounted(() => {
        document.removeEventListener('dragover', handleDragOver);
        document.removeEventListener('drop', handleDrop);
      });

      const ondragstart = (e, msg) => {
        e.target.style.backgroundColor = 'var(--devui-float-block-shadow)';
        emit('closeDrawer');
        emit('chartStrChange', msg.componentStr);
      };

      const ondragover = (e) => {
        e.preventDefault();
        if (isDragging.value) {
          e.dataTransfer.dropEffect = 'move';
        }
      };

      const ondragleave = (e) => {
      };

      const ondrop = (e) => {
        isDragging.value = false;
      };

      const changeType = (msg, index) => {
        msg.componentStr = copyContent(msg);
        messages.value[index] = {
          ...msg,
          type: msg.type === 'card' ? 'common' : 'card'
        };
      }

      const copyContent = (message) => {
        const componentRegex = /<template>[\s\S]*?<\/template>\s*<script[\s\S]*?<\/script>\s*(?:<style[\s\S]*?<\/style>)?/g;
  
        const match = message.content.match(componentRegex);

        return match ? match[0] : null;
      }
  
      return {
        inputValue,
        conversationRef,
        inputFootIcons,
        messages,
        onSubmit,
        introPrompt,
        simplePrompt,
        onNewConvo,
        onItemClick,
        startChat,
        guessQuestions,
        closeDrawer,
        isDragging,
        ondragstart,
        ondragover,
        ondragleave,
        ondrop,
        changeType,
        isAgentOpen,
        selectedAgent,
        agentList,
        onInputIconClick,
        copyContent,
        stop
      };
    },
  });
  </script>
  
  <style scoped lang="scss">
  .demo-test {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    gap: 8px;
    .conversation-area,
    .welcome-page {
      flex: 1;
      display: flex;
      flex-direction: column;
      overflow: auto;
      padding: 0 12px;
    }
  
    .conversation-area {
      gap: 8px;
    }
  
    .welcome-page {
      gap: 24px;
      justify-content: space-between;
      .intro {
        padding-top: 40px;
        flex: 1;
      }
    }
  
    .guess-question {
      width: 100%;
      padding: 16px 12px;
      border-radius: var(--devui-border-radius-card);
      background-color: var(--devui-gray-form-control-bg);
  
      .guess-title {
        display: flex;
        justify-content: space-between;
        align-items: center;
        color: var(--devui-text);
        margin-bottom: 12px;
  
        & > div:first-child {
          font-weight: 700;
          font-size: var(--devui-font-size);
        }
        & > div:last-child {
          font-size: var(--devui-font-size-sm);
          cursor: pointer;
          span {
            margin-left: 4px;
          }
        }
      }
  
      .guess-content {
        display: flex;
        align-items: center;
        flex-wrap: wrap;
        gap: 8px;
        span {
          font-size: var(--devui-font-size-sm);
          color: var(--devui-text);
          padding: 4px 12px;
          border-radius: var(--devui-border-radius-full);
          background-color: var(--devui-gray-form-control-hover-bg);
          cursor: pointer;
        }
      }
    }
  
    .bubble-bottom-operations {
      margin-top: 8px;
      i {
        padding: 4px;
        border-radius: 4px;
        cursor: pointer;
  
        &:hover {
          background-color: var(--devui-icon-hover-bg);
        }
      }
    }
  
    .new-convo-button {
      padding: 0 12px;
      display: flex;
      justify-content: flex-end;
      align-items: center;
      height: 39px;
      gap: 4px;
    }

    .prompt-list {
      display: flex;
      flex: 1;
    }
  
    :deep(.simple-prompt .mc-list) {
      justify-content: unset;
    }
  
    :deep(.intro-prompt .mc-list) {
      justify-content: center;
  
      .mc-list-item {
        flex: 1;
      }
    }
  
    .operations {
      i {
        padding: 4px;
        border-radius: 4px;
        cursor: pointer;
  
        &:hover {
          background: var(--devui-global-bg);
        }
      }
    }
  
    .agent-knowledge {
      flex: 1;
      display: flex;
      align-items: center;
  
      .agent-wrapper {
        display: flex;
        align-items: center;
        padding: 4px 8px;
        border-radius: var(--devui-border-radius-full);
        background-color: var(--devui-area);
        cursor: pointer;
  
        img {
          width: 16px;
          height: 16px;
          margin-right: 4px;
        }
  
        span {
          font-size: var(--devui-font-size);
          color: var(--devui-text);
          margin-right: 8px;
        }
  
        i {
          font-size: var(--devui-font-size);
          color: var(--devui-text);
          transition: transform 0.3s ease-in-out;
  
          &:last-child {
            margin-left: 4px;
          }
        }
  
        .is-open {
          transform: rotate(180deg);
        }
      }
  
      .agent-knowledge-dividing-line {
        width: 1px;
        height: 14px;
        margin: 0 12px;
        background-color: var(--devui-line);
      }
  
      .knowledge-wrapper {
        font-size: var(--devui-font-size);
        color: var(--devui-text);
        cursor: pointer;
  
        span {
          margin-left: 4px;
        }
      }
    }
  
    .input-foot-wrapper {
      display: flex;
      justify-content: space-between;
      align-items: center;
      width: 100%;
      height: 100%;
      margin-right: 8px;
  
      .input-foot-left {
        display: flex;
        align-items: center;
        gap: 8px;
  
        span {
          font-size: var(--devui-font-size-sm);
          color: var(--devui-text);
          cursor: pointer;
        }
  
        .input-foot-dividing-line {
          width: 1px;
          height: 14px;
          background-color: var(--devui-line);
        }
  
        .input-foot-maxlength {
          font-size: var(--devui-font-size-sm);
          color: var(--devui-aide-text);
        }
      }
  
      .input-foot-right {
        & > *:not(:first-child) {
          margin-left: 8px;
        }
      }
    }
  }

  .content-card {
  margin: 8px;
  overflow: hidden;
  background-color: var(--devui-base-bg);
  border-radius: var(--devui-border-radius-card);
  box-shadow: var(--devui-shadow-length-base) var(--devui-light-shadow);
  height: 400px;
  width: 400px;
  transition: transform 0.3s, box-shadow 0.3s;
  &.dragging {
    opacity: 1 !important;
  }
  &:hover {
    transform: translateY(-5px);
    
  }
}
</style>