<template>
  <div class="fault-rule-drawer">
    <el-drawer v-model="isShowDrawer" :title="title" direction="rtl" size="90%"
               modal-class="model-dev-opn"
               :before-close="handleBeforeClose" @opened="onDrawerOpened">
      <main class="wh-full flex">
        <EdfsWrap title="点位组" class="p-r-4 h-full border-r-1 border-solid border-r-#e4e7ed">
          <PointGroupTree
            v-if="isShowDrawer"
            :data="pointGroup"
            @device-select="onGroupChange"
            :groupChangeLoading="groupChangeLoading"
            @onchangePoints="onchangePoints"
            :pointList="pointList"
            :loadingPoints="loadingPoints"
            :isTransfer="props.isTransfer"
            :siteInfo="props.siteInfo"
            ref="pointGroupTreeRef"/>
        </EdfsWrap>
        <div class="flex-1 p-4 h-full overflow-hidden relative"
        >
          <div class="absolute w-full h-full bg-[#ffffffe5] z-99" v-if="loadingChart">
            <div class="w-full h-full flex flex-col justify-center items-center">
              <el-progress
                style="width: 70%"
                :text-inside="true"
                :stroke-width="18"
                :percentage="progress"
                status="success"
              />
              <div class="text-xl">
                <div>当前加载数据量较大请稍等。。。</div>
              </div>
            </div>
          </div>
          <el-button class="mb-4" type="primary" @click="loadChardData">查询数据</el-button>
          <NewDataChart v-if="isShowChart" :chart-datas="chartData" :legends="legends"
                        :axis-data="Array.from(axisData)" ref="chartRef"/>
        </div>
      </main>
    </el-drawer>
  </div>
</template>

<script setup lang="ts">
import NewDataChart from '../../component/newDataChart.vue'
import PointGroupTree from './PointGroupTree.vue'
import type { IMyPoint, IOfflineDevice, IOnlineDevice } from '../../type'
import {
  getDeviceDetails,
  getPointGroup,
  getPoints,
  type IGetDeviceDataParams,
  type IPointGroupOV,
  type IPointGroupParams,
  type IPointsParams,
  type ISite,
} from '@/api/module/transfer'
import { useMessage } from '@/composables/useMessage'
import dayjs from 'dayjs'
import { nextTick } from "vue";
import EdfsWrap from "@/components/Edfs-wrap.vue";

const env = import.meta.env


const isShowDrawer = defineModel<boolean>()
const title = computed(() => (props.isTransfer ? '数据详情' : `已迁移数据详情`))
const message = useMessage()

const pointGroupTreeRef = ref<InstanceType<typeof PointGroupTree>>()
const props = defineProps<{
  siteInfo: ISite | null
  isTransfer: boolean
}>()

const emit = defineEmits(['on-save'])

const pointList = ref<IMyPoint[]>([])

const curDevice = ref<IOfflineDevice | IOnlineDevice>()

async function open(device: IOfflineDevice | IOnlineDevice) {
  curDevice.value = device
  await loadPointGroup()
    .then(async () => {
      await loadDeviceDetails()
    })
    .catch(() => {
      message.error('获取点位组数据失败')
      fullscreenLoading.value?.close()
    })
}


const loadingPoints = ref(false)
const columParams = computed(() => ['ts', ...checkPointList.value.map(i => i.addr)])

async function loadPoints() {
  if (!curGroup.value) {
    message.error('请先选择点位组')
    return
  }
  const params: IPointsParams = {
    type: curGroup.value,
  }
  if (props.isTransfer) {
    const onlineDevice = curDevice.value as IOnlineDevice
    params.isLocal = false
    params.host = onlineDevice.clientIp
  } else {
    const offlineDevice = curDevice.value as IOfflineDevice
    params.sn = offlineDevice.sn
    params.site = props.siteInfo!.name
    params.isLocal = true
  }
  loadingPoints.value = true
  const res = await getPoints(params)
  if (res.code === 0) {
    const data = Array.isArray(res?.data) ? res.data : []
    pointList.value = data.map((i: any) => ({
      label: i.cnName,
      addr: i.addr,
      unit: i.unit || '',
    }))
  }
  loadingPoints.value = false
  return res
}

async function loadDeviceDetails() {
  if (!fullscreenLoading.value) {
    openFullScreen()
  }
  chartData.clear()
  axisData.clear()
  legends.value = []
  const pointsRes = await loadPoints()
  if (!pointsRes || pointsRes.code !== 0) {
    message.error('获取点位数据失败')
    pointList.value = []
    chartData.clear()
    axisData.clear()
    fullscreenLoading.value?.close()
    return
  }
  isShowDrawer.value = true
  groupChangeLoading.value = false
  fullscreenLoading.value?.close()
}

const chartData = reactive(new Map<string, any[]>())
const axisData = new Set<string>()
const legends = ref<{ addr: string; label: string, unit: string }[]>([])

const loadingChart = ref(false)
const chartAllTotal = ref(0)
const chartLimit = ref(1000)
const chartOffset = ref(0)
const progress = ref(0)

