<template>
  <div class="archive-main">
    <HeadMenu/>
    <div class="archive-content">
      <div class="archive-basic" v-if="themeConfigCpt.main.indexStyle" v-loading="state.mainObj.loading">
        <div class="archive-basic-title">
          <SvgIcon class="flag" name="flag_1" color="var(--cus-main-color)"/>
          <span class="main">{{state.mainObj.data[themeConfigCpt.main.indexStyle.mainParam]}}</span>
          <template v-for="k in themeConfigCpt.main.indexStyle.tagParams">
            <span class="tag" v-if="state.mainObj.data[k]">{{ state.mainObj.data[k] }}</span>
          </template>
        </div>
        <div class="archive-basic-sub" v-if="themeConfigCpt.main.indexStyle.subParams?.length > 0">
          <template v-for="(k, i) in themeConfigCpt.main.indexStyle.subParams">
            <span>{{ state.mainObj.data[k] }}</span>
            <span class="line" v-if="i < themeConfigCpt.main.indexStyle.subParams.length - 1"/>
          </template>
        </div>
        <div class="archive-basic-avatar" v-if="themeConfigCpt.main.indexStyle.imgParam">
          <el-image
            :src="state.mainObj.data[themeConfigCpt.main.indexStyle.imgParam]"
            :zoom-rate="1.2"
            :max-scale="7"
            :min-scale="0.2"
            :preview-src-list="[state.mainObj.data[themeConfigCpt.main.indexStyle.imgParam]]"
            :preview-teleported="true"
          >
            <template #error>
              <div class="image-slot">
                <img src="../../../assets/images/web/archive-main-img.png" alt="暂无图片"/>
              </div>
            </template>
          </el-image>
        </div>
        <div class="archive-basic-cols" v-if="themeConfigCpt.main.indexStyle.otherParams?.length > 0">
          <template v-for="item in themeConfigCpt.main.indexStyle.otherParams">
            <div class="cols-item">
              <div class="label">{{ item.label }}</div>
              <div class="value">{{ state.mainObj.data[item.value] }}</div>
            </div>
          </template>
        </div>
      </div>
      <div class="archive-list">
        <el-tabs v-model="state.activeTab" class="archive-list-tabs">
          <el-tab-pane label="首页" name="首页"/>
          <template v-for="([key, value], index) in themeConfigCpt.tabs">
            <el-tab-pane :label="value.indexNameShort || value.indexName" :name="key"/>
          </template>
        </el-tabs>
        <template v-if="state.activeTab === '首页'">
          <div class="archive-list-block">
            <div class="archive-list-block-title">
              <SvgIcon class="flag" name="flag_1" color="var(--cus-main-color)"/>关系图谱
              <el-tooltip :content="state.chartData.showZero ? '点击切换隐藏空节点' : '点击切换显示空节点'" placement="top">
                  <SvgIcon style="margin-left: 6px" class="__hover" :name="state.chartData.showZero ? 'show' : 'hide'" color="var(--cus-text-color-2)" size="14" @click="state.chartData.showZero = !state.chartData.showZero"/>
              </el-tooltip>
              <div class="layout-select">
                <CusFormColumn
                  :span="24"
                  v-model:param="state.chartData.layout"
                  link="select"
                  :options="DictionaryStore.relationChartLayoutList"
                />
              </div>
            </div>
            <div class="archive-list-block-page" v-loading="state.chartData.loading">
              <RelationChart :data="state.chartData.data" :layout="state.chartData.layout" :show-zero="state.chartData.showZero" @chartPage="onChartPage"/>
            </div>
          </div>
          <div class="archive-list-block" v-if="state.chartTable.chartId">
            <div class="archive-list-block-title">
              <SvgIcon class="flag" name="flag_1" color="var(--cus-main-color)"/>
              {{ themeConfigCpt.chart.nodes.filter(v => v.id == state.chartTable.chartId)?.[0]?.name }}
            </div>
            <div class="archive-list-block-page" v-loading="state.chartTable.loading">
              <CusTable
                :page-num="state.chartTable.page.pageNum"
                :page-size="state.chartTable.page.pageSize"
                :total="state.chartTable.result.total"
                :data="state.chartTable.result.data"
                :table-head="state.chartTable.tableHead"
                @handlePage="onPageChart"
              >
              </CusTable>
            </div>
          </div>
        </template>
        <template v-else>
          <div class="archive-list-block">
            <div class="archive-list-block-title">
              <SvgIcon class="flag" name="flag_1" color="var(--cus-main-color)"/>
              {{ themeConfigCpt.tabs.get(state.activeTab)?.indexNameShort || themeConfigCpt.tabs.get(state.activeTab)?.indexName }}
            </div>
            <div class="archive-list-block-page" v-loading="state.tabTable.loading">
              <CusTable
                :page-num="state.tabTable.page.pageNum"
                :page-size="state.tabTable.page.pageSize"
                :total="state.tabTable.result.total"
                :data="state.tabTable.result.data"
                :table-head="state.tabTable.tableHead"
                @handlePage="onPage"
                :page-sizes="[20, 40, 60, 80, 100]"
              >
              </CusTable>
            </div>
          </div>
        </template>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import {computed, getCurrentInstance, onMounted, reactive, watch} from "vue";
