<template>
  <div class="chart-analysis-container">
    <!-- 仪表盘：整体健康度 -->
    <div class="gauges-row">
      <!-- 月度仪表盘 -->
      <div class="chart-card gauge-card">
        <div class="chart-header">
          <div class="chart-title">
            <!-- 月度健康度 -->
            {{ activeTab === BudgetCategory.Expense ? '使用情况（月度）' : '完成情况（月度）' }}
            <van-icon
              name="info-o"
              size="16"
              color="var(--van-primary-color)"
              style="margin-left: auto; cursor: pointer"
              @click="showDescriptionPopup = true; activeDescTab = 'month'"
            />
          </div>
        </div>
        <div class="gauge-wrapper">
          <div
            ref="monthGaugeRef"
            class="chart-body gauge-chart"
            :style="{ transform: activeTab === BudgetCategory.Expense ? 'scaleX(-1)' : '' }"
          />
          <div class="gauge-text-overlay">
            <div
              class="remaining-label"
            >
              {{
                activeTab === BudgetCategory.Expense
                  ? (
                    overallStats.month.current > overallStats.month.limit
                      ? '超支'
                      : '余额'
                  )
                  : overallStats.month.current > overallStats.month.limit
                    ? '超额'
                    : '差额'
              }}
            </div>
            <div
              class="remaining-value"
              :style="{ color:
                overallStats.month.current > overallStats.month.limit
                  ? activeTab === BudgetCategory.Expense ? 'var(--van-danger-color)' : 'var(--van-success-color)'
                  : ''
              }"
            >
              ¥{{ formatMoney(Math.abs(overallStats.month.limit - overallStats.month.current)) }}
            </div>
          </div>
        </div>
        <div class="gauge-footer compact">
          <div class="gauge-item">
            <span class="label">
              {{ activeTab === BudgetCategory.Expense ? '已用' : '已收' }}
            </span>
            <span class="value expense">¥{{ formatMoney(overallStats.month.current) }}</span>
          </div>
          <div class="gauge-item">
            <span class="label">
              {{ activeTab === BudgetCategory.Expense ? '预算' : '目标' }}
            </span>
            <span class="value">¥{{ formatMoney(overallStats.month.limit) }}</span>
          </div>
        </div>
      </div>

      <!-- 年度仪表盘 -->
      <div class="chart-card gauge-card">
        <div class="chart-header">
          <div class="chart-title">
            {{ activeTab === BudgetCategory.Expense ? '使用情况（年度）' : '完成情况（年度）' }}
            <van-icon
              name="info-o"
              size="16"
              color="var(--van-primary-color)"
              style="margin-left: auto; cursor: pointer"
              @click="showDescriptionPopup = true; activeDescTab = 'year'"
            />
          </div>
        </div>
        <div class="gauge-wrapper">
          <div
            ref="yearGaugeRef"
            class="chart-body gauge-chart"
            :style="{ transform: activeTab === BudgetCategory.Expense ? 'scaleX(-1)' : '' }"
          />
          <div class="gauge-text-overlay">
            <div
              class="remaining-label"
            >
              {{ activeTab === BudgetCategory.Expense ? (overallStats.year.current > overallStats.year.limit ? '超支' : '余额') : '差额' }}
            </div>
            <div
              class="remaining-value"
              :style="{ color: activeTab === BudgetCategory.Expense && overallStats.year.current > overallStats.year.limit ? 'var(--van-danger-color)' : '' }"
            >
              ¥{{ formatMoney(Math.abs(overallStats.year.limit - overallStats.year.current)) }}
            </div>
          </div>
        </div>
        <div class="gauge-footer compact">
          <div class="gauge-item">
            <span class="label">
              {{ activeTab === BudgetCategory.Expense ? '已用' : '已收' }}
            </span>
            <span class="value expense">¥{{ formatMoney(overallStats.year.current) }}</span>
          </div>
          <div class="gauge-item">
            <span class="label">
              {{ activeTab === BudgetCategory.Expense ? '预算' : '目标' }}
            </span>
            <span class="value">¥{{ formatMoney(overallStats.year.limit) }}</span>
          </div>
        </div>
      </div>
    </div>

    <!-- 月度预算进度 -->
    <div
      v-if="budgets.length > 0"
      class="chart-card"
    >
      <div class="chart-header">
        <div class="chart-title">
          预算进度（月度）
        </div>
        <div class="chart-subtitle">
          预算剩余消耗趋势
        </div>
      </div>
      <div
        ref="burndownChartRef"
        class="chart-body burndown-chart"
      />
    </div>

    <!-- 年度预算进度 -->
    <div
      v-if="budgets.length > 0"
      class="chart-card"
      style="margin-top: 12px"
    >
      <div class="chart-header">
        <div class="chart-title">
          预算进度（年度）
        </div>
        <div class="chart-subtitle">
          本年各预算执行情况
        </div>
      </div>
      <div
        ref="yearBurndownChartRef"
        class="chart-body burndown-chart"
      />
    </div>

    <!-- 偏差分析 -->
    <div
      v-if="budgets.length > 0"
      class="chart-card"
      style="margin-top: 12px"
    >
      <div class="chart-header">
        <div class="chart-title">
          偏差分析
        </div>
        <div class="chart-subtitle">
          预算执行偏差排行
        </div>
      </div>
      <div
        ref="varianceChartRef"
        class="chart-body variance-chart"
        :style="{ height: calculateChartHeight(budgets) + 'px' }"
      />
    </div>

    <!-- 空状态占位 -->
    <div
      v-else-if="budgets.length === 0"
      class="chart-card empty-card"
    >
      <van-empty
        description="暂无预算数据"
        image="search"
      />
    </div>
  </div>

  <!-- 详细描述弹窗 -->
  <PopupContainer
    v-model="showDescriptionPopup"
    :title="activeDescTab === 'month' ? '预算额度/实际详情（月度）' : '预算额度/实际详情（年度）'"
    height="70%"
  >
    <div
      class="rich-html-content"
      style="padding: 16px"
      v-html="activeDescTab === 'month' ? (overallStats.month?.description || '<p style=\'text-align:center;color:var(--van-text-color-3)\'>暂无数据</p>') : (overallStats.year?.description || '<p style=\'text-align:center;color:var(--van-text-color-3)\'>暂无数据</p>')"
    />
  </PopupContainer>
