<template>
  <!-- 横向堆叠条形图 -->
  <div 
    ref="barScoringRateHorzontal" 
    class="echart_content" 
    :style="{ height: `${chartHeight}px` }"
  ></div>
</template>

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

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

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

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

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

// ===================== Props 配置 & 默认值 =====================
const props = withDefaults(defineProps<BarScoringRateHorizontalProps>(), {
  datax: () => [],
  datay: () => [],
  color: () => ['#3BA272', '#EE6666'],
  unit: '%',
  showNuitY: true,
  showTooltip: true,
  tooltipData: () => [],
  typeName: '',
  average: '0',
  markLineData: () => [],
  isClick: false
})

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

// ===================== 响应式变量 =====================
const barScoringRateHorzontal = ref<HTMLDivElement | null>(null)
let myChart: echarts.ECharts | null = null
const chartHeight = ref(0)
let firstBarColor = ''

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

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

// ===================== 图表初始化核心方法 =====================
function loadEchart() {
  const dom = barScoringRateHorzontal.value
  if (!dom) return

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

  // 初始化 ECharts
  myChart = echarts.init(dom, null, { devicePixelRatio: 2 })

  const {
    datax,
    datay,
    color,
    unit,
    showNuitY,
    showTooltip,
    tooltipData,
    typeName,
    average,
    markLineData,
    isClick
  } = props

  const colors = color
  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,
        zoomLock: true,
        brushSelect: false,
        preventDefaultMouseMove: false,
        handleSize: 0,
        handleStyle: {
          color: '#b8b8b8',
          borderWidth: 2
        },
        backgroundColor: 'transparent',
        showDataShadow: false,
        showDetail: false,
        filterMode: 'filter'
      }
    : null

  // 处理平均线/多条辅助线
  const isArrayAvg = Object.prototype.toString.call(average) === '[object Array]'
  let markNumber: number | (string | number)[] = 0
  let markLineArr: echarts.MarkLineDataItem[] = []

  if (isArrayAvg) {
    markNumber = average
  } else {
    markNumber = parseFloat(average as string) || 0
  }

  if (markLineData && markLineData.length > 0) {
    markLineData.forEach((item, index) => {
      if (item.isShow) {
        const lineColor = getCompareAnalysis[index] || '#F56C6C'
        markLineArr.push({
          name: '辅助线',
          xAxis: Number(item.value),
          label: {
            show: true,
            formatter: (e) => {
              return e.value === 0 ? '' : `${e.value}%`
            },
            position: 'start',
            color: lineColor,
            fontSize: 14
          },
          lineStyle: { color: lineColor }
        })
      }
    })
  } else {
    const val = Array.isArray(markNumber) ? markNumber[0] : markNumber
    markLineArr.push({
      name: '辅助线',
      xAxis: Number(val),
      label: {
        show: true,
        formatter: (e) => {
          return e.value === 0 ? '' : `${e.value}%`
        },
        position: 'start',
        color: '#F56C6C',
        fontSize: 14
      }
    })
  }

  const yAxisUnit = showNuitY ? unit : ''

  // 计算柱子颜色列表
  const barColorList = datay[0]?.map((item, key) => {
    const targetVal = Array.isArray(markNumber) ? markNumber[key] : markNumber
    const barColor = Number(item) >= Number(targetVal) ? colors[0] : colors[1]
    if (key === 0) {
      firstBarColor = barColor
    }
    return barColor
  }) || []

  // 组装 series 数据
  const seriesData: echarts.SeriesOption[] = []
  for (let i = 0; i < datay.length; i++) {
    const itemYData = datay[i].map((item, key) => {
      let itemColor = ''
      let borderColor = ''
      if (i === 0) {
        itemColor = barColorList[key]
        borderColor = barColorList[key]
      } else {
        itemColor = '#fff'
        borderColor = barColorList[key]
      }
      return {
        value: item,
        itemStyle: {
          color: itemColor,
          borderWidth: 1,
          borderColor: borderColor
        }
      }
    })

    const hasMarkLine = (!isArrayAvg && Number(markNumber) !== 0) || markLineData.length > 0

    seriesData.push({
      name: i === 0 ? '得分率' : '失分率',
      type: 'bar',
      stack: 'total',
      barMaxWidth: 50,
      barMinWidth: 14,
      label: {
        show: true,
        fontSize: 12,
        formatter: `{c}${unit}`,
        color: i === 1 ? '#666' : '#fff'
      },
      data: itemYData,
      markLine: hasMarkLine
        ? {
            symbol: ['triangle', 'none'],
            symbolSize: [8, 8],
            lineStyle: {
              type: 'dashed',
              color: '#F56C6C',
              width: 1
            },
            label: {
              formatter: `{c}${unit}`,
              position: 'start'
            },
            data: markLineArr
          }
        : undefined
    })
  }

  // ECharts 配置项
  const option: echarts.EChartsOption = {
    grid: {
      left: 20,
      right: 50,
      top: 20,
      bottom: 0,
      containLabel: true
    },
    dataZoom: dataZoom,
    tooltip: {
      show: showTooltip,
      trigger: showTooltip ? 'axis' : 'item',
      triggerOn: 'mousemove',
      confine: 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 pList = Array.isArray(params) ? params : [params]
        const title = pList[0]?.name || ''
        const value = pList[0]?.value ?? ''
        let tipHtml = `<div class="tooltip_content"><div class="tooltip_title">${title}</div>`
        tipHtml += `<div class="tooltip_student">${typeName}：${value}${unit}</div>`

        const tipItem = tooltipData[pList[0]?.dataIndex ?? 0]
        if (tipItem?.list?.length) {
          tipItem.list.forEach(item => {
            tipHtml += `<div class="tooltip_student">${item.name}：${item.value}</div>`
          })
        }
        tipHtml += '</div>'
        return tipHtml
      }
    },
    xAxis: {
      type: 'value',
      max: 100,
      axisLabel: {
        color: '#666666',
        fontSize: 14,
        formatter: `{value}${yAxisUnit}`
      },
      axisLine: {
        show: true,
        lineStyle: {
          color: '#E4E7ED',
          width: 1
        }
      },
      splitLine: {
        show: false
      },
      axisTick: {
        show: true,
        alignWithLabel: false
      }
    },
    yAxis: {
      type: 'category',
      data: datax,
      axisPointer: {
        type: 'shadow'
      },
      axisLabel: {
        interval: 0,
        color: '#666666',
        width: 80,
        fontSize: 14
      },
      inverse: true
    },
    series: seriesData
  }

  myChart.setOption(option, true)

  // 点击高亮逻辑
  if (isClick && myChart) {
    const gridModel = myChart.getModel().getComponent('grid')
    const gridRect = gridModel.coordinateSystem.getRect()
    const singleLabelHeight = gridRect.height / xLen

    // 默认选中第一项
    if (datax.length > 0) {
      const defaultPixelPos = myChart.convertToPixel({ yAxisIndex: 0 }, datax[0])
      myChart.setOption({
        graphic: {
          id: 'highlight-box',
          type: 'rect',
          shape: {
            y: defaultPixelPos - singleLabelHeight / 2,
            x: gridRect.x,
            width: gridRect.width,
            height: singleLabelHeight
          },
          style: {
            fill: firstBarColor + '30'
          }
        }
      })
    }

    // 柱子点击事件
    myChart.on('click', (params) => {
      if (params.componentSubType !== 'bar') return

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

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

// ===================== 监听 & 生命周期 =====================
// 监听 datax 变化，动态计算高度并重绘图表
watch(
  () => props.datax,
  async () => {
    const len = props.datax.length
    let h = len * 24 + 60
    if (h < 380) h = 380
    if (h > 600) h = 600
    chartHeight.value = h
    await nextTick()
    loadEchart()
  },
  { deep: true }
)

// 监听辅助线数据变化
watch(
  () => props.markLineData,
  () => loadEchart(),
  { deep: true }
)

// 组件挂载初始化
onMounted(async () => {
  const len = props.datax.length
  let h = len * 24 + 60
  if (h < 380) h = 380
  if (h > 600) h = 600
  chartHeight.value = h
  await nextTick()
  loadEchart()
})

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

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