<template>
  <div class="p-small radius-base fill-blank statistics-personnel">
    <base-table
      ref="tableRef"
      :key="tableKey"
      border
      stripe
      size="small"
      :data="sortTableData"
      :columns="columns"
      :height="tableHeight"
      :row-class-name="rowClassName"
      highlight-current-row
      :default-sort="defaultSort"
      @current-change="onCurrentChange"
      @row-dblclick="myDbClick"
      @row-contextmenu="rowContextmenu"
      @sort-change="sortChange"
    >
      <template #column-marker="{ row }">
        <!-- <el-popover
          v-if="row.markerId"
          :ref="(popover: any) => setPopoverRefs(row.markerId,popover)"
          trigger="contextmenu"
          placement="right"
          :show-arrow="false"
          transition="none"
          @show="onPopoverShow(row.markerId)"
        >
          <template #reference>
            <el-button size="small" link type="primary">{{ row.markerName }}</el-button>
          </template>
          <el-menu @select="() => {}">
            <el-menu-item index="setting" @click="onSetWorkload(row)">
              <el-button link>设置工作量</el-button>
            </el-menu-item>
            <el-menu-item index="send" @click="onSendMessage(row)">
              <el-button link>发送消息</el-button>
            </el-menu-item>
          </el-menu>
        </el-popover> -->
        <span v-if="row.markerId">
          <span
            :style="{
              backgroundColor: row.online ? '#00B42A' : '#ddd',
              display: 'inline-block',
              width: '10px',
              height: '10px',
              marginRight: '3px',
              borderRadius: '2px',
            }"
          ></span>
          {{ row.markerName }}</span
        >
        <span v-else-if="row.markingGroupNumber == 0">全体</span>
        <span v-else>全组</span>
      </template>
    </base-table>
  </div>
  <div
    v-if="!!current && !!current?.markerId && showCharts"
    v-loading="loading1 || loading2"
    class="flex justify-between charts-box"
  >
    <el-button type="primary" plain size="small" class="close-panel" @click="clearCheck">关闭</el-button>

    <div class="flex-1 p-base radius-base fill-blank m-r-base chart-box">
      <vue-e-charts class="full" :option="markerSubjectiveChartsOption"></vue-e-charts>
    </div>
    <div class="flex-1 p-base radius-base fill-blank chart-box">
      <vue-e-charts class="full" :option="markerObjectiveChartsOption"></vue-e-charts>
    </div>
  </div>
  <set-workload v-model="setWorkloadVisible" :data="setWorkloadData" />
  <right-key-menu
    v-show="visable"
    ref="rightKeyMenu"
    @right-click="rightClick"
    @on-set-workload="onSetWorkload"
    @on-send-message="onSendMessage"
    @force-assessment="forceAssessment"
    @on-show-score-lines="onShowScoreLines"
  ></right-key-menu>
</template>

<script setup lang="tsx" name="StatisticsPersonnel">
/** 人员数据统计-按人员展开 */
import { ref, inject, computed, watch, nextTick, unref } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { ElButton, ElPopover, ElMenu, ElMenuItem } from 'element-plus'
import VueECharts from 'vue-echarts'
import BaseTable from '@/components/element/BaseTable.vue'
import SetWorkload from './SetWorkload.vue'
import useVW, { usePX } from '@/hooks/useVW'
import useFetch from '@/hooks/useFetch'
import useTableCheck from '@/hooks/useTableCheck'
import RightKeyMenu from './RightKeyMenu.vue'
import useMainStore from '@/store/main'
import { cloneDeep } from 'lodash-es'
import type { EChartsOption } from 'echarts'
import type { ExtractApiResponse, ExtractApiParams } from '@/api/api'
import type { EpTableColumn } from 'global-type'
import type { PopoverInstance } from 'element-plus'
const tableKey = ref(Date.now() + '')
const mainStore = useMainStore()
const firstSorted = ref(false)
const isChief = computed(() => {
  const arr = ['CHIEF', 'SECTION_LEADER', 'EXPERT']
  return arr.indexOf(mainStore.myUserInfo?.role || '') > -1
})
const showCharts = ref(false)
const rightKeyMenu = ref(null)
const rightClick = () => {
  visable.value = false
}
const props = defineProps<{
  data: ExtractApiResponse<'getStatisticsByGroup'>
  params: ExtractApiParams<'getStatisticsByGroup'> & { expand: boolean }
  filterColumns?: any
  result?: any
}>()
const rowClassName = (obj: any) => {
  if (obj.row.markingGroupNumber === 0) {
    return 'fixed-row'
  } else if (obj.row.isGroupTotalRow) {
    return 'fixed-row2'
  }
}
const setMessageVisible = inject<(visible: boolean) => void>('setMessageVisible')
const setReplyUserId = inject<(id: number) => void>('setReplyUserId')

