<script setup lang="ts">
import dayjs from 'dayjs'
import { IotRdDailyReportApi } from '@/api/pms/iotrddailyreport'
import { useDebounceFn } from '@vueuse/core'
import CountTo from '@/components/count-to1.vue'
import * as echarts from 'echarts'
import { Motion, AnimatePresence } from 'motion-v'
import download from '@/utils/download'
import { useTableComponents } from '@/components/ZmTable/useTableComponents'

interface Query {
  pageNo: number
  pageSize: number
  deptId: number
  contractName?: string
  taskName?: string
  createTime: string[]
}

const props = defineProps<{
  query: Query
  deptName: string
  defaultView?: '表格' | '看板'
  refreshKey: number
}>()

const totalWorkKeys: [string, string | undefined, string, string, number][] = [
  [
    'cumulativeBridgePlug',
    undefined,
    '桥塞',
    'i-material-symbols:check-circle-outline-rounded text-emerald',
    0
  ],
  [
    'cumulativeRunCount',
    undefined,
    '趟数',
    'i-material-symbols:check-circle-outline-rounded text-emerald',
    0
  ],
  [
    'cumulativeWorkingWell',
    undefined,
    '井数',
    'i-material-symbols:check-circle-outline-rounded text-emerald',
    0
  ],
  [
    'cumulativeWorkingLayers',
    undefined,
    '段数',
    'i-material-symbols:check-circle-outline-rounded text-emerald',
    0
  ],
  [
    'cumulativeHourCount',
    undefined,
    '小时(H)',
    'i-material-symbols:nest-clock-farsight-analog-outline-rounded text-emerald',
    2
  ],
  [
    'cumulativeWaterVolume',
    '方',
    '水方量',
    'i-material-symbols:water-drop-outline-rounded text-sky',
    2
  ],
  ['taici', undefined, '台次', 'i-material-symbols:check-circle-outline-rounded text-emerald', 0],
  [
    'utilizationRate',
    '%',
    '设备利用率',
    'i-material-symbols:check-circle-outline-rounded text-emerald',
    0
  ],
  [
    'cumulativeFuels',
    '万升',
    '累计油耗',
    'i-material-symbols:directions-car-outline-rounded text-sky',
    2
  ]
]

const totalWork = ref<Record<string, number>>({
  cumulativeFuels: 0,
  taici: 0,
  cumulativeBridgePlug: 0,
  cumulativeRunCount: 0,
  cumulativeWorkingWell: 0,
  cumulativeWorkingLayers: 0,
  cumulativeHourCount: 0,
  cumulativeWaterVolume: 0,
  utilizationRate: 0
})

const totalLoading = ref(false)

const getQueryWithoutPage = () => {
  const { pageNo: _pageNo, pageSize: _pageSize, ...other } = props.query

  void _pageNo
  void _pageSize

  return other
}

const getTotal = useDebounceFn(async () => {
  totalLoading.value = true

  try {
    const res2 = await IotRdDailyReportApi.totalWorkload(getQueryWithoutPage())

    totalWork.value = {
      ...totalWork.value,
      taici: res2.taici || 0,
      cumulativeBridgePlug: res2.cumulativeBridgePlug || 0,
      cumulativeRunCount: res2.cumulativeRunCount || 0,
      cumulativeWorkingWell: res2.cumulativeWorkingWell || 0,
      cumulativeWorkingLayers: res2.cumulativeWorkingLayers || 0,
      cumulativeHourCount: res2.cumulativeHourCount || 0,
      cumulativeWaterVolume: res2.cumulativeWaterVolume || 0,
      ...res2,
      cumulativeFuels: (res2.cumulativeFuels || 0) / 10000,
      utilizationRate: Number(((res2.utilizationRate || 0) * 100).toFixed(2))
    }
  } finally {
    totalLoading.value = false
  }
}, 500)

interface List {
  id: number | null
  name: string | null
  projectDeptId?: number
  type: '1' | '2' | '3'
  cumulativeBridgePlug: number | null
  cumulativeRunCount: number | null
  cumulativeWorkingWell: number | null
  cumulativeHourCount: number | null
  totalDailyFuel: number | null
  cumulativeWaterVolume: number | null
  cumulativeWorkingLayers: number | null
  cumulativePumpTrips: number | null
  cumulativeMixSand: number | null
  utilizationRate: number | null
}

const list = ref<List[]>([])

const listLoading = ref(false)