import RelationChart from "./relation-chart.vue";
import {ElLoading, ElMessage} from "element-plus";
import {useAppStore, useDictionaryStore, useThemeStore} from "@/stores";
import {frontGetThemeByThemeId, searchLogsSaveSearchLog} from "@/api/modules/web/list";
import {useRoute} from "vue-router";
import WorkerWebsocket from "@/worker/worker-websocket?sharedworker";

const ThemeStore = useThemeStore()
const DictionaryStore = useDictionaryStore()
const AppStore = useAppStore()
const route = useRoute()
const {proxy} = getCurrentInstance()
const state: any = reactive({
  activeTab: '',
  tabTable: {
    loading: false,
    page: {
      pageNum: 1,
      pageSize: 20
    },
    tableHead: [],
    result: {
      total: 0,
      data: []
    },
  },
  chartTable: {
    chartId: '',
    loading: false,
    page: {
      pageNum: 1,
      pageSize: 10
    },
    tableHead: [],
    result: {
      total: 0,
      data: []
    },
  },
  chartData: {
    loading: false,
    data: {
      nodes: [],
      edges: []
    },
    layout: 'radial',
    showZero: false,
  },
  ws: {
    getMain: () => {},
    tabPage: () => {},
    getChart: () => {},
    chartPage: () => {},
    loading: null,
    loadingTimer: null
  },
  themeDetail: {},
  mainObj: {
    loading: false,
    data: {}
  }
})
const themeConfigCpt = computed(() => {
  const getSearchParam = (item) => {
    // es查询参数
    const param = {}
    if (item.type === 'inner_index') {
      param.indexCode = item.indexTableName
      if (item.indexOrder) {
        const obj = {}
        JSON.parse(item.indexOrder).forEach(s => {
          obj[s.sortParam] = s.sortType
        })
        param.orderBy = obj
      }
      if (item.indexCondition) {
        const arr: any = []
        JSON.parse(item.indexCondition).forEach(s => {
          arr.push({
            fieldCode: s.indexParam,
            fieldQueryType: s.condition,
            fieldQueryValue: route.query[s.themeParam]
          })
        })
        param.datas = arr
      }
    } else {
      param.serviceId = item.indexId
      if (item.indexCondition) {
        const obj: any = {}
        JSON.parse(item.indexCondition).forEach(s => {
          obj[s.indexParam] = route.query[s.themeParam] || ''
        })
        param.serviceMap = obj
      }
    }
    return param
  }
  const getTableHead = (item) => {
    const arr: any = []
    item.indexFields.forEach(v => {
      arr.push({value: v.fieldKey, label: v.fieldName})
    })
    return arr
  }
  const getSex = (idCard: string) => {
    if (idCard.length !== 18) {
      throw new Error("身份证号码长度不正确");
    }
    const genderDigit = parseInt(idCard.charAt(16), 10);
    return genderDigit % 2 === 1 ? "男" : "女";
  }
  const res = {
    main: <any>{
      indexStyle: {}
    },
    tabs: new Map(),
    chart: {
      nodes: <any>[],
      edges: <any>[],
    }
  }
  state.themeDetail.indexDtos?.forEach(v => {
    if (v.isMain == 1) {
      state.chartData.layout = v.chartLayout
      res.main = {
        __type: v.type,
        indexTableName: v.indexTableName,
        indexId: v.indexId,
        indexStyle: v.indexStyle ? JSON.parse(v.indexStyle) : '',
        searchParam: getSearchParam(v),
        tableHead: getTableHead(v),
      }
      const node = {
        id: String(v.id),
        iconSrc: v.url,
        iconSize: v.iconSize,
        weight: v.weight || 100,
        num: 0,
        name: v.indexNameShort,
        __type: v.type,
        indexTableName: v.indexTableName,
        indexId: v.indexId,
        searchParam: getSearchParam(v),
        tableHead: getTableHead(v),
      }
      try {
        JSON.parse(v.indexCondition).forEach(c => {
          if (c.paramType == 'sex') {
            const sex = getSex(route.query[c.themeParam])
            if (sex == '男') {
              node.iconSrc = c.sexImgs[0].url
            } else if (sex == '女') {
              node.iconSrc = c.sexImgs[1].url
            }
          }
        })
      } catch (e) {
        console.error(e)
      }
      res.chart.nodes.unshift(node)
    } else if (v.relateIndexId) {
      const node = {
        id: String(v.id),
        iconSrc: v.url,
        iconSize: v.iconSize,
        weight: v.weight,
        num: 0,
        name: v.indexNameShort,
        __type: v.type,
        indexTableName: v.indexTableName,
        indexId: v.indexId,
        searchParam: getSearchParam(v),
        tableHead: getTableHead(v),
      }
      try {
        JSON.parse(v.indexCondition).forEach(c => {
          if (c.paramType == 'sex') {
            const sex = getSex(route.query[c.themeParam])
            if (sex == '男') {
              node.iconSrc = c.sexImgs[0].url
            } else if (sex == '女') {
              node.iconSrc = c.sexImgs[1].url
            }
          }
        })
      } catch (e) {
        console.error(e)
      }
      res.chart.nodes.push(node)
      res.chart.edges.push({source: String(v.relateIndexId), target: String(v.id), labelText: v.description || '关系描述'})
    } else {
      res.tabs.set(v.id, {
        __type: v.type,
        indexName: v.indexName,
        indexNameShort: v.indexNameShort,
        indexTableName: v.indexTableName,
        indexId: v.indexId,
        searchParam: getSearchParam(v),
        tableHead: getTableHead(v),
      })
    }
  })
  console.log(res)
  return res
})
const onPage = (pageNum, pageSize) => {
  state.tabTable.page = {
    pageNum: pageNum,
    pageSize: pageSize
  }
  state.ws.tabPage()
}
const onPageChart = (pageNum, pageSize) => {
  state.chartTable.page = {
    pageNum: pageNum,
    pageSize: pageSize
  }
  state.ws.chartPage()
}
const onChartPage = (id) => {
  state.chartTable = {
    chartId: id,
    loading: false,
    page: {
      pageNum: 1,
      pageSize: 10
    },
    tableHead: themeConfigCpt.value.chart.nodes.filter(v => v.id == id)?.[0]?.tableHead,
    result: {
      total: 0,
      data: []
    },
  }
  state.ws.chartPage()
}
const initTheme = () => {
  const loading = ElLoading.service({
    lock: true,
    text: '获取主题中……',
    background: ThemeStore.loadingBg
  })
  frontGetThemeByThemeId(route.query.themeId).then(res => {
    state.themeDetail = res.data
    loading.close()
    initWorker()
  })
}
watch(() => state.activeTab, (n) => {
  if (n === '首页') {
    state.chartTable.chartId = ''
    state.ws.getChart()
  } else {
    state.tabTable = {
      loading: false,
      page: {
        pageNum: 1,
        pageSize: 20
      },
      tableHead: themeConfigCpt.value.tabs.get(n).tableHead,
      result: {
        total: 0,
        data: []
      },
    }
    state.ws.tabPage()
  }
})
const initWorker = () => {
  const loading = ElLoading.service({
    lock: true,
    text: '搜索服务连接中……',
    background: ThemeStore.loadingBg
  })
  let sessionId = ''
  let lastTabParams = ''
  let lastMainParams = ''
  let lastChartParams = ''
  let lastChartPageParams = ''
  const worker = new WorkerWebsocket()
  worker.port.onmessage = (e) => {
    const data = JSON.parse(e.data)
    switch (data.type) {
      case 'load': {
        worker.port.postMessage(JSON.stringify({type: 'init', userId: AppStore.userInfo.id}))
      } break
      case 'onopen': {
        loading.close()
        state.ws.loading?.close()
        state.ws.loading = null
        state.ws.getMain = () => {
          // 如果有的话，终止上一次请求
          if (lastMainParams) {
            const p = JSON.parse(lastMainParams)
            p.flag = 'stop'
            worker.port.postMessage(JSON.stringify({type: 'send', data: p}))
            lastMainParams = ''
          }
          const params = {
            __type: themeConfigCpt.value.main.__type,
            pageNumber: 1,
            pageSize: 1,
            type: 'list-fix',
            sessionId: sessionId,
            timestamp: new Date().getTime(),
            flag: 'run',
            orderBy: {},
            builder:[
              {
                tagCode: '',
                datas:[
                  {
                    typeCode: '',
                    datas: [themeConfigCpt.value.main.searchParam]
                  }
                ]
              }
            ],
          }
          lastMainParams = JSON.stringify(params)
          state.mainObj.loading = true
          worker.port.postMessage(JSON.stringify({type: 'send', data: lastMainParams}))
        }
        state.ws.tabPage = () => {
          // 如果有的话，终止上一次请求
          if (lastTabParams) {
            const p = JSON.parse(lastTabParams)
            p.flag = 'stop'
            worker.port.postMessage(JSON.stringify({type: 'send', data: p}))
            lastTabParams = ''
          }
          const params = {
            __type: themeConfigCpt.value.tabs.get(state.activeTab).__type,
            pageNumber: state.tabTable.page.pageNum,
            pageSize: state.tabTable.page.pageSize,
            type: 'list-fix',
            sessionId: sessionId,
            timestamp: new Date().getTime(),
            flag: 'run',
            builder:[
              {
                tagCode: '',
                datas:[
                  {
                    typeCode: '',
                    datas: [themeConfigCpt.value.tabs.get(state.activeTab).searchParam]
                  }
                ]
              }
            ],
          }
          lastTabParams = JSON.stringify(params)
          state.tabTable.loading = true
          worker.port.postMessage(JSON.stringify({type: 'send', data: lastTabParams}))
        }
        state.ws.getChart = () => {
          // 如果有的话，终止上一次请求
          if (lastChartParams) {
            const p = JSON.parse(lastChartParams)
            p.flag = 'stop'
            worker.port.postMessage(JSON.stringify({type: 'send', data: p}))
            lastChartParams = ''
          }
          const params = {
            pageNumber: state.tabTable.page.pageNum,
            pageSize: state.tabTable.page.pageSize,
            type: 'count-fix',
            sessionId: sessionId,
            timestamp: new Date().getTime(),
            flag: 'run',
            builder:[
              {
                tagCode: '',
                datas:[
                  {
                    typeCode: '',
                    datas: themeConfigCpt.value.chart.nodes.map(v => {
                      const obj = {...v.searchParam}
                      if (obj.indexCode) {
                        obj.indexCode += '|' + v.id
                      } else if (obj.serviceId) {
                        obj.serviceId += '|' + v.id
                      }
                      return obj
                    })
                  }
                ]
              }
            ]
          }
          lastChartParams = JSON.stringify(params)
          state.chartData.loading = true
          worker.port.postMessage(JSON.stringify({type: 'send', data: lastChartParams}))
        }
        state.ws.chartPage = () => {
          // 如果有的话，终止上一次请求
          if (lastChartPageParams) {
            const p = JSON.parse(lastChartPageParams)
            p.flag = 'stop'
            worker.port.postMessage(JSON.stringify({type: 'send', data: p}))
            lastChartPageParams = ''
          }
          const params = {
            __type: themeConfigCpt.value.chart.nodes.filter(v => v.id == state.chartTable.chartId)[0].__type,
            pageNumber: state.chartTable.page.pageNum,
            pageSize: state.chartTable.page.pageSize,
            type: 'list-fix',
            sessionId: sessionId,
            timestamp: new Date().getTime(),
            flag: 'run',
            builder:[
              {
                tagCode: '',
                datas:[
                  {
                    typeCode: '',
                    datas: [themeConfigCpt.value.chart.nodes.filter(v => v.id == state.chartTable.chartId)[0].searchParam]
                  }
                ]
              }
            ],
          }
          lastChartPageParams = JSON.stringify(params)
          state.chartTable.loading = true
          worker.port.postMessage(JSON.stringify({type: 'send', data: lastChartPageParams}))
        }
      } break
      case 'onmessage': {
        try {
          const json = JSON.parse(data.data)
          console.log(json)
          if (json.respCode == -1) {
            ElMessage.error(json.respMsg)
            return
          }
          if (json.type === 'session') {
            sessionId = json.sessionId
            // 左侧
            state.ws.getMain()
            state.activeTab = '首页'
          } else {
            switch (json.type) {
              case 'list-fix': {
                if (lastMainParams) {
                  const pMain = JSON.parse(lastMainParams)
                  // 返回为最新批次的
                  if (json.timestamp == pMain.timestamp) {
                    if (pMain.__type === 'inner_index') {
                      state.mainObj.data = json.datas?.[0] || {}
                    } else {
                      state.mainObj.data = json.datas.data?.[0] || {}
                    }
                    state.mainObj.loading = false
                    lastMainParams = ''
                  }
                }
                if (lastTabParams) {
                  const pTab = JSON.parse(lastTabParams)
                  // 返回为最新批次的
                  if (json.timestamp == pTab.timestamp) {
                    if (pTab.__type === 'inner_index') {
                      state.tabTable.result.data = json.datas
                      state.tabTable.result.total = json.records
                    } else {
                      state.tabTable.result.data = json.datas.data
                      state.tabTable.result.total = json.datas.pathForm.total
                    }
                    state.tabTable.loading = false
                    lastTabParams = ''
                  }
                }
                if (lastChartPageParams) {
                  const pChartPage = JSON.parse(lastChartPageParams)
                  // 返回为最新批次的
                  if (json.timestamp == pChartPage.timestamp) {
                    if (pChartPage.__type === 'inner_index') {
                      state.chartTable.result.data = json.datas
                      state.chartTable.result.total = json.records
                    } else {
                      state.chartTable.result.data = json.datas.data
                      state.chartTable.result.total = json.datas.pathForm.total
                    }
                    state.chartTable.loading = false
                    lastChartPageParams = ''
                  }
                }
              } break
              case 'count-fix': {
                if (lastChartParams) {
                  const pChart = JSON.parse(lastChartParams)
                  // 返回为最新批次的
                  if (json.timestamp == pChart.timestamp) {
                    const obj = {
                      edges: [...themeConfigCpt.value.chart.edges],
                      nodes: themeConfigCpt.value.chart.nodes.map(v => {
                        if (v.__type === 'inner_index') {
                          v.num = json.datas.filter(s => s.indexCode == (v.indexTableName + '|' + v.id))?.[0]?.data || 0
                        } else {
                          v.num = json.datas.filter(s => s.serviceId == (v.indexId + '|' + v.id))?.[0]?.data || 0
                        }
                        return v
                      })
                    }
                    state.chartData.data = obj
                    state.chartData.loading = false
                    lastChartParams = ''
                  }
                }
              } break
            }
          }
        } catch (e) {
          console.log(e)
        }
      } break
      case 'onclose': {
        state.ws.loading = ElLoading.service({
          lock: true,
          text: '智搜服务已断开，请刷新页面……',
          background: ThemeStore.loadingBg,
        })
      } break
    }
  }
}
onMounted(() => {
  initTheme()
  DictionaryStore.initDict('relation_chart_layout')
})
</script>