const { push } = useRouter()
const route = useRoute()
const defaultSort: any = ref(route.query?.sortKey ? { prop: route.query?.sortKey, order: 'descending' } : undefined)
const columns = computed(() => {
  return [
    {
      label: '#',
      type: 'index',
      width: 40,
      align: 'center',
      fixed: 'left',
      index(index: number) {
        return index + 1
      },
    },
    {
      label: '小组',
      prop: 'markingGroupNumber',
      width: 60,
      fixed: 'left',
      formatter(row: any) {
        return row.markingGroupNumber === 0 ? '全部' : `第${row.markingGroupNumber}组`
      },
    },
    { label: '评卷员', prop: 'markerName', minWidth: 100, slotName: 'marker', fixed: 'left' },

    { align: 'center', label: '份数', prop: 'markingPaperCount', minWidth: 80 },
    { align: 'center', label: '平均分', prop: 'avg', minWidth: 64 },
    {
      align: 'center',
      label: '相关系数',
      prop: 'xyRelate',
      minWidth: 80,
      formatter(row: any) {
        let r = unref(props.result) || []
        const { markingGroupNumber } = row
        let compareTarget = r.find((item: any) => item.markingGroupNumber == markingGroupNumber)
        let allTarget = r.find((item: any) => item.markingGroupNumber == 0)
        if (compareTarget && markingGroupNumber) {
          return (
            props.params.markingGroupNumber ? row.xyRelate < compareTarget.xyRelate : row.xyRelate < allTarget.xyRelate
          ) ? (
            <span style="color:red">{row.xyRelate}</span>
          ) : (
            row.xyRelate
          )
        } else {
          return row.xyRelate
        }
      },
    },
    { align: 'center', label: '标准差', prop: 'std', minWidth: 64 },
    { align: 'center', label: '综合系数', prop: 'integration', minWidth: 80 },

    // { align: 'center', label: '评卷份数', prop: 'markingPaperCount', width: 92 },
    { align: 'center', label: '当日可阅', prop: 'markDayCount', minWidth: 80 },
    { align: 'center', label: '剩余可阅', prop: 'todoMarkDayCount', minWidth: 80 },
    { align: 'center', label: '速度', prop: 'markingRate', minWidth: 56 },
    { align: 'center', label: '客观题0分量', prop: 'objectiveZero', minWidth: 104 },
    { align: 'center', label: '客观平均分', prop: 'objectiveAvg', minWidth: 94 },
    { align: 'center', label: '客观标准差', prop: 'objectiveStd', minWidth: 94 },
    {
      align: 'center',
      label: '重评/待确认',
      prop: 'reMarkUnConfirmCount',
      minWidth: 104,
      formatter(row: any) {
        return `${row.reMarkCount}/${row.reMarkUnConfirmCount}`
      },
    },
    { align: 'center', label: '抽查量', prop: 'checkCount', minWidth: 74 },
    { align: 'center', label: '抽查改正量', prop: 'checkCorrectCount', minWidth: 94 },
    // { align: 'center', label: '相关系数', prop: 'xyRelate', width: 90 },
    // { align: 'center', label: '平均分', prop: 'avg', width: 80 },
    // { align: 'center', label: '标准差', prop: 'std', width: 80 },
    { align: 'center', label: '近5分钟最高分', prop: 'scoreTop', minWidth: 114 },
    { align: 'center', label: '近5分钟最低分', prop: 'scoreLow', minWidth: 114 },
    { align: 'center', label: '近5分钟客主比', prop: 'objSubRate', minWidth: 114 },
    { align: 'center', label: '平均客主比', prop: 'objSubAvgRate', minWidth: 96 },
    {
      align: 'center',
      label: '在线',
      prop: 'online',
      minWidth: 56,
      formatter(row: any) {
        if (row.markingGroupNumber === 0) {
          let total = (unref(props.result) || [])
            .filter((item: any) => item.markingGroupNumber !== 0)
            .reduce((ar: any, item: any) => {
              return [...ar, ...(item.markerDetails || [])]
            }, [])
            .reduce((num: number, item: any) => {
              return num + (item.online ? 1 : 0)
            }, 0)
          return total + '人'
        } else if (row.isGroupTotalRow) {
          let total = (unref(props.result) || [])
            .filter((item: any) => item.markingGroupNumber == row.markingGroupNumber)
            .reduce((ar: any, item: any) => {
              return [...ar, ...(item.markerDetails || [])]
            }, [])
            .reduce((num: number, item: any) => {
              return num + (item.online ? 1 : 0)
            }, 0)
          return total + '人'
        } else {
          return row.online ? '在线' : '离线'
        }
      },
    },
    { align: 'center', label: '状态', prop: 'markingStatus', minWidth: 84 },

    // { align: 'center', label: '综合系数', prop: 'integration', width: 90 },
  ]
    .map((col: any) => {
      if (!['小组', '重评/待确认'].includes(col.label)) col.sortable = 'custom'
      return col
    })
    .filter((col: any) => {
      return props.filterColumns ? props.filterColumns.indexOf(col.prop) > -1 || col.type === 'index' : col
    })
})
const visable = ref(false)
const rowContextmenu = (row: any, column: any, event: any) => {
  console.log(row, column, event)
  visable.value = false
  setTimeout(() => {
    visable.value = true
  }, 50)
  event.preventDefault()
  nextTick(() => {
    ;(rightKeyMenu.value as any).onload(row, column, event)
  })
}
const popovers = ref<Record<string, PopoverInstance>>({})