</template>

<script setup>
import { ref, onMounted, watch, nextTick, onUnmounted, computed } from 'vue'
import * as echarts from 'echarts'
import { BudgetCategory, BudgetPeriodType } from '@/constants/enums'
import { getCssVar } from '@/utils/theme'
import PopupContainer from '@/components/PopupContainer.vue'

const props = defineProps({
  overallStats: {
    type: Object,
    required: true
  },
  budgets: {
    type: Array,
    default: () => []
  },
  activeTab: {
    type: [Number, String],
    default: BudgetCategory.Expense
  },
  selectedDate: {
    type: Date,
    default: () => new Date()
  }
})

const monthGaugeRef = ref(null)
const yearGaugeRef = ref(null)
const varianceChartRef = ref(null)
const burndownChartRef = ref(null)
const yearBurndownChartRef = ref(null)

// 弹窗状态
const showDescriptionPopup = ref(false)
const activeDescTab = ref('month')

let monthGaugeChart = null
let yearGaugeChart = null
let varianceChart = null
let burndownChart = null
let yearBurndownChart = null

const formatMoney = (val) => {
  if (Math.abs(val) >= 10000) {
    return (val / 10000).toFixed(1) + 'w'
  }
  return parseFloat(val || 0).toLocaleString(undefined, {
    minimumFractionDigits: 0,
    maximumFractionDigits: 0
  })
}