const getList = useDebounceFn(async () => {
  listLoading.value = true
  try {
    const res = await IotRdDailyReportApi.getIotRdDailyReportSummary(props.query)
    const reslist = res?.list || []

    list.value = reslist.map(
      ({ projectDeptId, projectDeptName, teamId, teamName, type, id, ...other }) => {
        return {
          id: type === '2' ? projectDeptId : teamId,
          name: type === '2' ? projectDeptName : teamName,
          ...other,
          cumulativeBridgePlug: other.cumulativeBridgePlug || 0,
          cumulativeRunCount: other.cumulativeRunCount || 0,
          cumulativeWorkingWell: other.cumulativeWorkingWell || 0,
          cumulativeHourCount: other.cumulativeHourCount || 0,
          totalDailyFuel: other.totalDailyFuel || 0,
          cumulativeWaterVolume: other.cumulativeWaterVolume || 0,
          cumulativeWorkingLayers: other.cumulativeWorkingLayers || 0,
          cumulativePumpTrips: other.cumulativePumpTrips || 0,
          cumulativeMixSand: other.cumulativeMixSand || 0,
          utilizationRate: other.utilizationRate || 0
        }
      }
    )

    console.log('list', list.value)
  } finally {
    listLoading.value = false
  }
}, 500)

const tab = ref<'表格' | '看板'>('表格')

const currentTab = ref<'表格' | '看板'>('表格')

const direction = ref<'left' | 'right'>('right')

const handleSelectTab = (val: '表格' | '看板') => {
  if (tab.value === val && currentTab.value === val) return

  tab.value = val
  direction.value = val === '看板' ? 'right' : 'left'
  nextTick(() => {
    currentTab.value = val
    setTimeout(() => {
      render()
    })
  })
}

watch(
  () => props.defaultView,
  (val) => {
    handleSelectTab(val || '表格')
  },
  { immediate: true }
)

const chartRef = ref<HTMLDivElement | null>(null)
let chart: echarts.ECharts | null = null

const xAxisData = ref<string[]>([])

const legend = ref<string[][]>([
  ['个数', 'cumulativeBridgePlug'],
  ['井数', 'cumulativeWorkingWell'],
  ['小时 (H)', 'cumulativeHourCount'],
  ['油耗 (万升)', 'cumulativeFuels'],
  ['水方量 (方)', 'cumulativeWaterVolume'],
  ['台次(泵车)', 'cumulativePumpTrips'],
  ['段数', 'cumulativeWorkingLayers'],
  ['台次(仪表/混砂)', 'cumulativeMixSand'],
  ['设备利用率 (%)', 'utilizationRate']
])

const chartData = ref<Record<string, number[]>>({
  cumulativeBridgePlug: [],
  cumulativeWorkingWell: [],
  cumulativeHourCount: [],
  cumulativeFuels: [],
  cumulativeWaterVolume: [],
  cumulativeWorkingLayers: [],
  cumulativePumpTrips: [],
  cumulativeMixSand: [],
  utilizationRate: []
})

let chartLoading = ref(false)

const getChart = useDebounceFn(async () => {
  chartLoading.value = true

  try {
    const res = await IotRdDailyReportApi.getIotRdDailyReportSummaryPolyline(props.query)

    chartData.value = {
      cumulativeBridgePlug: res.map((item) => item.cumulativeBridgePlug || 0),
      cumulativeWorkingWell: res.map((item) => item.cumulativeWorkingWell || 0),
      cumulativeHourCount: res.map((item) => item.cumulativeHourCount || 0),
      cumulativeFuels: res.map((item) => (item.cumulativeFuels || 0) / 10000),
      cumulativeWaterVolume: res.map((item) => item.cumulativeWaterVolume || 0),
      cumulativeWorkingLayers: res.map((item) => item.cumulativeWorkingLayers || 0),
      cumulativePumpTrips: res.map((item) => item.cumulativePumpTrips || 0),
      cumulativeMixSand: res.map((item) => item.cumulativeMixSand || 0),
      utilizationRate: res.map((item) => Number(((item.utilizationRate || 0) * 100).toFixed(2)))
    }

    xAxisData.value = res.map((item) => item.reportDate || '')
  } finally {
    chartLoading.value = false
  }
}, 500)

const resizer = () => {
  chart?.resize()
}

onUnmounted(() => {
  window.removeEventListener('resize', resizer)
  chart?.dispose()
})