const setWorkloadVisible = ref<boolean>(false)

const setWorkloadData = ref<ExtractArrayValue<ExtractApiResponse<'getStatisticsByGroup'>>>()

function setPopoverRefs(id: number, popover: PopoverInstance) {
  popovers.value[`popovers-${id}`] = popover
}

/** on popover show */
function onPopoverShow(id: number) {
  Object.keys(popovers.value).forEach((k) => {
    if (k !== `popovers-${id}`) {
      popovers.value[k]?.hide()
    }
  })
}

/** 设置工作量 */
function onSetWorkload(data: ExtractArrayValue<ExtractApiResponse<'getStatisticsByGroup'>>) {
  popovers.value[`popovers-${data.markerId}`]?.hide()
  setWorkloadData.value = data
  setWorkloadVisible.value = true
}
/** 发送消息 */
function onSendMessage(data: ExtractArrayValue<ExtractApiResponse<'getStatisticsByGroup'>>) {
  popovers.value[`popovers-${data.markerId}`]?.hide()
  setReplyUserId?.(data.markerId)
  setMessageVisible?.(true)
}
function onShowScoreLines(row: any) {
  showCharts.value = true
  ;(elTableRef as any).value!.setCurrentRow(row)
}
function forceAssessment(data: ExtractArrayValue<ExtractApiResponse<'getStatisticsByGroup'>>) {
  push({
    name: 'MarkingAssess',
    query: { markerId: data.markerId },
  })
}
const data = computed(() => {
  return JSON.parse(JSON.stringify(props.data || [])) || []
})