const updateSingleGauge = (chart, data, isExpense) => {
  if (!chart) { return }

  const rate = parseFloat(data.rate || 0)
  // 展示逻辑：支出显示剩余，收入显示已积累
  let displayRate
  if (isExpense) {
    // 支出：显示剩余容量 (100% - 已消耗%)，随支出增大逐渐消耗；超支时显示超出部分
    displayRate = Math.max(0, 100 - rate)
    // 如果超支(rate > 100)，显示超支部分（例如110% -> 显示10%超支）
    if (rate > 100) {
      displayRate = rate - 100
    }
  } else {
    // 收入：显示已积累 (%)，随收入增多逐渐增多，可以超过100%
    displayRate = rate
  }

  // 颜色逻辑：支出从绿色消耗到红色，收入从红色积累到绿色
  let color
  if (isExpense) {
    // 支出：满格绿色，随消耗逐渐变红 (根据剩余容量)
    if (rate > 100) {
      color = getCssVar('--chart-danger') // 超支显示红色
    } else if (displayRate <= 30) {
      color = getCssVar('--chart-danger') // 红色（剩余很少）
    } else if (displayRate <= 65) {
      color = getCssVar('--chart-warning') // 橙色
    } else {
      color = getCssVar('--chart-success') // 绿色（剩余充足）
    }
  } else {
    // 收入：空红色，随积累逐渐变绿 (根据已积累)
    if (displayRate <= 30) { color = getCssVar('--chart-danger') } // 红色
    else if (displayRate <= 65) { color = getCssVar('--chart-warning') } // 橙色
    else { color = getCssVar('--chart-success') } // 绿色
  }

  const option = {
    series: [
      {
        type: 'gauge',
        startAngle: 180,
        endAngle: 0,
        min: 0,
        max: isExpense && rate > 100 ? 50 : 100, // 超支时显示0-50%范围（实际代表0-150%）
        splitNumber: 5,
        radius: '120%', // 放大一点以适应小卡片
        center: ['50%', '70%'],
        itemStyle: {
          color: color,
          shadowColor: getCssVar('--chart-shadow'),
          shadowBlur: 10,
          shadowOffsetX: 2,
          shadowOffsetY: 2
        },
        progress: {
          show: true,
          roundCap: true,
          width: 12 // 变细一点
        },
        pointer: { show: false },
        axisLine: {
          roundCap: true,
          lineStyle: {
            width: 12,
            color: [[1, getCssVar('--chart-axis')]]
          }
        },
        axisTick: { show: false },
        splitLine: { show: false },
        axisLabel: { show: false },
        detail: {
          valueAnimation: true,
          fontSize: 24, // 字体调小
          offsetCenter: [0, -5],
          color: getCssVar('--van-text-color'),
          formatter: '{value}%',
          fontWeight: 'bold',
          fontFamily: 'DIN Alternate, system-ui',
          show: false
        },
        data: [{ value: displayRate.toFixed(0) }]
      }
    ]
  }

  chart.setOption(option, true)
}

const disposeBudgetCharts = () => {
  varianceChart?.dispose()
  varianceChart = null
  burndownChart?.dispose()
  burndownChart = null
  yearBurndownChart?.dispose()
  yearBurndownChart = null
}