const render = () => {
  if (!chartRef.value) return

  chart?.dispose()
  chart = echarts.init(chartRef.value, undefined, { renderer: 'canvas' })

  window.removeEventListener('resize', resizer)
  window.addEventListener('resize', resizer)

  const values: number[] = []

  for (const [_name, key] of legend.value) {
    values.push(...(chartData.value[key] || []))
  }

  const maxVal = values.length === 0 ? 10000 : Math.max(...values)
  const minVal = values.length === 0 ? 0 : Math.min(...values) > 0 ? 0 : Math.min(...values)

  const maxDigits = (Math.floor(maxVal) + '').length
  const minDigits = minVal === 0 ? 0 : (Math.floor(Math.abs(minVal)) + '').length
  const interval = Math.max(maxDigits, minDigits)

  const maxInterval = interval
  const minInterval = minDigits

  const intervalArr = [0]
  for (let i = 1; i <= interval; i++) {
    intervalArr.push(Math.pow(10, i))
  }

  chart.setOption({
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'line'
      },
      formatter: (params) => {
        let d = `${params[0].axisValueLabel}<br>`
        let item = params.map((el) => {
          const key = legend.value[el.componentIndex]?.[1] || ''
          const value = chartData.value[key]?.[el.dataIndex] || 0

          return `<div class="flex items-center justify-between mt-1 gap-1">
            <span>${el.marker} ${el.seriesName}</span>
            <span>${value.toFixed(2)} ${el.seriesName.split(' ')[1] ?? ''}</span>
          </div>`
        })

        return d + item.join('')
      }
    },
    legend: {
      data: legend.value.map(([name]) => name),
      show: true
    },
    xAxis: {
      type: 'category',
      data: xAxisData.value
    },
    yAxis: {
      type: 'value',
      min: -minInterval,
      max: maxInterval,
      interval: 1,
      axisLabel: {
        formatter: (v) => {
          const num = v === 0 ? 0 : v > 0 ? Math.pow(10, v) : -Math.pow(10, -v)

          return num.toLocaleString()
        }
      }
    },
    series: legend.value.map(([name, key]) => ({
      name,
      type: 'line',
      smooth: true,
      showSymbol: true,
      data: (chartData.value[key] || []).map((value) => {
        if (value === 0) return 0

        const isPositive = value > 0
        const absItem = Math.abs(value)

        const min_value = Math.max(...intervalArr.filter((v) => v <= absItem))
        const min_index = intervalArr.findIndex((v) => v === min_value)

        const new_value =
          (absItem - min_value) / (intervalArr[min_index + 1] - intervalArr[min_index]) + min_index

        return isPositive ? new_value : -new_value
      })
    }))
  })
}

const handleQuery = () => {
  getChart().then(() => {
    nextTick(() => {
      render()
    })
  })
  getList()
  getTotal()
}

watch(
  () => [
    props.refreshKey,
    props.query.deptId,
    props.query.contractName,
    props.query.taskName,
    props.query.createTime?.[0],
    props.query.createTime?.[1]
  ],
  () => {
    handleQuery()
  },
  { immediate: true }
)

const exportChart = () => {
  if (!chart) return
  let img = new Image()
  img.src = chart.getDataURL({
    type: 'png',
    pixelRatio: 1,
    backgroundColor: '#fff'
  })

  img.onload = function () {
    let canvas = document.createElement('canvas')
    canvas.width = img.width
    canvas.height = img.height
    let ctx = canvas.getContext('2d')
    ctx?.drawImage(img, 0, 0)
    let dataURL = canvas.toDataURL('image/png')

    let a = document.createElement('a')

    let event = new MouseEvent('click')

    a.href = dataURL
    a.download = `瑞都日报统计数据.png`
    a.dispatchEvent(event)
  }
}

const exportData = async () => {
  const res = await IotRdDailyReportApi.exportRdDailyReportStatistics(props.query)
  download.excel(res, '瑞都日报统计数据.xlsx')
}

const exportAll = async () => {
  if (tab.value === '看板') exportChart()
  else exportData()
}

const router = useRouter()

const tolist = (id: number | null) => {
  console.log('id', id)
  if (!id) return

  router.push({
    name: 'IotRdDailyReport',
    query: {
      deptId: id,
      createTime: props.query.createTime
    }
  })
}

const handleRowClick = (row: List) => {
  console.log('row', row)
  tolist(row.id)
}

const getClickableRowClassName = () => 'summary-clickable-row'

const { ZmTable, ZmTableColumn } = useTableComponents()
</script>

