<template>
  <el-row :gutter="20">
    <el-col :span="6" :xs="24">
      <ContentWrap class="h-1/1">
        <el-input
          v-model="keyword"
          clearable
          placeholder="搜索设备或参数"
          class="!w-1/1"
          @input="handleKeywordChange"
        />
        <div class="mt-12px">
          <el-tree
            ref="treeRef"
            v-loading="treeLoading"
            :data="treeData"
            :props="treeProps"
            node-key="id"
            highlight-current
            @node-click="handleTreeNodeClick"
          />
        </div>
      </ContentWrap>
    </el-col>

    <el-col :span="18" :xs="24">
      <ContentWrap>
        <el-form class="-mb-15px" :inline="true">
          <el-form-item label="时间">
            <el-date-picker
              v-model="dateRange"
              type="daterange"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              value-format="YYYY-MM-DD"
              :shortcuts="dateShortcuts"
              :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
              class="!w-360px"
            />
          </el-form-item>
          <el-form-item>
            <el-button :disabled="!selectedParam" @click="handleQuery">
              <Icon icon="ep:search" class="mr-5px" /> 搜索
            </el-button>
            <el-button :disabled="!selectedParam" @click="resetQuery">
              <Icon icon="ep:refresh" class="mr-5px" /> 重置
            </el-button>
          </el-form-item>
        </el-form>
      </ContentWrap>

      <ContentWrap>
        <el-alert
          v-if="selectedParam"
          :title="selectedParamTitle"
          type="info"
          :closable="false"
          class="mb-12px"
        />
        <div v-loading="chartLoading">
          <el-empty v-if="!selectedParam" description="请选择左侧参数" />
          <EChart v-else :key="chartRenderKey" :options="chartOption" height="70vh" />
        </div>
      </ContentWrap>
    </el-col>
  </el-row>
</template>

<script setup lang="ts">
import type { EChartsOption } from 'echarts'
import dayjs from 'dayjs'
import { Echart as EChart } from '@/components/Echart'
import { OrganizationApi } from '@/api/mes/organization'
import { DeviceModelAttributeApi } from '@/api/iot/devicemodelattribute'

defineOptions({ name: 'DeviceParamAnalysis' })

type TreeNodeType = 'device' | 'param'

type DeviceTreeNode = {
  id: string
  label: string
  type: TreeNodeType
  children?: DeviceTreeNode[]
  deviceId?: number
  modelId?: number
  paramKey?: string
  unit?: string
}

type ApiTreeParameter = {
  id: number
  name: string
  code?: string
  unit?: string | null
}

type ApiTreeEquipment = {
  id: number
  name: string
  parameters?: ApiTreeParameter[]
}

type ApiTreeOrg = {
  id: number
  name: string
  equipments?: ApiTreeEquipment[]
}

const message = useMessage()

const treeRef = ref()
const treeLoading = ref(false)
const keyword = ref('')
const treeProps = { children: 'children', label: 'label' }
const treeData = ref<DeviceTreeNode[]>([])

const selectedDeviceId = ref<number | undefined>(undefined)
const selectedModelId = ref<number | undefined>(undefined)

const selectedParam = ref<DeviceTreeNode | null>(null)
const chartLoading = ref(false)
const chartXAxis = ref<string[]>([])
const chartSeries = ref<{ name: string; data: Array<number | null> }[]>([])
const chartRenderKey = ref(0)

const buildDefaultDateRange = (): [string, string] => {
  const end = dayjs().endOf('day')
  const start = end.subtract(6, 'day').startOf('day')
  return [start.format('YYYY-MM-DD'), end.format('YYYY-MM-DD')]
}

const dateRange = ref<[string, string]>(buildDefaultDateRange())