const updateCharts = () => {
  const isExpense = props.activeTab === BudgetCategory.Expense

  // 仪表盘总是存在的
  if (!monthGaugeChart && monthGaugeRef.value) {
    monthGaugeChart = echarts.init(monthGaugeRef.value)
  }
  if (monthGaugeChart) {
    updateSingleGauge(monthGaugeChart, props.overallStats.month, isExpense)
  }

  if (!yearGaugeChart && yearGaugeRef.value) {
    yearGaugeChart = echarts.init(yearGaugeRef.value)
  }
  if (yearGaugeChart) {
    updateSingleGauge(yearGaugeChart, props.overallStats.year, isExpense)
  }

  if (props.budgets.length > 0) {
    // 等待 v-if 相关的 DOM 更新
    nextTick(() => {
      // 偏差分析图
      if (varianceChartRef.value) {
        const existing = echarts.getInstanceByDom(varianceChartRef.value)
        if (existing) {
          varianceChart = existing
        } else {
          varianceChart?.dispose()
          varianceChart = echarts.init(varianceChartRef.value)
        }
        updateVarianceChart(varianceChart, props.budgets)
        varianceChart.resize()
      }

      // 月度燃尽图
      if (burndownChartRef.value) {
        const existing = echarts.getInstanceByDom(burndownChartRef.value)
        if (existing) {
          burndownChart = existing
        } else {
          burndownChart?.dispose()
          burndownChart = echarts.init(burndownChartRef.value)
        }
        updateBurndownChart()
        burndownChart.resize()
      }

      // 年度燃尽图
      if (yearBurndownChartRef.value) {
        const existing = echarts.getInstanceByDom(yearBurndownChartRef.value)
        if (existing) {
          yearBurndownChart = existing
        } else {
          yearBurndownChart?.dispose()
          yearBurndownChart = echarts.init(yearBurndownChartRef.value)
        }
        updateYearBurndownChart()
        yearBurndownChart.resize()
      }
    })
  } else {
    // 预算数据为空，DOM 已移除，清理实例
    disposeBudgetCharts()
  }
}

const updateVarianceChart = (chart, budgets) => {
  if (!chart || !budgets || budgets.length === 0) { return }

  const data = budgets.map(b => {
    const limit = b.limit || 0
    const current = b.current || 0
    const diff = current - limit
    return {
      name: b.name + (b.type === BudgetPeriodType.Year ? ' (年)' : ''),
      value: diff,
      limit: limit,
      current: current,
      type: b.type
    }
  })

  // 先月度再年度，各自按偏差绝对值排序
  const monthlyData = data.filter(item => item.type === BudgetPeriodType.Month)
  const annualData = data.filter(item => item.type === BudgetPeriodType.Year)

  monthlyData.sort((a, b) => Math.abs(b.value) - Math.abs(a.value))
  annualData.sort((a, b) => Math.abs(b.value) - Math.abs(a.value))

  // 确保月度在前，年度在后
  const sortedData = [...annualData,...monthlyData]

  const categories = sortedData.map(item => item.name)
  const values = sortedData.map(item => item.value)
  const maxVal = Math.max(...values.map(v => Math.abs(v))) || 1

  const textColor = getCssVar('--van-text-color')
  const splitLineColor = getCssVar('--chart-split')

  const option = {
    grid: {
      left: '3%',
      right: '8%',
      bottom: '3%',
      top: '3%',
      containLabel: true
    },
    tooltip: {
      trigger: 'axis',
      formatter: (params) => {
        const item = sortedData[params[0].dataIndex]
        let html = `${item.name}<br/>`
        html += `预算: ¥${formatMoney(item.limit)}<br/>`
        html += `实际: ¥${formatMoney(item.current)}<br/>`
        const diffText = item.value > 0 ? `超支: ¥${formatMoney(item.value)}` : `结余: ¥${formatMoney(Math.abs(item.value))}`
        const color = item.value > 0 ? getCssVar('--van-danger-color') : getCssVar('--van-success-color')
        html += `<span style="color:${color};font-weight:bold">${diffText}</span>`
        return html
      }
    },
    xAxis: {
      type: 'value',
      position: 'top',
      axisLine: { show: false },
      axisLabel: { show: false },
      splitLine: {
        show: true,
        lineStyle: {
          type: 'dashed',
          color: splitLineColor
        }
      }
    },
    yAxis: {
      type: 'category',
      axisTick: { show: false },
      axisLine: { show: false },
      data: categories,
      axisLabel: {
        color: textColor,
        width: 60,
        overflow: 'truncate'
      }
    },
    series: [
      {
        name: '偏差',
        type: 'bar',
        stack: 'Total',
        barWidth: 20, // Fixed bar width
        data: values.map((val) => {
          // 如果柱子太短（小于25%），文字显示在外部，否则显示在内部
          const ratio = Math.abs(val) / maxVal
          const isShort = ratio < 0.25
          let position
          let color

          if (val >= 0) {
            position = isShort ? 'right' : 'insideLeft'
          } else {
            position = isShort ? 'left' : 'insideRight'
          }

          // eslint-disable-next-line prefer-const
          color = isShort ? textColor : '#fff'

          return {
            value: val,
            label: {
              position: position,
              color: color
            }
          }
        }),
        label: {
          show: true,
          formatter: (params) => {
            const val = params.value
            return val > 0 ? `+${formatMoney(val)}` : formatMoney(val)
          },
          color: textColor
        },
        itemStyle: {
          borderRadius: 4,
          color: (params) => {
            const val = params.value
            if (props.activeTab === BudgetCategory.Expense) {
              return val > 0 ? getCssVar('--van-danger-color') : getCssVar('--van-success-color')
            } else {
              return val > 0 ? getCssVar('--van-success-color') : getCssVar('--van-danger-color')
            }
          }
        }
      }
    ]
  }

  chart.setOption(option, true)
}

