<template>
  <div class="analysis-monitor-view">
    <div class="flex items-center justify-end p-l-base p-r-base fill-blank view-header">
      <div class="pointer circle-button" custom-1 @click="toggleSetting(true)"><svg-icon name="setting" /></div>
      <el-button type="primary" :loading="loading" @click="onRefresh">刷新</el-button>
    </div>
    <div class="content-wrap p-base flex">
      <div class="data-card-view">
        <div
          v-for="card in cards"
          :key="card.dataField"
          class="radius-base full fill-blank data-card"
          :class="{ active: activeCard?.dataField === card.dataField }"
          @click="setActiveCard(card)"
        >
          <div class="flex direction-column radius-base full fill-blank data-card-content">
            <div class="p-base card-title">{{ card.title }}</div>
            <div class="p-l-extra-base p-r-mini p-b-extra-small flex-1 overflow-hidden">
              <base-table
                border
                v-bind="getTableProps(card.hasAll)"
                size="small"
                height="100%"
                :columns="getColumns(card.valueLabel)"
                :data="getData(sortableResult[card.dataField], card.hasAll)"
              >
                <template #empty>
                  <empty :image-size="100"></empty>
                </template>
              </base-table>
            </div>
          </div>
        </div>
      </div>
      <div class="p-base radius-base m-l-auto fill-blank data-detail-view">
        <div class="m-b-mini card-title">系统监控</div>
        <base-table
          v-if="activeCard"
          border
          stripe
          size="small"
          :columns="getColumns(activeCard.valueLabel)"
          :data="sortableResult[activeCard.dataField]"
        >
        </base-table>
      </div>
    </div>
    <base-dialog v-model="visibleSetting" title="参数设置" :footer="false" destroy-on-close>
      <base-form :label-width="'88px'" :model="model" :items="formItems">
        <el-form-item>
          <confirm-button @confirm="onConfirm" @cancel="toggleSetting(false)"></confirm-button>
        </el-form-item>
      </base-form>
    </base-dialog>
  </div>
</template>

<script setup lang="tsx" name="AnalysisMonitoring">
/** 决策分析-监控 */
import { computed, reactive, ref, watch, nextTick } from 'vue'
import { useRouter } from 'vue-router'
import { ElButton, ElFormItem } from 'element-plus'
import { omit } from 'lodash-es'
import { useIntervalFn } from '@vueuse/core'
import { localStorage } from '@/plugins/storage'
import useFetch from '@/hooks/useFetch'
import useOptions from '@/hooks/useOptions'
import useVW from '@/hooks/useVW'
import SvgIcon from '@/components/common/SvgIcon.vue'
import BaseTable from '@/components/element/BaseTable.vue'
import BaseDialog from '@/components/element/BaseDialog.vue'
import BaseForm from '@/components/element/BaseForm.vue'
import ConfirmButton from '@/components/common/ConfirmButton.vue'
import Empty from '@/components/common/Empty.vue'

import type { EpTableColumn, EpFormItem, EpTableProps } from 'global-type'
import type { ExtractApiParams, ExtractApiResponse } from '@/api/api'

const { push } = useRouter()

const { subjectList, mainQuestionList, groupListWithAll, dataModel, changeModelValue, initFinish, onOptionInit } =
  useOptions(['subject', 'question', 'group'])

const model = reactive<
  Omit<ExtractApiParams<'getStatistics'>, 'markingGroupNumbers'> & {
    refresh: number
    markingGroupNumbers?: number
  }
>({
  subjectCode: dataModel.subject || '',
  questionMainNumber: dataModel.question,
  markingGroupNumbers: dataModel.group,
  refresh: localStorage.get('MONITORING_REFRESH_RATE') || 0,
})

const modelToFetchModel = () => {
  return Object.assign({}, model, {
    markingGroupNumbers:
      typeof model.markingGroupNumbers === 'number' ? [model.markingGroupNumbers] : model.markingGroupNumbers,
  })
}

const fetchModel = reactive<ExtractApiParams<'getStatistics'> & { refresh: number }>(modelToFetchModel())

