<script setup>
import { ref, unref, computed, provide, onUnmounted } from 'vue';
import { useMessage, NDatePicker, NTabs, NTab, NRadioGroup, NRadio, NCheckboxGroup, NCheckbox, NDataTable } from 'naive-ui';
import { BaseButton, RecodeCardItem, TheSubMenu, TheChatView, ChatWelcome, SvgIcon } from '@/components';
import { ChatAsk, ChatAnswer } from '@/components/Chat';
import { orderApi } from "@/api/order";
import { chatApi } from '@/api/chat';
import { formatEchart, isNumberComprehensive } from '@/utils/format';
import { ORDER_OPTION_ENUM } from '@/utils/enum';
import { getOrderAreaOptions } from './config/echartOptions'
import * as echarts from 'echarts';
import dayjs from 'dayjs';

import { useInfinite, useScroll, useChat } from '@/composables';

const { recordList, isFetching, onScrolltolower, onReset } = useInfinite('/front/bigModel/qa/pageList', { module: 1 });
const { scrollRef, scrollToBottom, scrollToBottomIfAtBottom, scrollToTop } = useScroll();
const { chatDataSource, addChat, updateChat, clearChat, updateById } = useChat();

let controller = new AbortController();
let timer = null;

const ANSWER_ID_KEY = '@@id@@';

const chartInstance = {};

const message = useMessage();
const reportDate = ref();

const workOrderParams = ref({
  timeBegin: null,
  timeEnd: null,
  whichWay: 1,
  checkGroup: [],
})

const switchActive = ref(false);
const tabActive = ref("daily");

const isLoading = ref(false);
const recordActive = ref(null);

const currenSessionId = ref(null);

const catalogData = ref([]);

const isExistInHistory = computed(() => (recordList.value.findIndex(({ sessionId: sId }) => sId === unref(currenSessionId)) === -1));
const isChart = computed(() => tabActive.value == 'customDaily');
const chatDataSourceItem = computed(() => unref(chatDataSource)[chatDataSource.value.length - 1]);

// 目录版块
provide('updateCatalog', (val) => {
  catalogData.value = val;
})

const resetFormData = () => {
  workOrderParams.value = {
    timeBegin: null,
    timeEnd: null,
    whichWay: 1,
    checkGroup: [],
  }
}

const resetState = () => {
  tabActive.value = 'daily';

  currenSessionId.value = null;

  recordActive.value = null;

  reportDate.value = null;

  resetFormData();

  clearChat();
}

// 新建对话
const handleCreateDialog = async () => {
  message.destroyAll();

  if (unref(isLoading)) {
    return message.warning('当前对话生成中');
  }

  if (!unref(chatDataSource).length) {
    return message.info('已切换最新会话');
  }
  
  catalogData.value = [];

  resetState();
}

// 查询对话详情
const handleChatDetail = async ({ sessionId }) => {
  isLoading.value = false;

  controller.abort();

  if(currenSessionId.value === sessionId) return;

  recordActive.value = sessionId;

  const { data } = await chatApi.getAnswerHistoryDetail({ sessionId });

  let echartData = [];
  let whichWay = null;
  chatDataSource.value = data.map(item => {
    if ( item.remark ) {
      const remark = JSON.parse(item.remark);
      whichWay = remark.whichWay;
      echartData = item.echartWithTableData = formatData(remark);
    }

    return { ...item, loading: false };
  })
 
  echartData.length && createEchart(echartData, whichWay);

  currenSessionId.value = sessionId;

  resetFormData();

  scrollToTop();
}

// 请求
const onRegenerate = async (question, options) => {
  controller = new AbortController();

  const sessionId = unref(currenSessionId);
  const params = {
    data: {
      sessionId,
      showVal: question,
      question,
      module: 1,
      isStrong: Number(unref(switchActive)),
      reportDate: reportDate.value,
      ...options,
    },
    signal: controller.signal,
    onDownloadProgress: ({ event }) => {
      const xhr = event.target;
      const { responseText } = xhr;
      const [answer] = responseText.split(ANSWER_ID_KEY);

      updateChat({
        ...chatDataSourceItem.value,
        sessionId,
        showVal: question,
        answer,
        loading: true,
        delayLoading: false,
        innerLoading: false
      })

      scrollToBottomIfAtBottom();
    }
  }

  try {
    const { data } = await chatApi.getChatStream(params);

    const [answer, id] = data.split(ANSWER_ID_KEY);

    updateChat({
      ...chatDataSourceItem.value,
      id,
      sessionId,
      showVal: question,
      answer,
      loading: false,
      delayLoading: false,
      innerLoading: false
    })

    scrollToBottomIfAtBottom();
  }
  catch (error) {
    console.log("取消了请求 - catch", error);
  }
  finally {
    isLoading.value = false;
    onReset();
  }
}