async function loadChardData() {
  if (!columParams.value.filter(i => i !== 'ts').length) {
    message.error('请选择点位')
    return
  }
  clearData()
  const limit = chartLimit.value
  const offset = chartOffset.value
  const options = {
    columns: columParams.value,
    isLocal: !props.isTransfer,
    host: props.isTransfer ? (curDevice.value as IOnlineDevice).clientIp : '',
    name: curGroupName.value as string,
  }

  const params: IGetDeviceDataParams = {
    ...options,
    limit,
    offset
  }

  if (env.VITE_APP_ENV !== 'local' || !props.isTransfer) {
    params.site_id = props.siteInfo!.name || ''
    params.device_id = curDevice.value?.sn || ''
  }
  loadingChart.value = true
  isShowChart.value = false

  const res = await getDeviceDetails(params)

  if (res.code !== 0) {
    resetChartStatus()
    message.error('获取设备数据失败')
    return
  }

  chartAllTotal.value = res?.data?.total ?? 0
  if (chartAllTotal.value === 0) {
    resetChartStatus()
    message.info('暂无数据')
    return
  }

  const pointData = Array.isArray(res.data.results) ? res.data.results : []
  setChartData(pointData)
  const pageCount = Math.ceil(chartAllTotal.value / Number(limit))
  if (pageCount <= 1) {
    progress.value = 100
    setTimeout(() => {
      resetChartStatus()
    })
    return
  }

  for (let i = 1; i < pageCount; i++) {
    const params: IGetDeviceDataParams = {
      ...options,
      limit,
      offset: i * Number(limit)
    }
    const res = await getDeviceDetails(params)
    if (res.code !== 0) {
      clearData()
      resetChartStatus()
      message.error('获取设备数据失败')
      return
    }
    const pointData = Array.isArray(res.data.results) ? res.data.results : []
    setChartData(pointData)
    progress.value = Math.min(100, Math.floor(((i + 1) / pageCount) * 100))
  }

  resetChartStatus()
}


function setChartData(pointData: any[]) {
  for (const addr of columParams.value.filter(i => i !== 'ts')) {
    const label = pointList.value.find(i => i.addr === addr)?.label || addr
    const find = legends.value.find(i => i.addr === addr)
    const unit = pointList.value.find(i => i.addr === addr)?.unit || ''
    if (!find) {
      legends.value.push({ addr, label, unit })
    }
  }
  pointData.forEach((data: any[]) => {
    const [ts, val, addr] = data
    if (checkPointList.value.some(i => i.addr === addr)) {
      const time = dayjs(Number(ts)).format('YYYY-MM-DD HH:mm:ss')
      if (addr) {
        const colData = chartData.get(addr)
        if (colData) {
          colData.push([time, val])
        } else {
          chartData.set(addr, [[time, val]])
        }
      }

      if (ts) {
        axisData.add(time)
      }
    }
  })
}

function handleBeforeClose(done: () => void) {
  isShowDrawer.value = false
  clearData()
  fullscreenLoading.value = null
  done()
}

function clearData() {
  chartLimit.value = 1000
  chartOffset.value = 0
  chartAllTotal.value = 0
  progress.value = 0
  legends.value = []
  chartData.clear()
  axisData.clear()
}

function resetChartStatus() {
  loadingChart.value = false
  nextTick(() => {
    isShowChart.value = true
  })
}

const chartRef = ref<InstanceType<typeof NewDataChart>>()
const isShowChart = ref(false)

function onDrawerOpened() {
  nextTick(() => {
    isShowChart.value = true
  })
}

const fullscreenLoading = ref<any>(null)
const openFullScreen = () => {
  fullscreenLoading.value = ElLoading.service({
    lock: true,
    text: '数据加载中,请稍后...',
    background: 'rgba(255, 255, 255, 0.8)',
  })
}

const pointGroup = ref<IPointGroupOV[]>([])
const curGroup = ref<string>()
const curGroupName = ref<string>()

async function loadPointGroup() {
  const params: IPointGroupParams = {}
  if (props.isTransfer) {
    const onlineDevice = curDevice.value as IOnlineDevice
    params.isLocal = false
    params.host = onlineDevice.clientIp
  } else {
    const offlineDevice = curDevice.value as IOfflineDevice
    params.sn = offlineDevice.sn
    params.site = props.siteInfo!.name
    params.isLocal = true
  }

  const res = await getPointGroup(params)
  if (res.code === 0) {
    curGroup.value = res.data[0]?.type
    curGroupName.value = res.data[0]?.name
    pointGroup.value = Array.isArray(res?.data) ? res.data : []
    return Promise.resolve()
  } else {
    return Promise.reject()
  }
}

const groupChangeLoading = ref<boolean>(false)

function onGroupChange(item: IPointGroupOV) {
  if (!item?.type) {
    return
  }
  groupChangeLoading.value = true
  curGroup.value = item.type
  curGroupName.value = item.name
  loadDeviceDetails()
}


const checkPointList = ref<IMyPoint[]>([])


function onchangePoints(checkPoints: IMyPoint[]) {
  checkPointList.value = []
  checkPointList.value = checkPoints
}

defineExpose({
  open,
  openFullScreen,
})
</script>

<style scoped lang="scss">
.fault-rule-drawer {
  font-size: 16px;

  :deep(.edfs-wrap) {
    width: auto;
  }

  :deep(.el-drawer__header) {
    color: var(--text-color);
  }
}
</style>