const dateShortcuts = [
  {
    text: '最近 7 天',
    value: () => {
      const end = dayjs().endOf('day').toDate()
      const start = dayjs().subtract(6, 'day').startOf('day').toDate()
      return [start, end]
    }
  },
  {
    text: '上周',
    value: () => {
      const start = dayjs().subtract(1, 'week').startOf('week').toDate()
      const end = dayjs().subtract(1, 'week').endOf('week').toDate()
      return [start, end]
    }
  },
  {
    text: '上个月',
    value: () => {
      const start = dayjs().subtract(1, 'month').startOf('month').toDate()
      const end = dayjs().subtract(1, 'month').endOf('month').toDate()
      return [start, end]
    }
  },
  {
    text: '三个月内',
    value: () => {
      const end = dayjs().endOf('day').toDate()
      const start = dayjs().subtract(3, 'month').startOf('day').toDate()
      return [start, end]
    }
  }
]

const selectedParamTitle = computed(() => {
  const param = selectedParam.value
  if (!param) return ''
  const unitText = param.unit ? `（${param.unit}）` : ''
  return `参数：${param.label}${unitText}`
})

const chartOption = computed<EChartsOption>(() => {
  const unit = selectedParam.value?.unit
  return {
    tooltip: { trigger: 'axis' },
    legend: { top: 10, left: 'center', type: 'scroll' },
    grid: { left: 50, right: 60, top: 80, bottom: 40, containLabel: true },
    xAxis: {
      type: 'category',
      boundaryGap: false,
      data: chartXAxis.value
    },
    yAxis: {
      type: 'value',
      name: unit || ''
    },
    series: chartSeries.value.map((s) => ({
      type: 'line',
      name: s.name,
      smooth: false,
      showSymbol: false,
      data: s.data
    }))
  }
})

let keywordTimer: number | undefined
const handleKeywordChange = () => {
  if (keywordTimer) window.clearTimeout(keywordTimer)
  keywordTimer = window.setTimeout(() => {
    loadTree()
  }, 300)
}

const buildTreeFromApi = (orgs: ApiTreeOrg[]): DeviceTreeNode[] => {
  return (
    orgs?.map((org) => {
      const equipments = Array.isArray(org?.equipments) ? org.equipments : []
      const equipmentNodes: DeviceTreeNode[] = equipments.map((eq) => {
        const params = Array.isArray(eq?.parameters) ? eq.parameters : []
        const paramNodes: DeviceTreeNode[] = params.map((p) => ({
          id: `param-${eq.id}-${p.id}`,
          label: p?.name ?? p?.code ?? String(p?.id ?? ''),
          type: 'param',
          deviceId: Number(eq.id),
          modelId: Number(p.id),
          paramKey: p?.code ? String(p.code) : undefined,
          unit: p?.unit ? String(p.unit) : undefined
        }))

        return {
          id: `equipment-${org.id}-${eq.id}`,
          label: eq?.name ?? String(eq?.id ?? ''),
          type: 'device',
          children: paramNodes.length ? paramNodes : undefined
        }
      })

      return {
        id: `org-${org.id}`,
        label: org?.name ?? String(org?.id ?? ''),
        type: 'device',
        children: equipmentNodes.length ? equipmentNodes : undefined
      }
    }) ?? []
  )
}

const loadTree = async () => {
  treeLoading.value = true
  try {
    const data = await OrganizationApi.deviceParameterAnalysis({ keyword: keyword.value || undefined })
    treeData.value = buildTreeFromApi(Array.isArray(data) ? (data as ApiTreeOrg[]) : [])
    if (keyword.value) {
      treeRef.value?.setCurrentKey?.(undefined)
      selectedParam.value = null
      selectedDeviceId.value = undefined
      selectedModelId.value = undefined
      chartXAxis.value = []
      chartSeries.value = []
    }
  } catch {
    message.error('获取树数据失败')
  } finally {
    treeLoading.value = false
  }
}

const ensureDateRange = () => {
  if (!dateRange.value || dateRange.value.length !== 2) {
    dateRange.value = buildDefaultDateRange()
  }
}