const calculateChartHeight = (budgets) => {
  if (!budgets) { return 100 }
  const dataCount = budgets.length
  const minHeight = 100
  const heightPerItem = 30 // Fixed height per bar item
  const calculatedHeight = Math.max(minHeight, dataCount * heightPerItem)
  return calculatedHeight
}

const updateBurndownChart = () => {
  if (!burndownChart) { return }

  // 使用传入的所选日期作为参考日期
  const refDate = props.selectedDate
  const year = refDate.getFullYear()
  const month = refDate.getMonth()
  const daysInMonth = new Date(year, month + 1, 0).getDate()

  const now = new Date()
  const isCurrentMonth = now.getFullYear() === year && now.getMonth() === month
  const isPastMonth =
    now.getFullYear() > year || (now.getFullYear() === year && now.getMonth() > month)
  // 如果是过去月份，显示完整数据；如果是当前月，显示到今天；如果是将来月，不显示实际数据
  const currentDay = isCurrentMonth ? now.getDate() : isPastMonth ? daysInMonth : 0
  const isExpense = props.activeTab === BudgetCategory.Expense

  // 生成日期和理想燃尽线/积累线
  const dates = []
  const idealBurndown = []
  const actualBurndown = []

  const totalBudget = props.overallStats.month.limit || 0
  const currentExpense = props.overallStats.month.current || 0
  const trend = props.overallStats.month.trend || []

  for (let i = 1; i <= daysInMonth; i++) {
    dates.push(`${i}日`)

    if (isExpense) {
      // 支出：燃尽图（向下走）
      // 理想燃尽：每天均匀消耗
      const idealRemaining = totalBudget * (1 - i / daysInMonth)
      idealBurndown.push(Math.round(idealRemaining))

      // 实际燃尽：根据当前日期显示，允许负值以表示超支
      if (trend.length > 0) {
        // 后端返回了趋势数据
        const dayValue = trend[i - 1]
        if (dayValue !== undefined && dayValue !== null) {
          const actualRemaining = totalBudget - dayValue
          actualBurndown.push(Math.round(actualRemaining))
        } else {
          actualBurndown.push(null)
        }
      } else {
        // 后端没有趋势数据， fallback 到线性估算
        if (i <= currentDay && totalBudget > 0) {
          // 允许显示负值以表示超支
          const actualRemaining = totalBudget - (currentExpense * i / currentDay)
          actualBurndown.push(Math.round(actualRemaining))
        } else {
          actualBurndown.push(null)
        }
      }
    } else {
      // 收入：积累图（向上走）
      // 理想积累：每天均匀积累
      const idealAccumulated = Math.min(totalBudget, totalBudget * (i / daysInMonth))
      idealBurndown.push(Math.round(idealAccumulated))

      // 实际积累：根据当前日期显示
      if (trend.length > 0) {
        const dayValue = trend[i - 1]
        if (dayValue !== undefined && dayValue !== null) {
          actualBurndown.push(Math.round(dayValue))
        } else {
          actualBurndown.push(null)
        }
      } else {
        if (i <= currentDay && totalBudget > 0) {
          const actualAccumulated = Math.min(totalBudget, currentExpense * i / currentDay)
          actualBurndown.push(Math.round(actualAccumulated))
        } else {
          actualBurndown.push(null)
        }
      }
    }
  }

  const splitLineColor = getCssVar('--chart-split')
  const axisLabelColor = getCssVar('--chart-text-muted')

  const idealSeriesName = isExpense ? '理想燃尽' : '理想积累'
  const actualSeriesName = isExpense ? '实际燃尽' : '实际积累'

  const option = {
    grid: {
      left: '3%',
      right: '8%',
      bottom: '3%',
      top: '3%',
      containLabel: true
    },
    xAxis: {
      type: 'category',
      data: dates,
      axisLabel: {
        color: axisLabelColor,
        interval: 'auto',
        rotate: 0
      },
      splitLine: { show: false },
      axisLine: {
        lineStyle: {
          color: splitLineColor
        }
      }
    },
    yAxis: {
      type: 'value',
      axisLabel: {
        color: axisLabelColor,
        formatter: (value) => {
          if (value >= 10000) { return (value / 10000).toFixed(0) + 'w' }
          return value
        }
      },
      splitLine: {
        lineStyle: {
          type: 'dashed',
          color: splitLineColor
        }
      }
    },
    tooltip: {
      trigger: 'axis',
      formatter: (params) => {
        let result = params[0].name + '<br/>'
        params.forEach(param => {
          if (param.value !== null && param.value !== undefined) {
            result += param.marker + param.seriesName + ': ¥' + (param.value >= 10000 ? (param.value / 10000).toFixed(1) + 'w' : param.value) + '<br/>'
          }
        })
        return result
      }
    },
    series: [
      {
        name: idealSeriesName,
        type: 'line',
        data: idealBurndown,
        smooth: false,
        lineStyle: {
          color: getCssVar('--chart-warning'),
          width: 2,
          type: 'dashed'
        },
        itemStyle: {
          color: getCssVar('--chart-warning')
        },
        z: 1
      },
      {
        name: actualSeriesName,
        type: 'line',
        data: actualBurndown,
        smooth: false,
        lineStyle: {
          color: getCssVar('--chart-primary'),
          width: 2
        },
        itemStyle: {
          color: getCssVar('--chart-primary')
        },
        z: 2
      }
    ]
  }

  burndownChart.setOption(option, true)
}

