<template>
  <div class="kimigpt">
    <header_local />
    <el-container>
      <el-aside width="200px">
        <br />
        <el-button
          type="warning"
          @click="newChat"
          style="width: 100%; display: block; margin: 0 auto"
          round
          block
        >
          新建对话
        </el-button>
        <br />
        <br />
        <el-menu @select="select" :default-active="selectMneu" v-if="menu && menu.length">
          <el-menu-item :index="item.id + ''" v-for="item in menu" :key="item.id">
            <span class="ellipsis" v-text="item.title"></span>
          </el-menu-item>
        </el-menu>
      </el-aside>
      <el-main style="position: relative; padding-bottom: 60px; box-sizing: border-box">
        <el-image class="logo" v-if="!list.length" style="width: 300px" :src="logo" fit="contain" />

        <div class="chatList" id="chatList">
          <div
            :class="item.role"
            :style="item.role === 'user' ? 'padding-bottom: 12px;' : ''"
            v-for="(item, index) in list"
            :key="index"
          >
            <div v-if="item.content && item.content.length" style="padding-left: 10px">
              <div
                v-for="(item2, index2) in item.content"
                :key="index2"
                v-html="toMarkdown(item2)"
              />
            </div>
            <div v-if="item.role === 'system'">
              <div style="display: inline-block; width: 25px; text-align: center">
                <el-icon @click="() => copy(item.content)" :size="15"><DocumentCopy /></el-icon>
              </div>
            </div>
          </div>
        </div>
        <div class="input">
          <input type="text" v-model="inputText" placeholder="请输入内容" />
          <div class="icon">
            <el-icon :size="25" color="#fdba74"><UploadFilled /></el-icon>
          </div>
          <div class="icon" v-loading="loading">
            <el-icon @click="() => pushW()" :size="25" color="#fdba74"><Position /></el-icon>
          </div>
        </div>
      </el-main>
    </el-container>
  </div>
</template>

<script setup>
import { ref, nextTick } from 'vue';
import MarkdownIt from 'markdown-it';
import { ElMessage, ElNotification } from 'element-plus';
import header_local from '../components/header.vue';
import config from '../../../config/index';
import { getGroupList, createGroup } from '@/api/kimigpt.js';

import logo from '../../../assets/img/logo.png';

import { fetchEventSource } from '@microsoft/fetch-event-source';

const selectMneu = ref('');
const inputText = ref('');
const loading = ref(false);
const list = ref([]);
const menu = ref([]);
let oldIndex = 0;

const toMarkdown = text => {
  const mk = new MarkdownIt();
  return mk.render(text);
};

const copy = async text => {
  try {
    await navigator.clipboard.writeText(text.join('\n'));
    ElMessage({
      message: '复制成功',
      type: 'success'
    });
  } catch (err) {
    ElMessage({
      message: '您的浏览器不支持复制',
      type: 'warning'
    });
  }
};

const select = (index, item) => {
  menu.value[oldIndex].kimiChats = list.value;
  selectMenu(menu.value[index]);
  oldIndex = index;
};

getGroupList({}).then(r => {
  menu.value = (r || []).map(v => {
    return {
      ...v,
      kimiChats: v.kimiChats.map(o => {
        o.content = o.content.split('\n');
        return o;
      })
    };
  });
  selectMneu.value = ((r || [])[0].id || '').toString();
  selectMenu(menu.value[0]);
});

function selectMenu(item) {
  const l = [];
  const ori = item || {};
  selectMneu.value = ori.id + '';
  for (let i = 0; i < (ori.kimiChats || []).length; i++) {
    const v = (ori.kimiChats || [])[i];
    l.push(v);
  }
  list.value = l;
  toBottom();
}

const toBottom = () => {
  nextTick(() => {
    var scrollableContainer = document.getElementById('chatList');
    scrollableContainer.scrollTo({
      top: scrollableContainer.scrollHeight,
      behavior: 'smooth'
    });
  });
};

