<template>
  <div ref="barEchartHorizontal" class="echart_content" :style="{ height: `${chartHeight}px` }"></div>
</template>

<script setup lang="ts">
import { ref, watch, onMounted, onBeforeUnmount, nextTick, withDefaults } from 'vue'
import _ from 'lodash'
import * as echarts from 'echarts'
import { getCompareAnalysis } from '@/utils/common'

// ===================== 类型定义 =====================
/** 单条辅助线配置 */
interface MarkLineItem {
  isShow: boolean
  value: number | string
}

/** 悬浮提示子项 */
interface TooltipListItem {
  name?: string
  value: string | number
}

/** 悬浮提示数据 */
interface TooltipDataItem {
  rank?: string
  list: TooltipListItem[]
}

/** Props 类型 */
interface BarHorizontalProps {
  datax: string[]
  datay: (number | string)[]
  color: string
  isClick: boolean
  markNumber: number | number[]
  markLineData: MarkLineItem[]
  unit: string
  typeName: string
  tooltipData: TooltipDataItem[]
}

// ===================== Props 与默认值 =====================
const props = withDefaults(defineProps<BarHorizontalProps>(), {
  datax: () => [1, 2, 3, 4, 5, 6, 7].map(String),
  datay: () => [50, 60, 70, 80, 70, 70, 100],
  color: '#FAC858',
  isClick: false,
  markNumber: 65,
  markLineData: () => [],
  unit: '%',
  typeName: '',
  tooltipData: () => []
})

// 自定义事件
const emit = defineEmits<{
  HandleChartClick: [index: number, xName: string]
}>()

// ===================== 响应式变量 =====================
const barEchartHorizontal = ref<HTMLDivElement | null>(null)
let echart: echarts.ECharts | null = null
const chartHeight = ref(0)

// 窗口 resize 节流
const handleResize = _.throttle(async () => {
  await nextTick()
  loadEchart()
}, 500)

// 全局监听窗口变化（替代 Vue2 created）
window.addEventListener('resize', handleResize)

// ===================== 工具函数 =====================
/** 计算坐标轴最大值规则 */
function getMaxValue(value: number): number {
  const thresholdMap = [
    { maxThreshold: 0.3, bound: 0.3 },
    { maxThreshold: 0.6, bound: 0.6 },
    { maxThreshold: 1, bound: 1 },
    { maxThreshold: 1.5, bound: 1.5 },
    { maxThreshold: 2, bound: 2 },
    { maxThreshold: 4, bound: 4 },
    { maxThreshold: 8, bound: 8 },
    { maxThreshold: 10, bound: 10 },
    { maxThreshold: 40, bound: 40 },
    { maxThreshold: 50, bound: 50 },
    { maxThreshold: 60, bound: 60 },
    { maxThreshold: 70, bound: 70 },
    { maxThreshold: 80, bound: 80 },
    { maxThreshold: 90, bound: 90 },
    { maxThreshold: 100, bound: 100 },
    { maxThreshold: 120, bound: 120 },
    { maxThreshold: 150, bound: 150 },
    { maxThreshold: 180, bound: 180 },
    { maxThreshold: 200, bound: 200 },
    { maxThreshold: 250, bound: 250 },
    { maxThreshold: 300, bound: 300 },
    { maxThreshold: 350, bound: 350 },
    { maxThreshold: 400, bound: 400 },
    { maxThreshold: 450, bound: 450 },
    { maxThreshold: 500, bound: 500 },
    { maxThreshold: 600, bound: 600 },
    { maxThreshold: 700, bound: 700 }
  ]

  const matchedRule = thresholdMap.find(
    ({ maxThreshold }) => value === maxThreshold || value < maxThreshold
  )

  if (matchedRule) {
    return matchedRule.bound
  }
  return Math.ceil(value / 10) * 10
}

/** 设置图表高度 */
function setChartHeight() {
  const len = props.datax.length
  let h = len * 24 + 60
  if (h < 380) h = 380
  if (h > 600) h = 600
  chartHeight.value = h
}