const { tableRef, tableData, current, onCurrentChange, onDbClick, currentView, elTableRef } = useTableCheck(data, false)
const myDbClick = (row: any) => {
  onDbClick(row)
  if (currentView.value && !!currentView.value.markingGroupNumber && !!currentView.value.markerId) {
    push({
      name: 'AnalysisPersonnelStatisticsMarker',
      query: {
        markerId: currentView.value.markerId,
        markerName: currentView.value.markerName,
        source: '人员数据统计',
        subjectCode: props.params?.subjectCode,
        questionMainNumber: props.params?.questionMainNumber,
      },
    })
  }
}
const sortTableData = ref<any[]>([])
const sortByCutGroup = (prop: string, order: string) => {
  let arr = cloneDeep(originalTableData.value)
  let groupNodeIndexes: any = arr
    .map((item: any, index: number) => {
      if (!item.markerId) {
        return index
      } else {
        return null
      }
    })
    .filter((item: any) => item !== null)
  console.log('groupNodeIndexes', groupNodeIndexes)
  let newArr = []
  let targetIndex = 0
  for (let i = 0; i < groupNodeIndexes.length; i++) {
    if (i == 0) {
      newArr.push(arr[groupNodeIndexes[i]])
    } else {
      let subArr = arr.slice(targetIndex + 1, groupNodeIndexes[i])
      subArr.sort((a: any, b: any) => {
        if (typeof a[prop] === 'string') {
          let aa = a[prop] || '',
            bb = b[prop] || ''
          return order === 'ascending' ? aa.localeCompare(bb) : bb.localeCompare(aa)
        } else {
          return order === 'ascending' ? a[prop] - b[prop] : b[prop] - a[prop]
        }
      })
      newArr.push(...subArr)
      newArr.push(arr[groupNodeIndexes[i]])
      targetIndex = groupNodeIndexes[i]
      if (i == groupNodeIndexes.length - 1) {
        let subArr2 = arr.slice(targetIndex + 1)
        subArr2.sort((a: any, b: any) => {
          if (typeof a[prop] === 'string') {
            let aa = a[prop] || '',
              bb = b[prop] || ''
            return order === 'ascending' ? aa.localeCompare(bb) : bb.localeCompare(aa)
          } else {
            return order === 'ascending' ? a[prop] - b[prop] : b[prop] - a[prop]
          }
        })
        newArr.push(...subArr2)
      }
    }
  }
  sortTableData.value = newArr
}
const originalTableData = ref<any[]>([])
const sortChange = (params: any) => {
  console.log('params:', params)
  const { column, prop, order } = params
  if (order === 'ascending') {
    sortByCutGroup(prop, order)
    // sortTableData.value.sort((a: any, b: any) => {
    //   if (a.markingGroupNumber == 0) {
    //     return -1
    //   } else if (b.markingGroupNumber == 0) {
    //     return 1
    //   } else {
    //     if (typeof a[prop] === 'string') {
    //       let aa = a[prop] || '',
    //         bb = b[prop] || ''
    //       return aa.localeCompare(bb)
    //     } else {
    //       return a[prop] - b[prop]
    //     }
    //   }
    // })
  } else if (order === 'descending') {
    sortByCutGroup(prop, order)

    // sortTableData.value.sort((a: any, b: any) => {
    //   if (a.markingGroupNumber == 0) {
    //     return -1
    //   } else if (b.markingGroupNumber == 0) {
    //     return 1
    //   } else {
    // if (typeof a[prop] === 'string') {
    //   let aa = a[prop] || '',
    //     bb = b[prop] || ''
    //   return bb.localeCompare(aa)
    // } else {
    //   return b[prop] - a[prop]
    // }
    //   }
    // })
  } else if (order == null) {
    sortTableData.value = JSON.parse(JSON.stringify(originalTableData.value))
  }
}
function initSortTableData(sortKey?: any) {
  if (tableData.value) {
    let data: any[] = JSON.parse(JSON.stringify(tableData.value)) || []
    if (data.length && data[data.length - 1].markingGroupNumber === 0) {
      let last = data.splice(data.length - 1, 1)[0]
      data.unshift(last)
    }
    sortTableData.value = JSON.parse(JSON.stringify(data))

    originalTableData.value = JSON.parse(JSON.stringify(data))
    if (sortKey) {
      sortByCutGroup(sortKey, 'descending')
    }
  }
}
initSortTableData()
watch(tableData, (val) => {
  popovers.value = {}
  if (!firstSorted.value && route.query?.sortKey && val?.length) {
    initSortTableData(route.query?.sortKey || '')
    firstSorted.value = true
  } else {
    initSortTableData()
    if (firstSorted.value) {
      defaultSort.value = undefined
      tableKey.value = Date.now() + ''
    }
  }
})

// watch(currentView, () => {
//   if (currentView.value && !!currentView.value.markingGroupNumber) {
//     push({
//       name: 'AnalysisPersonnelStatisticsMarker',
//       query: { markerId: currentView.value.markerId, markerName: currentView.value.markerName },
//     })
//   }
// })

const {
  fetch: getStatisticObjectiveByMarker,
  result: objectiveByMarker,
  loading: loading1,
} = useFetch('getStatisticObjectiveByMarker')
const {
  fetch: getStatisticSubjectiveByMarker,
  result: subjectiveByMarker,
  loading: loading2,
} = useFetch('getStatisticSubjectiveByMarker')

watch(
  [() => props.params, current],
  () => {
    const { startTime = '', endTime = '' } = props.params || {}
    // if (current.value?.markerId) {
    if (current.value?.markerId) {
      getStatisticObjectiveByMarker({
        markerId: current.value.markerId,
        startTime,
        endTime,
      })
      getStatisticSubjectiveByMarker({
        markerId: current.value.markerId,
        startTime,
        endTime,
      })
    }
  },
  { immediate: true, deep: true }
)

type StatisticObjectiveByMarker = ExtractApiResponse<'getStatisticObjectiveByMarker'>

type StatisticObjectiveByMarkerValues = StatisticObjectiveByMarker['segmentsByAll']