watch(fetchModel, () => {
  localStorage.set('MONITORING_REFRESH_RATE', fetchModel.refresh)
})

watch(
  dataModel,
  () => {
    model.subjectCode = dataModel.subject
    model.questionMainNumber = dataModel.question
    model.markingGroupNumbers = dataModel.group
  },
  { immediate: true }
)

const formItems = computed<EpFormItem[]>(() => [
  {
    label: '科目',
    slotType: 'select',
    prop: 'subjectCode',
    slot: {
      options: subjectList.value,
      disabled: true,
    },
  },
  {
    label: '大题',
    slotType: 'select',
    prop: 'questionMainNumber',
    slot: {
      options: mainQuestionList.value,
      disabled: true,
    },
  },
  {
    label: '小组',
    slotType: 'select',
    prop: 'markingGroupNumbers',
    slot: {
      options: groupListWithAll.value,
      onChange: changeModelValue('group'),
    },
  },
  {
    label: '自动刷新',
    slotType: 'select',
    prop: 'refresh',
    slot: {
      options: [3, 5, 10, 0].map((n) => ({ value: n, label: n ? `${n}分钟` : '不自动刷新' })),
    },
  },
])

interface Card {
  dataField: string
  title: string
  valueLabel: string
  hasAll: boolean
}

const cards: Card[] = [
  {
    dataField: 'totalPaperList',
    title: '评卷份数',
    valueLabel: '份数',
    hasAll: true,
  },
  {
    dataField: 'xyRelateList',
    title: '相关系数',
    valueLabel: '相关系数',
    hasAll: true,
  },
  {
    dataField: 'avgList',
    title: '平均分',
    valueLabel: '平均分',
    hasAll: true,
  },
  {
    dataField: 'stdList',
    title: '标准差',
    valueLabel: '标准差',
    hasAll: true,
  },
  {
    dataField: 'scoreTopLowList',
    title: '近5分钟最高最低分',
    valueLabel: '分数',
    hasAll: false,
  },
  {
    dataField: 'objSubRateList',
    title: '近5分钟客主比',
    valueLabel: '最高',
    hasAll: false,
  },
  {
    dataField: 'objSubAvgRateList',
    title: '平均客主比',
    valueLabel: '平均最高',
    hasAll: false,
  },
  {
    dataField: 'integrationList',
    title: '综合',
    valueLabel: '综合指数',
    hasAll: false,
  },
]

/** 跳转抽查详情 */
const viewMarkDetail = (row: ExtractArrayValue<ExtractRecordValue<ExtractApiResponse<'getStatistics'>>>) => {
  push({
    name: 'AnalysisViewMarked',
    params: {
      markerId: row.markerId,
    },
    query: {
      markerName: row.markerName,
    },
  })
}

const getTableProps: (hasAll: boolean) => EpTableProps = (hasAll) => {
  return {
    highlightCurrentRow: false,
    rowClassName({ rowIndex }) {
      const startIndex = hasAll ? 1 : 0
      const splitIndex = hasAll ? 3 : 2
      if (rowIndex >= startIndex && rowIndex <= splitIndex) {
        return 'top-three-row'
      } else if (rowIndex >= splitIndex + 1 && rowIndex <= splitIndex + 3) {
        return 'last-three-row'
      }
      return ''
    },
  }
}

const getColumns = (
  valueLabel: string
): EpTableColumn<ExtractArrayValue<ExtractRecordValue<ExtractApiResponse<'getStatistics'>>>>[] => {
  return [
    {
      label: '老师ID',
      align: 'center',
      formatter(row) {
        return row.markerId === 0 ? (
          '全体'
        ) : (
          <ElButton type="primary" link onClick={() => viewMarkDetail(row)}>
            {row.markerName}
          </ElButton>
        )
      },
    },
    { label: valueLabel, prop: 'value', align: 'center' },
  ]
}

const activeCard = ref<Card>()

const setActiveCard = (v: Card) => {
  activeCard.value = v
}

const visibleSetting = ref<boolean>(false)