// 提交问题
const handleSubmit = async (question, params) => {

  if (unref(isExistInHistory)) {
    const { data: sessionId } = await chatApi.getChatSessionTag();
    currenSessionId.value = sessionId;
  }

  isLoading.value = true;

  const option = {
    sessionId: unref(currenSessionId),
    showVal: question,
    answer: '',
    loading: true,
    delayLoading: true,
    echartWithTableData: []
  }

  if (isChart.value) {
    const { data } = await orderApi.postOrderChart(params);
    const reuslt = formatData({...data, whichWay: workOrderParams.value.whichWay});

    option.echartWithTableData = reuslt;
  }

  addChat({
    ...option,
    innerLoading: true,
  });

  timer = setTimeout(() => {

    updateChat({
      ...chatDataSourceItem.value,
      delayLoading: true,
      innerLoading: false,
    })

    createEchart(option.echartWithTableData, workOrderParams.value.whichWay);
      
    scrollToBottom();

    onRegenerate(question, params);
    
  }, 2 * 1000);
}

// 处理推荐问题
const handleCreateOrder = async () => {
  const { timeBegin, timeEnd, whichWay, checkGroup } = unref(workOrderParams);
  const startDateTime = dayjs(timeBegin);
  const endDateTime = dayjs(timeEnd);
  let params = {};

  let question = `${reportDate.value}智慧工单分析报告`;

  if (tabActive.value === 'customDaily') {
    const thirtyDaysBeforeEndTime = endDateTime.subtract(31, 'day');
    const isStartAfterThirtyDaysBeforeEnd = startDateTime.isAfter(thirtyDaysBeforeEndTime);

    if (!timeBegin) return message.warning('请选择开始日期');
    if (!timeEnd) return message.warning('请选择结束日期');
    if (!isStartAfterThirtyDaysBeforeEnd) return message.warning('只可生成一个月区间的工单报告');
    if (!checkGroup.length) return message.warning('请至少选择一项指标项');
    
    params = {
      timeBegin,
      timeEnd,
      whichWay
    }
    checkGroup.forEach(key => params[key] = true);

    question = `${startDateTime.format("MM月DD日")}-${endDateTime.format("MM月DD日")}的在线仪表的日报工单`

  } else {

    if (!reportDate.value) return message.warning('请选择时间');

  }

  handleSubmit(question, params)
}

// 创建echart图形
const createEchart = (echartData, whichWay) => {
  setTimeout(() => {
    echartData.forEach(({ key, xAxisData, yAxisData,  }) => {
      const dom = document.getElementById(key);
      chartInstance[key] = echarts.init(dom, null, { width: 680, height: 300 });
    
      const option = getOrderAreaOptions({ xAxisData, yAxisData, whichWay });
    
      chartInstance[key].setOption(option);
    })
  })
}

// 格式化 echart 和 table 数据
const formatData = (data) => {
  const titleEnum = {
    jsGroup: '进水指标',
    csGroup: '出水指标',
    hyGroup: '化验指标'
  }
  const { whichWay, jsGroup, csGroup, hyGroup } = data;
  return Object.entries({jsGroup, csGroup, hyGroup}).map(([key, value]) => {
    if ( value.length ) {
      const [ xAxisData, yAxisData ] = formatEchart(value);
      const [ item ] = value; 
      const columns = Object.keys(item).map(k => {
        const wihteKeyList = ['jsSlq', 'csSlqc'];
        let unit = '';

        if(wihteKeyList.includes(k)) {
          unit = whichWay === 1? '(m³/h)' : '(m³/d)';
        } else if (k !== 'time') {
          unit= '(mg/L)';
        }

        return {
          title: ORDER_OPTION_ENUM[k] + unit,
          key: k,
          width: '150px',
          align: 'center'
        }
      })
      const data = value.map(item => {
        Object.entries(item).forEach(([k, v]) => {
          !v && v!=0 && (item[k] = '-');
          if (isNumberComprehensive(v)) {
            item[k] = v ? Number(v.toFixed(2)) : 0
          }
        })
        return item;
      })

      return {
        key: key,
        title: titleEnum[key],
        xAxisData,
        yAxisData,
        columns,
        data
      }
    }
  }).filter(Boolean);
}