<style lang="scss" scoped>
.archive-main {
  width: 100%;
  height: 100%;
  background-color: #F6F7FB;
  display: flex;
  flex-direction: column;
  .archive-content {
    flex: 1;
    padding: 24px;
    display: flex;
    gap: 16px;
    overflow: hidden;
    .archive-basic {
      width: 362px;
      height: 100%;
      background: linear-gradient( 180deg, rgba(var(--cus-main-color-rgb), 0.2) 0%, rgba(var(--cus-main-color-rgb),0) 100%), #FFFFFF;
      box-shadow: 0px 2px 4px 0px rgba(46,129,255,0.2);
      border-radius: 4px;
      padding: 16px;
      display: flex;
      flex-direction: column;
      gap: 10px;
      .archive-basic-title {
        display: flex;
        align-items: center;
        gap: 8px;
        .main {
          font-weight: bold;
          font-size: 21px;
          color: var(--cus-main-color);
        }
        .tag {
          display: flex;
          align-items: center;
          justify-content: center;
          padding: 0 8px;
          background: #f8e5e5;
          border-radius: 2px;
          border: 1px solid #FF5454;
          font-size: 12px;
          color: #FF5454;
        }
      }
      .archive-basic-sub {
        display: flex;
        align-items: center;
        font-size: 14px;
        color: var(--cus-text-color-2);
        line-height: 16px;
        gap: 10px;
        .line {
          width: 1px;
          height: 10px;
          background-color: var(--cus-text-color-4);
        }
      }
      .archive-basic-avatar {
        width: 100%;
        .el-image {
          width: 100%;
          .image-slot {
            width: 100%;
            >img {
              width: 100%;
            }
          }
        }
      }
      .archive-basic-cols {
        display: flex;
        flex-wrap: wrap;
        row-gap: 12px;
        .cols-item {
          font-size: 14px;
          min-width: 50%;
          .label {
            font-weight: bold;
            color: var(--cus-text-color-1);
          }
          .value {
            margin-top: 2px;
            color: var(--cus-text-color-2);
            text-align: justify;
          }
        }
      }
    }
    .archive-list {
      flex: 1;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      :deep(.archive-list-tabs) {
        width: 100%;
        .el-tabs__header {
          margin: 0;
          height: 45px;
          .el-tabs__nav-wrap {
            height: 100%;
            &:after {
              display: none;
            }
            .el-tabs__nav-prev, .el-tabs__nav-next {
              height: 100%;
              display: flex;
              justify-content: center;
              align-items: center;
            }
            .el-tabs__nav-scroll {
              height: 100%;
              .el-tabs__nav {
                height: 100%;
                .el-tabs__item {
                  height: 100%;
                  font-size: 16px;
                  color: var(--cus-text-color-2);
                  padding: 0 16px;
                  &.is-active {
                    background-color: #FFFFFF;
                    box-shadow: 0px 4px 10px 0px rgba(62,123,250,0.1);
                    border-radius: 8px 8px 0px 0px;
                  }
                }
              }
            }
          }
        }
      }
      .archive-list-block {
        flex: 1;
        background-color: #FFFFFF;
        padding: 16px;
        display: flex;
        flex-direction: column;
        gap: 15px;
        overflow: hidden;
        &:first-child {
          border-top-right-radius: 8px;
        }
        &:last-child {
          border-bottom-left-radius: 8px;
          border-bottom-right-radius: 8px;
        }
        .archive-list-block-title {
          display: flex;
          align-items: center;
          font-weight: bold;
          font-size: 16px;
          color: var(--cus-text-color-1);
          .svg-icon {
            margin-right: 8px;
          }
          :deep(.layout-select) {
            margin-left: auto;
            .el-form-item {
              width: 150px;
              margin-bottom: 0;
            }
          }
        }
        .archive-list-block-page {
          flex: 1;
          overflow: hidden;
        }
      }
    }
  }
}
</style>