const updateYearBurndownChart = () => {
  if (!yearBurndownChart) { return }

  // 使用参考日期
  const refDate = props.selectedDate
  const year = refDate.getFullYear()
  const refMonth = refDate.getMonth()

  const now = new Date()
  const currentYear = now.getFullYear()
  const currentMonth = now.getMonth()
  const currentDay = now.getDate()
  const daysInCurrentMonth = new Date(currentYear, currentMonth + 1, 0).getDate()
  const isExpense = props.activeTab === BudgetCategory.Expense

  // 生成月份和理想燃尽线/积累线
  const months = []
  const idealBurndown = []
  const actualBurndown = []

  const totalBudget = props.overallStats.year.limit || 0
  const currentExpense = props.overallStats.year.current || 0
  const trend = props.overallStats.year.trend || []

  for (let i = 0; i < 12; i++) {
    months.push(`${i + 1}月`)

    // 计算当前时间进度（基于天数）
    let daysPassedInYear = 0
    let daysInYear = 0

    for (let j = 0; j < i; j++) {
      daysInYear += new Date(year, j + 1, 0).getDate()
    }

    if (year < currentYear || (year === currentYear && i < currentMonth)) {
      // 以前的年/月
      daysPassedInYear = daysInYear + new Date(year, i + 1, 0).getDate()
    } else if (year === currentYear && i === currentMonth) {
      // 当前月
      daysPassedInYear = daysInYear + currentDay
    } else {
      // 未来的年/月
      daysPassedInYear = 0
    }

    const daysInYearTotal = (year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)) ? 366 : 365
    const yearProgress = daysPassedInYear / daysInYearTotal

    if (isExpense) {
      // 支出：燃尽图（向下走）
      // 理想燃尽：每月均匀消耗
      const idealRemaining = totalBudget * (1 - (i + 1) / 12)
      idealBurndown.push(Math.round(idealRemaining))

      // 实际燃尽：根据日期显示，允许负值以表示超支
      if (trend.length > 0) {
        const monthValue = trend[i]
        if (monthValue !== undefined && monthValue !== null) {
          const actualRemaining = totalBudget - monthValue
          actualBurndown.push(Math.round(actualRemaining))
        } else {
          actualBurndown.push(null)
        }
      } else {
        // Fallback: 如果是今年且月份未开始，或者去年，做线性统计
        const isFuture = year > currentYear || (year === currentYear && i > currentMonth)
        if (!isFuture && totalBudget > 0) {
          const actualRemaining = totalBudget - (currentExpense * yearProgress)
          actualBurndown.push(Math.round(actualRemaining))
        } else {
          actualBurndown.push(null)
        }
      }
    } else {
      // 收入：积累图（向上走）
      // 理想积累：每月均匀积累
      const idealAccumulated = Math.min(totalBudget, totalBudget * ((i + 1) / 12))
      idealBurndown.push(Math.round(idealAccumulated))

      // 实际积累：根据参数显示
      if (trend.length > 0) {
        const monthValue = trend[i]
        if (monthValue !== undefined && monthValue !== null) {
          actualBurndown.push(Math.round(monthValue))
        } else {
          actualBurndown.push(null)
        }
      } else {
        const isFuture = year > currentYear || (year === currentYear && i > currentMonth)
        if (!isFuture && totalBudget > 0) {
          const actualAccumulated = Math.min(totalBudget, currentExpense * yearProgress)
          actualBurndown.push(Math.round(actualAccumulated))
        } else {
          actualBurndown.push(null)
        }
      }
    }
  }

  const splitLineColor = getCssVar('--chart-split')
  const axisLabelColor = getCssVar('--chart-text-muted')

  const idealSeriesName = isExpense ? '理想支出' : '理想收入'
  const actualSeriesName = isExpense ? '实际支出' : '实际收入'

  const option = {
    grid: {
      left: '3%',
      right: '8%',
      bottom: '3%',
      top: '3%',
      containLabel: true
    },
    xAxis: {
      type: 'category',
      data: months,
      axisLabel: {
        color: axisLabelColor
      },
      splitLine: { show: false },
      axisLine: {
        lineStyle: {
          color: splitLineColor
        }
      }
    },
    yAxis: {
      type: 'value',
      axisLabel: {
        color: axisLabelColor,
        formatter: (value) => {
          if (value >= 10000) { return (value / 10000).toFixed(0) + 'w' }
          return value
        }
      },
      splitLine: {
        lineStyle: {
          type: 'dashed',
          color: splitLineColor
        }
      }
    },
    tooltip: {
      trigger: 'axis',
      formatter: (params) => {
        let result = params[0].name + '<br/>'
        params.forEach(param => {
          if (param.value !== null && param.value !== undefined) {
            result += param.marker + param.seriesName + ': ¥' + (param.value >= 10000 ? (param.value / 10000).toFixed(1) + 'w' : param.value) + '<br/>'
          }
        })
        return result
      }
    },
    series: [
      {
        name: idealSeriesName,
        type: 'line',
        data: idealBurndown,
        smooth: false,
        lineStyle: {
          color: getCssVar('--chart-warning'),
          width: 2,
          type: 'dashed'
        },
        itemStyle: {
          color: getCssVar('--chart-warning')
        },
        z: 1
      },
      {
        name: actualSeriesName,
        type: 'line',
        data: actualBurndown,
        smooth: false,
        lineStyle: {
          color: getCssVar('--chart-primary'),
          width: 2
        },
        itemStyle: {
          color: getCssVar('--chart-primary')
        },
        z: 2
      }
    ]
  }

  yearBurndownChart.setOption(option, true)
}