// 返回
const handleback = async () => {
  catalogData.value = [];
  clearInterval(timer);
  await chatApi.getStopChatStream(currenSessionId.value);
  resetState();
}

// 删除历史对话
const handeChatDelete = async (id) => {
  await chatApi.deleteHistory(id);
  catalogData.value = [];
  onReset();
  clearChat();
  message.success('删除成功');
}

const handleTabChange = (val) => {
  tabActive.value = val;
}

const dateStartDisabled = (timestamp) => {
  const { timeEnd } = workOrderParams.value;
  if (timeEnd) {
    const currentDate = dayjs(timestamp);
    const endDateValue = dayjs(timeEnd);
    return !currentDate.isBefore(endDateValue);
  }
}

const dateEndDisabled = (timestamp) => {
  const { timeBegin } = workOrderParams.value;
  if (timeBegin) {
    const currentDate = dayjs(timestamp);
    const endDateValue = dayjs(timeBegin);
    return !currentDate.isAfter(endDateValue);
  }
}

onUnmounted(() => {
  controller.abort();
  Object.keys(chartInstance).forEach(key => chartInstance[key].clear());
})
</script>

<template>
  <section class="flex items-start h-full">

    <TheSubMenu title="智能工单" @scrollToLower="onScrolltolower" :loading="isFetching">
      <template #top>
        <div class="create-btn px-[11px] pb-[22px]">
          <BaseButton @click="handleCreateDialog" icon-name="tool-add-circle">新建工单</BaseButton>
        </div>
      </template>

      <div class="pr-[4px] text-[#5e5e5e]">
        <p v-show="!recordList.length" class="pt-[30px] text-[12px] text-[#999] text-center">暂无工单数据</p>
        <RecodeCardItem v-for="item, index in recordList" :key="item.sessionId + index" :title="item.showVal"
          :time="item.createTime" :data-item="item"
          :class="{ 'recode-card-item_active': recordActive === item.sessionId }" @on-click="handleChatDetail"
          @on-delete="handeChatDelete" />
      </div>
    </TheSubMenu>

    <TheChatView ref="scrollRef" :is-footer="false" :is-back-btn="!!chatDataSource.length" @on-click-back="handleback" :catalog-data="catalogData">
      
      <template #catalog>
        <ChatTree :data="catalogData"></ChatTree>
      </template>

      <ChatWelcome title="您好，我是LibraAI智慧工单助手" :sub-title="[
        '基于大语言模型的智能工单分析助手，可以为您实现数据分析及数据解读',
        '选择日期并为您生成日报分析'
      ]" v-if="!chatDataSource.length" />
  
      <div class="conversation-item" v-show="chatDataSource.length">
        <div v-for="item in chatDataSource" :key="item.sessionId">
          <ChatAsk :content="item.showVal" :sessionId="item.sessionId"></ChatAsk>
          <ChatAnswer
            :id="item.id"
            :content="item.answer"
            :loading="item.loading"
            :delay-loading="item.delayLoading"
            :isSatisfied="item.isSatisfied"
            :toggleVisibleIcons="false"
            loadingText="数据分析中，由于数据查询需要一些时间，请您耐心等候..."
            @on-click-icon="params => updateById(params)"
          >
            <main v-show="!item.innerLoading">
              <div 
                class="area_inner"
                v-for="(item, index) in item.echartWithTableData"
                :key="index"
              >
                <div class="echart-warpper" >
                  <span class="mb-[10px] #1A2029 font-bold">{{ item.title }}</span>
                  <div :id="item.key" class="w-[680px] h-[300px]"></div>
                </div>
                
                <div class="w-[680px]" style="max-width: 680px; overflow-x: auto;">
                  <NDataTable
                    bordered
                    size="small"
                    :scroll-x="item.columns.length > 4 ? 1200: 670"
                    :max-height="250"
                    :single-line="false"
                    :columns="item.columns"
                    :data="item.data"
                  >
                    <template #empty>
                      <span class="leading-[32px]">暂无数据</span>
                    </template>
                  </NDataTable>
                </div>
              </div>
            </main>
          </ChatAnswer>
        </div>
      </div>

      <div class="order-container px-[60px] py-[30px] mt-[36px] rounded-[10px] bg-[#fff]" v-if="!chatDataSource.length">
        <div
          class="flex items-center justify-start space-x-[24px] pb-[20px] border-b-[1px] border-solid border-[#F1F1F1]">
          <n-tabs type="segment" animated style="width: 188px;" size="large" :on-update:value="handleTabChange">
            <n-tab name="daily">日报工单</n-tab>
            <n-tab name="customDaily">自定义工单</n-tab>
          </n-tabs>
          <span class="text-[12px] text-[#8F959C]">
            {{ tabActive === 'daily' ? '选择日期后为您生成日报工单' : '选择内容后为您生成工单' }}
          </span>
        </div>

        <main class="order pt-[20px] text-[#1A2029]" v-show="tabActive === 'daily'">
          <div class="flex items-center justify-start text-[16px] space-x-[16px]">
            <span class="font-bold">选择时间</span>
            <div class="w-[164px] border-[1px] border-[#EFEFF0] rounded-[8px] overflow-hidden">
              <NDatePicker placeholder="选择日期" :readonly="true" v-model:formatted-value="reportDate"
                value-format="yyyy-MM-dd">
                <template #date-icon>
                  <SvgIcon name="tool-arrow-bottom"></SvgIcon>
                </template>
              </NDatePicker>
            </div>
          </div>

          <dl class="pt-[20px] text-[#1A2029] space-y-[16px]">
            <dt class="text-[16px] font-bold leading-[22px]">报告内容</dt>
            <dd>1、水质数据、生化数据情况</dd>
            <dd>2、各项指标数据分析</dd>
            <dd>3、对于工艺调整方面、数据趋势方面的措施与建议</dd>
          </dl>
        </main>

        <main class="order pt-[20px] text-[#1A2029]" v-show="tabActive === 'customDaily'">
          <div class="flex items-center justify-start mb-[20px] text-[16px] space-x-[16px]">
            <span class="font-bold">选择时间</span>
            <div class="w-[164px] border-[1px] border-[#EFEFF0] rounded-[8px] overflow-hidden">
              <NDatePicker placeholder="开始日期" :readonly="true" v-model:formatted-value="workOrderParams.timeBegin"
                value-format="yyyy-MM-dd" :is-date-disabled="dateStartDisabled">
                <template #date-icon>
                  <SvgIcon name="tool-arrow-bottom"></SvgIcon>
                </template>
              </NDatePicker>
            </div>
            <span class="text-[16px] text-[#8F959C]">至</span>
            <div class="w-[164px] border-[1px] border-[#EFEFF0] rounded-[8px] overflow-hidden">
              <NDatePicker placeholder="结束日期" :readonly="true" v-model:formatted-value="workOrderParams.timeEnd"
                value-format="yyyy-MM-dd" :is-date-disabled="dateEndDisabled">
                <template #date-icon>
                  <SvgIcon name="tool-arrow-bottom"></SvgIcon>
                </template>
              </NDatePicker>
            </div>
          </div>

          <div class="flex items-center justify-start mb-[20px] text-[16px] space-x-[16px]">
            <span class="font-bold">统计方式</span>
            <n-radio-group v-model:value="workOrderParams.whichWay" name="radiogroup2">
              <n-radio :value="1">在线仪表</n-radio>
              <n-radio :value="0">日报</n-radio>
            </n-radio-group>
          </div>

          <div class="flex items-center justify-start mb-[20px] text-[16px] space-x-[16px]">
            <span class="font-bold">进水指标</span>
            <n-checkbox-group v-model:value="workOrderParams.checkGroup" name="radiogroup2">
              <n-checkbox value="jsSlq">进水水量</n-checkbox>
              <n-checkbox value="jsCod">COD</n-checkbox>
              <n-checkbox value="jsTn">总氮</n-checkbox>
              <n-checkbox value="jsTp">总磷</n-checkbox>
              <n-checkbox value="jsNh3">氨氮</n-checkbox>
              <n-checkbox value="jsSs">SS</n-checkbox>
            </n-checkbox-group>
          </div>

          <div class="flex items-center justify-start mb-[20px] text-[16px] space-x-[16px]">
            <span class="font-bold">出水指标</span>
            <n-checkbox-group v-model:value="workOrderParams.checkGroup" name="radiogroup2">
              <n-checkbox value="csSlqc">出水水量</n-checkbox>
              <n-checkbox value="csCod">COD</n-checkbox>
              <n-checkbox value="csTn">总氮</n-checkbox>
              <n-checkbox value="csTp">总磷</n-checkbox>
              <n-checkbox value="csNh3">氨氮</n-checkbox>
              <n-checkbox value="csSs">SS</n-checkbox>
            </n-checkbox-group>
          </div>

          <div class="flex items-start justify-start mb-[20px] text-[16px] space-x-[16px]">
            <span class="font-bold">化验指标</span>
            <div class="w-[500px]">
              <n-checkbox-group v-model:value="workOrderParams.checkGroup" name="radiogroup2">
                <n-checkbox value="no3Hlj1Jqr">1#好氧池硝酸盐</n-checkbox>
                <n-checkbox value="no3Hlj2Jqr">2#好氧池硝酸盐</n-checkbox>
                <n-checkbox value="nh31Jqr">1#缺氧氨氮</n-checkbox>
                <n-checkbox value="nh32Jqr">2#缺氧氨氮</n-checkbox>
                <n-checkbox value="no3Qyc1Jqr">1#缺氧池硝酸盐</n-checkbox>
                <n-checkbox value="no3Qyc2Jqr">2#缺氧池硝酸盐</n-checkbox>
                <n-checkbox value="tpRccJqr">二沉池正磷酸盐</n-checkbox>
              </n-checkbox-group>
            </div>
          </div>

          <dl class="text-[#1A2029] space-y-[16px]">
            <dt class="text-[16px] font-bold leading-[22px]">报告内容</dt>
            <dd>1、数据情况</dd>
            <dd>2、各项指标数据分析及措施与建议</dd>
          </dl>
        </main>

        <footer class="pt-[24px]">
          <button class="btn-primary" @click="handleCreateOrder">立即生成</button>
        </footer>
      </div>

    </TheChatView>
  </section>