const getXAxisData = <K extends keyof ExtractArrayValue<StatisticObjectiveByMarkerValues>>(
  field: K,
  data?: StatisticObjectiveByMarkerValues
) => {
  if (!data) {
    return []
  }
  const getValue = (key: K, item: ExtractArrayValue<StatisticObjectiveByMarkerValues>) => {
    return item[key]
  }
  return data?.map((v) => getValue(field, v))
}

const markerSubjectiveChartsOption = computed<EChartsOption>(() => {
  return {
    grid: {
      top: 34,
      bottom: 0,
      left: 15,
      right: 15,
      containLabel: true,
    },
    legend: {
      right: 0,
      itemWidth: 14,
      data: ['评卷员主观分布', '小组主观分布', '题组主观分布'],
    },
    xAxis: {
      axisLine: { show: false },
      axisTick: { show: false },
      splitLine: { show: false },
      axisLabel: {
        align: 'right',
      },
      data: getXAxisData('scoreStart', subjectiveByMarker?.value?.segmentsByAll),
    },
    yAxis: [
      {
        type: 'value',
      },
      {
        type: 'value',
        axisLabel: {
          formatter: `{value}%`,
        },
        splitLine: { show: false },
      },
    ],
    series: [
      {
        name: '评卷员主观分布',
        type: 'line',
        itemStyle: {
          color: '#3AD500',
        },
        data: getXAxisData('rate', subjectiveByMarker?.value?.segmentsByUser),
      },
      {
        name: '小组主观分布',
        type: 'line',
        itemStyle: {
          color: '#0064FF',
        },
        data: getXAxisData('rate', subjectiveByMarker?.value?.segmentsByGroup),
      },
      {
        name: '题组主观分布',
        type: 'line',
        itemStyle: {
          color: '#008000',
        },
        data: getXAxisData('rate', subjectiveByMarker?.value?.segmentsByAll),
      },
    ],
  }
})

const markerObjectiveChartsOption = computed<EChartsOption>(() => {
  return {
    grid: {
      top: 34,
      bottom: 0,
      left: 15,
      right: 15,
      containLabel: true,
    },
    legend: {
      right: 0,
      itemWidth: 14,
      data: ['评卷员客观分布', '小组客观分布', '题组客观分布'],
    },
    xAxis: {
      axisLine: { show: false },
      axisTick: { show: false },
      splitLine: { show: false },
      axisLabel: {
        align: 'right',
      },
      data: getXAxisData('scoreStart', objectiveByMarker?.value?.segmentsByAll),
    },
    yAxis: [
      {
        type: 'value',
      },
      {
        type: 'value',
        axisLabel: {
          formatter: `{value}%`,
        },
        splitLine: { show: false },
      },
    ],
    series: [
      {
        name: '评卷员客观分布',
        type: 'line',
        itemStyle: {
          color: '#3AD500',
        },
        data: getXAxisData('rate', objectiveByMarker?.value?.segmentsByUser),
      },
      {
        name: '小组客观分布',
        type: 'line',
        itemStyle: {
          color: '#0064FF',
        },
        data: getXAxisData('rate', objectiveByMarker?.value?.segmentsByGroup),
      },
      {
        name: '题组客观分布',
        type: 'line',
        itemStyle: {
          color: '#008000',
        },
        data: getXAxisData('rate', objectiveByMarker?.value?.segmentsByAll),
      },
    ],
  }
})
const tableHeight = computed(() => {
  return !!current.value && !!current.value?.markerId && showCharts.value
    ? 'calc(100vh - 482px)'
    : 'calc(100vh - 318px)'
  // return 'calc(100vh - 250px)'
})
const clearCheck = () => {
  ;(elTableRef as any).value!.setCurrentRow(undefined)
  showCharts.value = false
}
</script>

<style scoped lang="scss">
.statistics-personnel {
  :deep(.el-table) {
    .fixed-row {
      display: table-row;
      position: sticky;
      position: '-webkit-sticky';
      top: 0;
      width: 100%;
      z-index: 3;
      font-weight: bold;
      color: #333;
    }
    .fixed-row2 {
      // display: table-row;
      // position: sticky;
      // position: '-webkit-sticky';
      // top: 44px;
      // width: 100%;
      // z-index: 3;
      font-weight: bold;
      color: #333;
    }
  }
}
.chart-box {
  height: 160px;
}
.charts-box {
  position: relative;
  margin-top: 5px;
  .close-panel {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translateX(-50%) translateY(-50%);
    z-index: 1;
  }
}
</style>