watch(() => props.overallStats, () => nextTick(updateCharts), { deep: true })
watch(() => props.budgets, () => {
  nextTick(() => {
    updateCharts()
  })
}, { deep: true })

watch(() => props.selectedDate, () => {
  nextTick(() => {
    updateCharts()
  })
})

watch(() => props.activeTab, () => {
  nextTick(() => {
    updateCharts()
    // 切换标签后延迟 resize，确保 DOM 已更新
    setTimeout(() => {
      burndownChart?.resize()
      yearBurndownChart?.resize()
      varianceChart?.resize()
    }, 100)
  })
})

const handleResize = () => {
  monthGaugeChart?.resize()
  yearGaugeChart?.resize()
  varianceChart?.resize()
  burndownChart?.resize()
  yearBurndownChart?.resize()
}

onMounted(() => {
  nextTick(() => {
    updateCharts()
    window.addEventListener('resize', handleResize)
  })
})

onUnmounted(() => {
  window.removeEventListener('resize', handleResize)
  monthGaugeChart?.dispose()
  monthGaugeChart = null
  yearGaugeChart?.dispose()
  yearGaugeChart = null
  disposeBudgetCharts()
})
</script>

<style scoped>
.chart-analysis-container {
  padding: 12px;
  padding-bottom: 80px;
}

