<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 w-340 border-r-1 border-solid border-r-#e4e7ed">
          <el-select
            v-if="currentGroup?.customNode"
            v-model="selectValue"
            placeholder="单体选择"
            style="width:240px"
            @change="onchangeSelect"
          >
            <el-option
              v-for="item in currentGroup.brother"
              :key="item.name"
              :label="item.customCnName"
              :value="item.name"
            />
          </el-select>
          <PointCheckbox
            :pointList="pointList"
            :loadingPoints="loadingPoints"
            @onchange-points="onchangePoints"
            ref="PointCheckboxRef"
          >
          </PointCheckbox>
        </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>
          <div class="flex w-full items-center gap-16">
            <div class="w-400px">
              <el-date-picker
                v-model="time"
                type="datetimerange"
                value-format="YYYY-MM-DD HH:mm:ss"
                range-separator="到"
                :default-value="getBeforeMonth"
                start-placeholder="开始时间"
                end-placeholder="结束时间"
                :disabled-date="disabledDate"
              />
            </div>
            <el-button type="primary" @click="loadChardData">查询数据</el-button>
          </div>
          <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 type { IDevice, IMyPoint, IOfflineDevice, IOnlineDevice } from '../../type'
import {
  getDeviceDetails,
  getPoints,
  type IGetDeviceDataParams,
  type IPointGroupOV,
  type IPointsParams,
} from '@/api/module/transfer'
import { useMessage } from '@/composables/useMessage'
import dayjs from 'dayjs'
import { nextTick } from "vue";
import EdfsWrap from "@/components/Edfs-wrap.vue";
import PointCheckbox from "@/views/stationData/component/pointCheckbox.vue";

const env = import.meta.env
const isShowDrawer = defineModel<boolean>()
const title = computed(() => (curDevice.value?.isonLine ? '数据详情' : `已导出数据详情`))
const message = useMessage()
const PointCheckboxRef = ref<InstanceType<typeof PointCheckbox>>()

const emit = defineEmits(['on-save'])
const pointList = ref<IMyPoint[]>([])
const curDevice = ref<IDevice & { isonLine: boolean, siteName: string }>()

async function open(device: IDevice & {
  isonLine: boolean,
  siteName: string
}, group: IPointGroupOV) {
  curDevice.value = device
  currentGroup.value = group
  if (
    currentGroup.value.customNode &&
    currentGroup.value.brother &&
    currentGroup.value.brother.length
  ) {
    selectValue.value = currentGroup.value.brother[0].name
  }
  PointCheckboxRef.value?.clearCheck()
  await loadPoints()
    .then(async () => {
      await loadDeviceDetails()
    })
    .catch(() => {
      message.error('获取点位数据失败')
      fullscreenLoading.value?.close()
    })
}

const selectValue = ref()

function onchangeSelect(value: string) {
  PointCheckboxRef.value?.clearCheck()
}


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

const currentGroup = ref<IPointGroupOV & {
  customNode?: boolean
  brother?: Array<any>
}>()

async function loadPoints() {
  if (!currentGroup.value) {
    message.error('请先选择点位组')
    return
  }
  const params: IPointsParams = {
    type: currentGroup.value.type,
  }
  if (curDevice.value?.isonLine) {
    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 = curDevice.value!.siteName
    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
  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 (!time.value || time.value.length !== 2) {
    message.error('请选择时间范围')
    return
  }
  if (!currentGroup.value) return
  if (!columParams.value.filter(i => i !== 'ts').length) {
    message.error('请选择点位')
    return
  }
  clearData()
  const limit = chartLimit.value
  const offset = chartOffset.value
  const options: any = {
    columns: columParams.value,
    isLocal: !curDevice.value?.isonLine,
    host: curDevice.value?.isonLine ? (curDevice.value as IOnlineDevice).clientIp : '',
    name: currentGroup.value?.customNode ? selectValue.value : currentGroup.value?.name  as string,
    startTime: time.value[0],
    endTime: time.value[1],
  }

  if (env.VITE_APP_ENV !== 'local' || !curDevice.value?.isonLine) {
    options.site_id = curDevice.value!.siteName || ''
    options.device_id = curDevice.value?.sn || ''
  }

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

  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) && !!val) {
      const time = dayjs(Number(ts)).format('YYYY-MM-DD HH:mm:ss')
      if (addr) {
        const colData = chartData.get(addr)
        const value = Number(Number(val).toFixed(5))
        if (colData) {
          colData.push([time, value])
        } else {
          chartData.set(addr, [[time, value]])
        }
      }

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

}


function handleBeforeClose(done: () => void) {
  time.value = undefined
  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 checkPointList = ref<IMyPoint[]>([])

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

const time = ref<[string, string]>()
const disabledDate = (time: any) => {
  const current = dayjs(time)
  if (curDevice.value?.isonLine) {
    return current.isAfter(dayjs(), 'day')
  }

  try {
    const deviceOff = curDevice.value as IOfflineDevice
    const start = dayjs(deviceOff.start_time).format('YYYY-MM-DD')
    const end = dayjs(deviceOff.end_time).format('YYYY-MM-DD')
    return current.isBefore(start, 'day') || current.isAfter(end, 'day')
  } catch (e) {
    console.log('disableDate error', e)
    return current.isAfter(dayjs(), 'day')
  }

}
const getBeforeMonth = dayjs().startOf('month').subtract(1, 'month').startOf('month').toDate()

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>