// ===================== 初始化 ECharts =====================
function loadEchart() {
  const dom = barEchartHorizontal.value
  if (!dom) return

  // 销毁旧实例
  if (echart) {
    echart.dispose()
    echart = null
  }

  // 初始化实例
  echart = echarts.init(dom, null, { devicePixelRatio: 2 })

  const { datax, datay, color, isClick, markNumber, markLineData, unit, typeName, tooltipData } = props
  const totalHeight = dom.clientHeight
  const xLen = datax.length

  // 计算单条高度 & 滚动条配置
  const singleSeriesHeight = Math.ceil((totalHeight - 97) / xLen)
  const barMinHeight = 20
  const dataZoomNum = Math.floor((totalHeight - 97) / barMinHeight)
  const dataZoomEnd = Math.floor((100 / xLen) * dataZoomNum)

  // 纵向 dataZoom
  const dataZoom: echarts.DataZoomSliderOption | null = singleSeriesHeight < barMinHeight
    ? {
        start: 0,
        end: dataZoomEnd,
        type: 'slider',
        show: true,
        borderColor: 'transparent',
        borderCap: 'round',
        yAxisIndex: [0],
        width: 8,
        right: 20,
        top: 20,
        bottom: 20,
        fillerColor: 'transparent',
        zoomLock: true,
        handleSize: '0',
        handleStyle: {
          color: '#b8b8b8',
          borderWidth: 2
        },
        backgroundColor: 'transparent',
        showDataShadow: false,
        showDetail: false,
        filterMode: 'filter'
      }
    : null

  // 处理辅助线数据
  let maxMarkNumber = 0
  const markLineArr: echarts.MarkLineDataItem[] = []
  const isMarkArr = Array.isArray(markNumber)

  if (isMarkArr) {
    const numArr = markNumber as number[]
    maxMarkNumber = numArr.length ? Math.max(...numArr) : 0
    numArr.forEach(item => {
      markLineArr.push({
        name: '辅助线',
        xAxis: item,
        label: {
          show: true,
          formatter: (e) => `${e.value}${unit}`,
          position: 'start',
          color: '#F56C6C',
          fontSize: 14
        }
      })
    })
  } else if (markLineData.length) {
    const tempNum: number[] = []
    markLineData.forEach((item, index) => {
      tempNum.push(Number(item.value))
      if (item.isShow) {
        const lineColor = getCompareAnalysis[index] || '#F56C6C'
        markLineArr.push({
          name: '辅助线',
          xAxis: Number(item.value),
          label: {
            show: true,
            formatter: (e) => `${e.value}${unit}`,
            position: 'start',
            color: lineColor,
            fontSize: 14
          },
          lineStyle: { color: lineColor }
        })
      }
    })
    maxMarkNumber = tempNum.length ? Math.max(...tempNum) : 0
  } else {
    maxMarkNumber = markNumber as number
    markLineArr.push({
      name: '辅助线',
      xAxis: markNumber as number,
      label: {
        show: true,
        formatter: (e) => `${e.value}${unit}`,
        position: 'start',
        color: '#F56C6C',
        fontSize: 14
      }
    })
  }

  // 过滤有效数值 & 计算X轴最大值
  const validData = datay.filter(num => !isNaN(Number(num))).map(Number)
  const maxValue = validData.length ? Math.max(...validData) : 0
  const nearestValue = getMaxValue(maxValue)
  const xAxisMax = maxMarkNumber > nearestValue ? maxMarkNumber : nearestValue

  // ECharts 配置项
  const option: echarts.EChartsOption = {
    tooltip: {
      axisPointer: { type: 'shadow' },
      trigger: 'axis',
      triggerOn: 'mousemove | click',
      confine: true,
      enterable: true,
      borderColor: '#fff',
      extraCssText: 'border-radius: 4px;padding:5px 0 5px 5px;white-space:normal;word-wrap:break-word;max-width: 400px;',
      formatter: (params) => {
        const p = Array.isArray(params) ? params[0] : params
        const title = p.name || ''
        const val = p.value ?? ''
        let tipHtml = `<div class="tooltip_content">`

        if (tooltipData.length) {
          const tipItem = tooltipData[p.dataIndex]
          if (typeName) {
            tipHtml += `<div class="tooltip_title">${title}</div>`
            tipHtml += `<div class="tooltip_student">${typeName}：${val}${unit}</div>`
          } else {
            tipHtml += `<div class="tooltip_title">${title} ${tipItem?.rank ?? ''}</div>`
          }
          if (tipItem?.list?.length) {
            tipItem.list.forEach(item => {
              if (item.name) {
                tipHtml += `<div class="tooltip_student">${item.name}：${item.value}</div>`
              } else {
                tipHtml += `<div class="tooltip_student">${item.value}</div>`
              }
            })
          }
        } else {
          tipHtml += `<div class="tooltip_title">${title}</div>`
          tipHtml += `<div class="tooltip_student">${typeName}：${val}${unit}</div>`
        }
        tipHtml += `</div>`
        return tipHtml
      }
    },
    grid: {
      left: 40,
      right: 50,
      top: 20,
      bottom: 0,
      containLabel: true
    },
    dataZoom: dataZoom,
    yAxis: {
      type: 'category',
      data: datax,
      axisPointer: { type: 'shadow' },
      axisLabel: {
        interval: 0,
        color: '#666666',
        fontSize: 14
      },
      splitArea: {
        show: true,
        areaStyle: {
          color: ['#fafafa', '#ffffff']
        }
      },
      inverse: true
    },
    xAxis: {
      type: 'value',
      max: xAxisMax,
      axisLabel: {
        formatter: `{value}${unit === '%' ? unit : ''}`,
        color: '#666666',
        fontSize: 14
      },
      axisLine: {
        show: true,
        lineStyle: {
          color: '#E4E7ED',
          width: 1
        }
      },
      splitLine: {
        show: false
      },
      axisTick: {
        show: true,
        alignWithLabel: false
      }
    },
    series: [
      {
        name: '',
        type: 'bar',
        barMaxWidth: 50,
        barMinWidth: 14,
        itemStyle: { color: color },
        label: {
          show: true,
          position: 'right',
          formatter: `{c}${unit}`,
          color: '#666',
          fontSize: 14
        },
        data: datay,
        markLine: markNumber
          ? {
              symbol: ['triangle', 'none'],
              symbolSize: [8, 8],
              lineStyle: {
                type: 'dashed',
                color: '#F56C6C',
                width: 1
              },
              label: {
                formatter: `{c}${unit}`,
                position: 'start'
              },
              data: markLineArr
            }
          : undefined
      }
    ]
  }

  echart.setOption(option)

  // 点击高亮 + 点击事件
  if (isClick && echart) {
    const gridModel = echart.getModel().getComponent('grid')
    const gridRect = gridModel.coordinateSystem.getRect()
    const singleLabelHeight = gridRect.height / xLen

    // 默认高亮第一项
    if (datax.length > 0) {
      const defaultPixelPos = echart.convertToPixel({ yAxisIndex: 0 }, datax[0])
      echart.setOption({
        graphic: {
          id: 'highlight-box',
          type: 'rect',
          shape: {
            y: defaultPixelPos - singleLabelHeight / 2,
            x: gridRect.x,
            width: gridRect.width,
            height: singleLabelHeight
          },
          style: {
            fill: 'rgba(84,112,198,0.1)'
          }
        }
      })
    }

    // 柱子点击监听
    echart.on('click', (params) => {
      if (params.componentSubType !== 'bar') return

      const pixelPosition = echart.convertToPixel({ yAxisIndex: 0 }, params.name)
      echart.setOption({
        graphic: {
          id: 'highlight-box',
          type: 'rect',
          shape: {
            y: pixelPosition - singleLabelHeight / 2,
            x: gridRect.x,
            width: gridRect.width,
            height: singleLabelHeight
          },
          style: {
            fill: (params.color as string) + '30'
          }
        }
      })

      emit('HandleChartClick', params.dataIndex, params.name as string)
    })
  }
}

// ===================== 监听 & 生命周期 =====================
// 数据变化 → 重算高度 + 重绘
watch(
  () => props.datay,
  async () => {
    setChartHeight()
    await nextTick()
    loadEchart()
  },
  { deep: true }
)

// 辅助线变化 → 重绘
watch(
  () => props.markLineData,
  () => loadEchart(),
  { deep: true }
)

// 组件挂载初始化
onMounted(async () => {
  setChartHeight()
  await nextTick()
  loadEchart()
})

// 组件卸载：清除监听、销毁图表
onBeforeUnmount(() => {
  window.removeEventListener('resize', handleResize)
  if (echart) {
    echart.dispose()
    echart = null
  }
})
</script>

<style lang="scss" scoped>
.echart_content {
  width: 100%;
}
</style>