<template>
  <div class="grid grid-rows-[96px_1fr] gap-2 h-full min-h-0">
    <div class="grid grid-cols-9 gap-4" v-loading="totalLoading">
      <div
        v-for="info in totalWorkKeys"
        :key="info[0]"
        class="bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-1 py-2 flex flex-col items-center justify-center gap-0.5 min-w-0">
        <div class="size-6.5" :class="info[3]"></div>
        <count-to
          class="text-xl font-medium leading-6"
          :start-val="0"
          :end-val="totalWork[info[0]]"
          :decimals="info[4]">
          <span class="text-xs leading-8 text-[var(--el-text-color-regular)]">暂无数据</span>
        </count-to>
        <div
          class="text-xs font-medium leading-5 text-[var(--el-text-color-regular)] whitespace-nowrap">
          {{ info[1] ? info[2] + '(' + info[1] + ')' : info[2] }}
        </div>
      </div>
    </div>

    <div class="bg-white dark:bg-[#1d1e1f] rounded-lg shadow flex flex-col p-3 gap-2 min-h-0">
      <div class="flex h-10 items-center justify-between">
        <el-button-group>
          <el-button
            size="default"
            :type="tab === '表格' ? 'primary' : 'default'"
            @click="handleSelectTab('表格')"
            >表格
          </el-button>
          <el-button
            size="default"
            :type="tab === '看板' ? 'primary' : 'default'"
            @click="handleSelectTab('看板')"
            >看板
          </el-button>
        </el-button-group>
        <h3 class="text-xl font-medium">{{ `${deptName}-${tab}` }}</h3>
        <el-button size="default" type="primary" @click="exportAll">导出</el-button>
      </div>
      <div class="flex-1 relative min-h-0">
        <el-auto-resizer class="absolute">
          <template #default="{ height }">
            <Motion
              as="div"
              :style="{ position: 'relative', overflow: 'hidden' }"
              :animate="{ height: `${height}px`, width: `100%` }"
              :transition="{ type: 'spring', stiffness: 200, damping: 25, duration: 0.3 }">
              <AnimatePresence :initial="false" mode="sync">
                <Motion
                  :key="currentTab"
                  as="div"
                  :initial="{ x: direction === 'left' ? '-100%' : '100%', opacity: 0 }"
                  :animate="{ x: '0%', opacity: 1 }"
                  :exit="{ x: direction === 'left' ? '50%' : '-50%', opacity: 0 }"
                  :transition="{ type: 'tween', stiffness: 300, damping: 30, duration: 0.3 }"
                  :style="{ position: 'absolute', left: 0, right: 0, top: 0 }">
                  <div :style="{ width: `100%`, height: `${height}px` }">
                    <zm-table
                      v-if="currentTab === '表格'"
                      :loading="listLoading"
                      :data="list"
                      :height="height"
                      show-border
                      :row-class-name="getClickableRowClassName"
                      @row-click="handleRowClick">
                      <zm-table-column label="部门" prop="name">
                        <template #default="{ row }">
                          <el-button text type="primary" @click.stop="tolist(row.id)">{{
                            row.name
                          }}</el-button>
                        </template>
                      </zm-table-column>
                      <zm-table-column label="油耗(万升)" prop="totalDailyFuel" />
                      <zm-table-column label="桥塞" prop="cumulativeBridgePlug" />
                      <zm-table-column label="趟数" prop="cumulativeRunCount" />
                      <zm-table-column label="井数" prop="cumulativeWorkingWell" />
                      <zm-table-column label="段数" prop="cumulativeWorkingLayers" />
                      <zm-table-column label="小时(H)" prop="cumulativeHourCount" />
                      <zm-table-column label="水方量(方)" prop="cumulativeWaterVolume" />
                      <zm-table-column label="台次">
                        <zm-table-column label="泵车" prop="cumulativePumpTrips" />
                        <zm-table-column label="仪表/混砂" prop="cumulativeMixSand" />
                      </zm-table-column>
                      <zm-table-column
                        label="设备利用率"
                        prop="utilizationRate"
                        cover-formatter
                        action
                        :real-value="
                          (row: List) => (Number(row.utilizationRate ?? 0) * 100).toFixed(2) + '%'
                        " />
                    </zm-table>
                    <div
                      ref="chartRef"
                      v-loading="chartLoading"
                      :key="dayjs().valueOf()"
                      v-else
                      :style="{ width: `100%`, height: `${height}px` }">
                    </div>
                  </div>
                </Motion>
              </AnimatePresence>
            </Motion>
          </template>
        </el-auto-resizer>
      </div>
    </div>
  </div>
</template>

<style scoped>
:deep(.summary-clickable-row) {
  cursor: pointer;
}
</style>