.gauges-row {
  display: flex;
  gap: 12px;
  margin-bottom: 12px;
}

.chart-card {
  background: var(--van-background-2);
  border-radius: 12px;
  padding: 16px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}

.gauge-card {
  flex: 1;
  min-width: 0;
  /* 防止 flex 子项溢出 */
  padding: 12px;
  /* 减小内边距 */
}

.gauge-wrapper {
  position: relative;
  width: 100%;
  height: 120px;
}

.gauge-text-overlay {
  position: absolute;
  bottom: 20%;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  z-index: 10;
}

.remaining-value {
  font-size: 24px;
  font-weight: bold;
  font-family: DIN Alternate, system-ui;
  color: var(--van-text-color);
  line-height: 1;
  transform-origin: center;
}

.remaining-label {
  font-size: 10px;
  color: var(--van-text-color-2);
  margin-top: 4px;
  font-family: system-ui;
  transform-origin: center;
}

.chart-header {
  margin-bottom: 12px;
}

.chart-title {
  font-size: 14px;
  /* 调小标题 */
  font-weight: 600;
  color: var(--van-text-color);
  margin-bottom: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chart-subtitle {
  font-size: 10px;
  color: var(--van-text-color-2);
}

.chart-body {
  width: 100%;
}

.gauge-chart {
  height: 120px;
  /* 调小高度 */
}

.variance-chart {
  min-height: 200px;
}

.burndown-chart {
  height: 190px;
}

.gauge-footer {
  display: flex;
  justify-content: space-around;
  /* 分散对齐 */
  align-items: center;
  margin-top: -20px;
  position: relative;
  z-index: 10;
}

.gauge-item {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.gauge-item .label {
  font-size: 10px;
  color: var(--van-text-color-2);
  transform: scale(0.9);
  /* 视觉上更小 */
}

.gauge-item .value {
  font-size: 12px;
  font-weight: 600;
  font-family: DIN Alternate, system-ui;
  color: var(--van-text-color);
}

.gauge-item .value.expense {
  color: var(--van-primary-color);
}

/* expand styles removed as they are no longer used */
</style>