const resetChartData = () => {
  chartXAxis.value = []
  chartSeries.value = []
  chartRenderKey.value++
}

const toNumber = (value: any) => {
  if (typeof value === 'number') return value
  if (typeof value === 'string') {
    const n = Number(value)
    return Number.isFinite(n) ? n : 0
  }
  if (Array.isArray(value)) return 0
  if (value && typeof value === 'object') {
    const maybe = value.value ?? value.val ?? value.count ?? value.amount
    const n = Number(maybe)
    return Number.isFinite(n) ? n : 0
  }
  return 0
}

const fetchChart = async () => {
  const param = selectedParam.value
  if (!selectedDeviceId.value || !selectedModelId.value) return

  ensureDateRange()
  const [start, end] = dateRange.value
  if (!start || !end) return

  const buildDateTime = (date: string, suffix: string) => {
    return date.includes(':') ? date : `${date} ${suffix}`
  }

  chartLoading.value = true
  resetChartData()
  try {
    const data = await DeviceModelAttributeApi.operationAnalysisDetails({
      deviceId: selectedDeviceId.value,
      modelId: selectedModelId.value,
      collectionStartTime: buildDateTime(start, '00:00:00'),
      collectionEndTime: buildDateTime(end, '23:59:59')
    })
    const rows: Record<string, any>[] = Array.isArray(data) ? data : []
    if (!rows.length) {
      chartXAxis.value = []
      chartSeries.value = []
      return
    }

    const firstRow = rows[0] || {}
    const keys = Object.keys(firstRow)
    const xKey = keys.find((k) => /time|date|时间|日期/i.test(k))
    if (xKey) {
      const sortedRows = [...rows].sort((a, b) =>
        String(a?.[xKey] ?? '').localeCompare(String(b?.[xKey] ?? ''))
      )
      chartXAxis.value = sortedRows.map((r) => String(r?.[xKey] ?? ''))

      const seriesKeys = keys.filter((k) => k !== xKey)
      const seriesMap = new Map<string, Array<number | null>>()
      const ensureSeries = (name: string) => {
        if (!seriesMap.has(name)) {
          seriesMap.set(name, Array(sortedRows.length).fill(null))
        }
        return seriesMap.get(name)!
      }

      sortedRows.forEach((row, rowIndex) => {
        seriesKeys.forEach((k) => {
          const v = row?.[k]
          if (Array.isArray(v)) {
            v.forEach((item) => {
              const name = String(item?.attributeName ?? k)
              const series = ensureSeries(name)
              series[rowIndex] = toNumber(item?.addressValue ?? item?.value ?? item?.val)
            })
            return
          }
          const series = ensureSeries(k)
          series[rowIndex] = toNumber(v)
        })
      })

      chartSeries.value = Array.from(seriesMap.entries()).map(([name, data]) => ({ name, data }))
    } else {
      chartXAxis.value = keys
      const values = keys.map((k) => toNumber(firstRow[k]))
      chartSeries.value = [{ name: param?.label || '参数', data: values }]
    }
  } catch {
    message.error('获取图表数据失败')
  } finally {
    chartLoading.value = false
  }
}

const handleTreeNodeClick = async (data: DeviceTreeNode) => {
  if (data.type !== 'param') return
  selectedParam.value = data
  selectedDeviceId.value = data.deviceId
  selectedModelId.value = data.modelId
  dateRange.value = buildDefaultDateRange()
  await fetchChart()
}

const handleQuery = async () => {
  if (!selectedParam.value) return
  await fetchChart()
}

const resetQuery = async () => {
  dateRange.value = buildDefaultDateRange()
  await fetchChart()
}

onMounted(async () => {
  await loadTree()
})
</script>

<style scoped lang="scss">
:deep(.el-tree) {
  max-height: calc(100vh - 280px);
  overflow: auto;
}
</style>