const toggleSetting = (visible: boolean) => {
  visibleSetting.value = visible
}

const interval = computed(() => fetchModel.refresh * 60 * 1000)

const { fetch, result, loading } = useFetch('getStatistics')

const getData = (data: ExtractRecordValue<ExtractApiResponse<'getStatistics'>>, hasAll: boolean) => {
  return data?.slice(0, hasAll ? 4 : 3).concat(data?.slice(hasAll ? 4 : 3).slice(-3)) || []
}

const sortableResult = computed<typeof result.value>(() => {
  if (!result.value) return {}
  return cards.reduce((final, { dataField, hasAll }) => {
    let resultData = result.value[dataField]?.filter((v) => hasAll || v.markerId) || []

    if (dataField === 'scoreTopLowList') {
      const scoreTopList = result.value?.['scoreTopList']?.filter((v) => hasAll || v.markerId) || []
      const scoreLowList = result.value?.['scoreLowList']?.filter((v) => hasAll || v.markerId) || []
      resultData = scoreTopList
        .concat(scoreLowList)
        ?.filter((d, i, arr) => d && i === arr.findIndex((v) => v.markerId === d.markerId))
    }

    const arr = [...resultData]
    const totalIndex = arr.findIndex((v) => v.markerId === 0)
    if (totalIndex >= 0) {
      const [total] = arr.splice(totalIndex, 1)
      total && arr.unshift(total)
    }
    final[dataField] = arr
    return final
  }, {} as typeof result.value)
})

const onRefresh = () => {
  let date = new Date()
  let year = date.getFullYear()
  let month: number | string = date.getMonth() + 1
  let day: number | string = date.getDate()
  month < 10 && (month = '0' + month)
  day < 10 && (day = '0' + day)
  if (fetchModel.subjectCode && fetchModel.questionMainNumber) {
    fetch({
      ...omit(fetchModel, 'refresh'),
      startTime: `${year}${month}${day}000000`,
      endTime: `${year}${month}${day}235959`,
    })
  }
}

const onConfirm = () => {
  Object.assign(fetchModel, modelToFetchModel())
  onRefresh()
  toggleSetting(false)
}

onOptionInit(onConfirm)

const { pause, isActive, resume } = useIntervalFn(onRefresh, interval, { immediate: false })

watch([interval, initFinish], () => {
  if (!initFinish.value) {
    return
  }
  if (interval.value <= 0 && isActive.value) {
    pause()
  } else {
    resume()
  }
})
</script>

<style scoped lang="scss">
.analysis-monitor-view {
  .content-wrapper {
    height: 784px;
  }
  .view-header {
    height: 52px;
    .circle-button {
      width: 32px;
      height: 32px;
      border-radius: 50%;
      background-color: #eee;
      color: #666;
      display: grid;
      place-items: center;
      margin-right: $ExtraSmallGapSpace;
    }
  }
  .data-card-view {
    // width: 1118px;
    width: calc(((100% - 40px) / 5) * 4 + 30px);
    height: 706px;
    flex-wrap: wrap;
    align-content: flex-start;
    display: flex;
    justify-content: space-between;
    .data-card {
      // width: 272px;
      width: calc((100% - 30px) / 4);
      height: 348px;
      padding-top: 2px;
      &.active {
        background-color: #32c5ff;
        box-shadow: 0px 16px 16px 0px rgba(0, 0, 0, 0.1);
      }
      &:nth-child(n + 5) {
        margin-top: $ExtraSmallGapSpace;
      }
    }
  }
  .data-detail-view {
    width: calc((100% - 40px) / 5);
    height: 706px;
    overflow: auto;
  }

  .card-title {
    color: $BlockTitleColor;
    font-size: $BaseFont;
    line-height: 1;
  }

  ::v-deep(.el-table) {
    .el-table__body-wrapper {
      .el-table__body {
        .top-three-row {
          background: rgba(0, 186, 151, 0.1);
        }
        .last-three-row {
          background: rgba(255, 114, 59, 0.1);
        }
        .el-table__cell {
          padding: 5px 0;
        }
      }
    }
  }
}
</style>