</template>

<style scoped lang="scss">
.n-input__input-el {
  font-size: 12px !important;
}

.area_inner {
  display: flex;
  align-items: center;
  flex-flow: column;
  padding-bottom: 20px;
  border-radius: 8px;
  margin-bottom: 20px;
  background: #eff8fc;
}

.list-item {
  margin-bottom: 16px;

  .title {
    font-size: 14px;
    font-weight: bold;
    line-height: 20px;
  }

  .item-top {
    display: flex;
    justify-content: space-between;
    margin-bottom: 10px;

    .num {
      font-size: 12px;
      font-weight: 400;
      color: #B0B7C0;
    }
  }
}


.btn-primary {
  width: 88px;
  height: 32px;
  border-radius: 6px;
  background-color: #2454FF;
  font-size: 14px;
  line-height: 32px;
  color: #fff;

  &:hover {
    background: #1D43CC;
  }
}

.echart-warpper {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-flow: column;
  width: 100%;
  padding: 20px 0;
  border-radius: 8px;
}
</style>

<style lang="scss">
.order {

  .n-input__input-el,
  .n-input__placeholder {
    font-size: 14px;
  }
}

.order-container {
  .n-tabs-tab__label {
    font-size: 14px !important;
    font-weight: bold;
    color: #5E5E5E;
  }

  .n-tabs-tab--active {
    .n-tabs-tab__label {
      color: #1A2029;
    }
  }
}
</style>