function pushW() {
  list.value.push({
    role: 'user',
    content: [inputText.value]
  });
  loading.value = true;
  if (!selectMneu.value) {
    createGroup({ title: inputText.value }).then(r => {
      if (r) {
        ElNotification({
          title: '提示',
          message: '创建成功',
          duration: 1000
        });
        menu.value.push({
          ...r,
          kimiChats: []
        });
        selectMneu.value = r.id.toString();
        selectMenu(r);
        sse(inputText.value);
      }
    });
  } else {
    sse(inputText.value);
  }
}
function sse(question) {
  const controller = new AbortController();
  const questionItem = {
    role: 'system',
    content: []
  };
  const index = list.value.length;
  const L = JSON.parse(JSON.stringify(list.value));
  let t = undefined;
  fetchEventSource(config.base.videoProcessing + '/user/chat', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: localStorage.getItem('token')
    },
    body: JSON.stringify({
      groupId: selectMneu.value,
      content: question
    }),
    signal: controller.signal,
    onerror: e => {
      console.log('连接报错', e);
      controller.abort();
      inputText.value = '';
      loading.value = false;
      if (t) window.clearTimeout();
    },
    onclose: e => {
      console.log('连接关闭');
      loading.value = false;
      controller.abort();
      inputText.value = '';
      if (t) window.clearTimeout();
    },
    onmessage: e => {
      if (e.event !== 'data') return;
      let { data } = e;
      if (data === '[DONE]') {
        controller.abort();
        return;
      }
      try {
        const { choices } = JSON.parse(data);
        for (let i = 0; i < choices.length; i++) {
          const v = choices[i];
          if (!questionItem.content[i]) questionItem.content[i] = '';
          let text = v && v.delta ? v.delta.content || '' : '';
          questionItem.content[i] += text;
          if (v && v.finish_reason === 'stop') {
            controller.abort();
            loading.value = false;
            inputText.value = '';
          }
        }
        L[index] = questionItem;
        t = setTimeout(() => {
          if (t) clearTimeout(t);
          list.value = JSON.parse(JSON.stringify(L));
          toBottom();
        }, 100);
      } catch (error) {
        inputText.value = '';
        ElNotification({
          title: '提示',
          message: '服务繁忙',
          duration: 1000
        });
      }
    },
    onopen: () => {
      console.log('连接成功');
    }
  });
}

function newChat() {
  list.value = [];
  selectMneu.value = '';
}
</script>

<style scoped>
.kimigpt {
  position: relative;
}

.logo {
  position: absolute;
  left: 50%;
  top: 150px;
  transform: translateX(-50%);
}

.input {
  position: absolute;
  width: 90%;
  left: 5%;
  bottom: 10px;
  padding: 0.5em 1em;
  box-shadow: 0 0 10px #999;
  border-radius: 2em;
  display: flex;
}

.input input {
  border: none;
  outline: none;
  width: 100%;
  flex: 1;
}

.input .icon {
  width: 25px;
  margin-right: 3px;
}

.chatList {
  box-sizing: border-box;
  width: 100%;
  height: calc(100vh - 122px);
  overflow-y: auto;
}

.chatList .system,
.chatList .user {
  font-weight: 400;
  font-size: 16px;
  box-sizing: border-box;
  padding: 12px 12px 0 12px;
  min-height: 2em;
  line-height: 2em;
  background-color: #f4f4f680;
  border-radius: 22px;
  border: 1px solid #e5e7eb;
  width: 98%;
  border-bottom-left-radius: 0;
  margin-bottom: 1em;
  width: 90%;
  margin-left: 5%;
  margin-top: 1.5em;
}
.chatList .user {
  border-radius: 22px !important;
  border-bottom-right-radius: 0 !important;
  border-color: #fdba74;
  background-color: #fff7ed;
}

.ellipsis {
  white-space: nowrap; /* 确保文本在一行内显示 */
  overflow: hidden; /* 超出容器的文本会被隐藏 */
  text-overflow: ellipsis; /* 使用省略号表示被截断的文本 */
}
</style>
