<template>
  <!-- 竖向堆叠条形图 -->
  <div 
    ref="barScoringRateVertical" 
    class="chart_width" 
    :style="{ height: `${height}px` }"
  ></div>
</template>

<script setup lang="ts">
import { ref, watch, onMounted, onBeforeUnmount, 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 BarScoringRateVerticalProps {
  datax: string[]
  datay: (string | number)[][]
  color: string[]
  height?: number
  unit?: string
  showNuitY?: boolean
  showTooltip?: boolean
  tooltipData: TooltipDataItem[]
  typeName: string
  average: string | number | (string | number)[]
  markLineData: MarkLineItem[]
  isClick: boolean
}

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

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

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

// 窗口 resize 节流
const handleResize = throttle(() => {
  if (myChart) {
    myChart.resize()
  }
}, 500)

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

// ===================== 工具函数 & 图表初始化 =====================
function loadEchart() {
  const dom = barScoringRateVertical.value
  if (!dom) return

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

  // 初始化 echarts
  myChart = echarts.init(dom, null, { devicePixelRatio: 2 })
  const colors = props.color
  const { datax, datay, unit, showNuitY, showTooltip, tooltipData, typeName, average, markLineData, isClick } = props

  // 计算柱子宽度 & 滚动条
  const totalWidth = dom.clientWidth
  const xLen = datax.length
  const singleSeriesWidth = Math.ceil((totalWidth - 140) / xLen)
  const barMinWidth = 30
  const dataZoomNum = Math.floor((totalWidth - 140) / barMinWidth)
  const dataZoomEnd = Math.floor((100 / xLen) * dataZoomNum)

  // 滚动条配置
  const dataZoom: echarts.DataZoomSliderOption | null = singleSeriesWidth < barMinWidth
    ? {
        start: 0,
        end: dataZoomEnd,
        type: 'slider',
        show: true,
        borderColor: 'transparent',
        borderCap: 'round',
        xAxisIndex: [0],
        height: 8,
        left: 20,
        right: 20,
        bottom: 0,
        fillerColor: 'transparent',
        zoomLock: true,
        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 color = getCompareAnalysis[index] || '#F56C6C'
        markLineArr.push({
          symbol: 'circle',
          type: 'value',
          yAxis: Number(item.value),
          lineStyle: { color },
          label: { color }
        })
      }
    })
  } else {
    const val = Array.isArray(markNumber) ? markNumber[0] : markNumber
    markLineArr.push({
      type: 'value',
      yAxis: Number(val)
    })
  }

  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: 20,
      label: {
        show: singleSeriesWidth > 26,
        fontSize: singleSeriesWidth < 60 ? 8 : 12,
        formatter: (e) => {
          if (e.value === '0' || e.value === '0.00') {
            return ''
          }
          return `${e.value}%`
        },
        color: i === 1 ? '#666' : '#fff'
      },
      data: itemYData,
      markLine: hasMarkLine
        ? {
            symbol: ['circle', 'arrow'],
            symbolSize: [8, 8],
            symbolOffset: [[0, 0], [0, 0]],
            label: {
              color: '#F56C6C',
              fontSize: 14,
              formatter: `{c}${unit}`,
              position: 'end'
            },
            data: markLineArr,
            lineStyle: markLineData.length ? undefined : { color: '#F56C6C' }
          }
        : undefined
    })
  }

  // X轴文字截断逻辑
  function formatXLabel(value: string): string {
    const charWidth = 14
    const valueWidth = value.length * charWidth
    if (valueWidth <= singleSeriesWidth) return value

    if (singleSeriesWidth < 80) {
      return valueWidth > 80 ? `${value.slice(0, 2)}...${value.slice(-3)}` : value
    } else {
      const maxLength = Math.floor(singleSeriesWidth / charWidth) - 1
      return value.slice(0, maxLength) + '...'
    }
  }

  // ECharts 配置项
  const option: echarts.EChartsOption = {
    grid: {
      top: 20,
      left: 40,
      right: 60,
      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 tooltip = `<div class="tooltip_content"><div class="tooltip_title">${title}</div>`
        tooltip += `<div class="tooltip_student">${typeName}：${value}${unit}</div>`

        const tipItem = tooltipData[pList[0]?.dataIndex ?? 0]
        if (tipItem?.list?.length) {
          tipItem.list.forEach(item => {
            tooltip += `<div class="tooltip_student">${item.name}：${item.value}</div>`
          })
        }
        tooltip += '</div>'
        return tooltip
      }
    },
    yAxis: {
      type: 'value',
      max: 100,
      axisLabel: {
        color: '#666666',
        fontSize: 14,
        formatter: `{value}${yAxisUnit}`
      },
      splitArea: {
        show: true,
        areaStyle: {
          color: ['#fafafa', '#ffffff']
        }
      }
    },
    xAxis: {
      type: 'category',
      data: datax,
      axisPointer: {
        type: 'shadow'
      },
      axisLabel: {
        interval: 0,
        rotate: singleSeriesWidth < 80 ? 45 : 0,
        color: '#666666',
        fontSize: 14,
        formatter: formatXLabel
      }
    },
    series: seriesData
  }

  myChart.setOption(option, true)

  // 柱子点击 + 高亮背景
  if (isClick && myChart) {
    const gridModel = myChart.getModel().getComponent('grid')
    const gridRect = gridModel.coordinateSystem.getRect()
    const singleLabelWidth = gridRect.width / xLen

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

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

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

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

// ===================== 监听 & 生命周期 =====================
watch(
  () => props.datax,
  () => loadEchart(),
  { deep: true }
)

watch(
  () => props.markLineData,
  () => loadEchart(),
  { deep: true }
)

onMounted(() => {
  loadEchart()
})

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

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