<template>
  <div class="system-agent-ratio-bar">
    <div class="agent-ratio-legend" aria-hidden="true">
      <span v-for="agent in resolvedAgents" :key="agent.key">
        <i :style="{ background: agent.resolvedColor }"></i>{{ agent.name }}
      </span>
    </div>
    <div ref="chartElement" class="chart-body" role="img" :aria-label="ariaLabel"></div>
  </div>
</template>

<script setup>
import { computed, shallowRef } from 'vue'
import { CustomChart as EChartsCustomChart } from 'echarts/charts'
import { GridComponent, TooltipComponent } from 'echarts/components'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'

import { useEcharts } from '../../composables/useEcharts.js'
import { resolveCssColor, useThemeColors } from '../../composables/useThemeColors.js'

use([GridComponent, TooltipComponent, EChartsCustomChart, CanvasRenderer])

const props = defineProps({
  labels: { type: Array, required: true },
  agents: { type: Array, required: true },
  series: { type: Object, required: true }
})

const chartElement = shallowRef(null)
const themeColors = useThemeColors()
const resolvedAgents = computed(() =>
  props.agents.map((agent) => ({
    ...agent,
    resolvedColor: resolveCssColor(agent.color, themeColors.value.chartPrimary)
  }))
)

const ariaLabel = computed(() =>
  props.labels.map((label, dayIndex) => {
    const parts = resolvedAgents.value.map((agent) => (
      `${agent.name}${props.series[agent.key]?.[dayIndex] || 0}%`
    ))
    return `${label}${parts.join('；')}`
  }).join('；')
)

const stackedAgentRatioData = computed(() => props.labels.map((_, index) => [
  index,
  ...resolvedAgents.value.map((agent) => Number(props.series[agent.key]?.[index] || 0))
]))

const chartOptions = computed(() => ({
  backgroundColor: 'transparent',
  animation: true,
  animationDuration: 1200,
  animationDurationUpdate: 1200,
  animationEasing: 'linear',
  animationEasingUpdate: 'linear',
  grid: {
    top: 8,
    right: 16,
    bottom: 24,
    left: 34,
    containLabel: true
  },
  tooltip: {
    trigger: 'item',
    confine: true,
    appendToBody: true,
    backgroundColor: 'rgba(255, 255, 255, 0.98)',
    borderColor: 'rgba(148, 163, 184, 0.24)',
    borderWidth: 1,
    padding: [9, 10],
    textStyle: {
      color: '#334155',
      fontSize: 12,
      fontWeight: 700
    },
    extraCssText: 'border-radius:4px;box-shadow:0 12px 28px rgba(15,23,42,.12);',
    formatter: (params) => formatStackedTooltip(params)
  },
  xAxis: {
    type: 'category',
    data: props.labels,
    axisTick: { show: false },
    axisLine: { lineStyle: { color: 'rgba(148, 163, 184, 0.28)' } },
    axisLabel: {
      color: '#64748b',
      fontSize: 11,
      fontWeight: 700
    }
  },
  yAxis: {
    type: 'value',
    min: 0,
    max: 100,
    splitNumber: 5,
    axisLabel: {
      color: '#64748b',
      fontSize: 11,
      fontWeight: 700,
      formatter: '{value}%'
    },
    splitLine: { lineStyle: { color: 'rgba(226, 232, 240, 0.75)' } }
  },
  series: [{
    name: '智能体调用占比',
    type: 'custom',
    data: stackedAgentRatioData.value,
    renderItem: renderStackedAgentRatioBar,
    animationDelay: (index) => index * 18,
    tooltip: {
      formatter: (params) => formatStackedTooltip(params)
    }
  }]
}))

useEcharts(chartElement, chartOptions)

function renderStackedAgentRatioBar(params, api) {
  const categoryIndex = Number(api.value(0))
  const zeroPoint = api.coord([categoryIndex, 0])
  const xCenter = zeroPoint[0]
  const zeroY = zeroPoint[1]
  const categoryWidth = api.size([1, 0])?.[0] || 48
  const barWidth = Math.max(24, Math.min(34, categoryWidth * 0.48))
  const barX = xCenter - barWidth / 2
  let accumulated = 0
  const values = resolvedAgents.value.map((_, index) => Number(api.value(index + 1) || 0))
  const lastVisibleIndex = values.reduce((last, value, index) => (value > 0 ? index : last), -1)
  const children = []
  let topY = zeroY

  values.forEach((value, index) => {
    if (value <= 0) {
      return
    }
    const lower = accumulated
    const upper = accumulated + value
    const lowerY = api.coord([categoryIndex, lower])[1]
    const upperY = api.coord([categoryIndex, upper])[1]
    const height = Math.max(1, lowerY - upperY)
    topY = Math.min(topY, upperY)
    accumulated = upper
    children.push({
      type: 'rect',
      shape: {
        x: barX,
        y: upperY,
        width: barWidth,
        height,
        r: index === lastVisibleIndex ? [4, 4, 0, 0] : 0
      },
      style: {
        fill: resolvedAgents.value[index]?.resolvedColor || themeColors.value.chartPrimary,
        stroke: index === lastVisibleIndex ? 'transparent' : '#ffffff',
        lineWidth: index === lastVisibleIndex ? 0 : 1
      }
    })
  })

  if (!children.length) {
    return {
      type: 'group',
      children: []
    }
  }

  const totalHeight = Math.max(1, zeroY - topY)
  return {
    type: 'group',
    originX: xCenter,
    originY: zeroY,
    scaleY: 1,
    enterFrom: {
      scaleY: 0
    },
    transition: ['scaleY'],
    clipPath: {
      type: 'rect',
      shape: {
        x: barX,
        y: topY,
        width: barWidth,
        height: totalHeight
      },
      enterFrom: {
        shape: {
          x: barX,
          y: zeroY,
          width: barWidth,
          height: 0
        }
      },
      transition: ['shape']
    },
    children
  }
}

function formatStackedTooltip(params) {
  const index = Number(params?.data?.[0] ?? params?.dataIndex ?? 0)
  const label = props.labels[index] || params?.axisValueLabel || ''
  const rows = resolvedAgents.value
    .map((agent) => ({
      name: agent.name,
      color: agent.resolvedColor,
      value: Number(props.series[agent.key]?.[index] || 0)
    }))
    .filter((item) => item.value > 0)
  const details = rows.map((item) => (
    `<span style="display:inline-block;width:8px;height:8px;border-radius:2px;margin-right:6px;background:${item.color};"></span>${item.name}：${item.value}%`
  ))
  return [label, ...details].join('<br/>')
}
</script>

<style scoped>
.system-agent-ratio-bar {
  height: 292px;
  display: flex;
  flex-direction: column;
}

.agent-ratio-legend {
  min-height: 30px;
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 6px 14px;
  color: #475569;
  font-size: 12px;
  line-height: 1.4;
  margin-bottom: 8px;
}

.agent-ratio-legend span {
  max-width: 132px;
  display: inline-flex;
  align-items: center;
  min-width: 0;
  color: #475569;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.agent-ratio-legend i {
  flex: 0 0 auto;
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  margin-right: 5px;
}

.chart-body {
  width: 100%;
  flex: 1;
  min-height: 0;
}
</style>
