<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
import * as echarts from 'echarts'
import type { Candle } from '@/api/candles'
import { useThemeStore } from '@/stores/theme'
import { useMobile } from '@/composables/useMobile'

const props = defineProps<{ data: Candle[]; scores?: { trade_date: string; composite: number }[] }>()
const theme = useThemeStore()
const { isMobile } = useMobile()

const containerRef = ref<HTMLDivElement | null>(null)
let chart: echarts.ECharts | null = null

function ensureChart() {
  if (!containerRef.value) return
  if (chart) {
    chart.dispose()
    chart = null
  }
  chart = echarts.init(containerRef.value, theme.isDark ? 'dark' : undefined)
}

function render() {
  if (!chart) return
  const dates = props.data.map((c) => c.trade_date)
  // ECharts K 线顺序: [open, close, low, high]
  const ohlc = props.data.map((c) => [c.open, c.close, c.low, c.high])
  const oi = props.data.map((c) => c.oi)

  const scoreMap = new Map((props.scores || []).map((s) => [s.trade_date, s.composite]))
  const compositeData = props.data.map((c) => scoreMap.get(c.trade_date) ?? null)

  const hasScores = props.scores && props.scores.length > 0
  const legendData = hasScores ? ['K 线', '持仓量', '综合分'] : ['K 线', '持仓量']
  const xAxisIndices = hasScores ? [0, 1, 2] : [0, 1]
  const grids: any[] = [
    { left: isMobile.value ? 48 : 60, right: isMobile.value ? 12 : 40, top: 40, height: hasScores ? '52%' : '60%' },
    { left: isMobile.value ? 48 : 60, right: isMobile.value ? 12 : 40, top: hasScores ? '72%' : '78%', height: hasScores ? '14%' : '18%' },
  ]
  const xAxes: any[] = [
    { type: 'category', data: dates, scale: true, boundaryGap: false },
    { type: 'category', gridIndex: 1, data: dates, scale: true, boundaryGap: false, axisLabel: { show: false } },
  ]
  const yAxes: any[] = [
    { scale: true, splitArea: { show: true }, name: '价格', nameLocation: 'end', nameTextStyle: { fontSize: 11 } },
    { gridIndex: 1, scale: true, splitNumber: 3, name: '持仓', nameLocation: 'end', nameTextStyle: { fontSize: 11 } },
  ]
  const series: any[] = [
    {
      name: 'K 线',
      type: 'candlestick',
      data: ohlc,
      itemStyle: {
        color: '#ec3a3a',
        color0: '#26a69a',
        borderColor: '#ec3a3a',
        borderColor0: '#26a69a',
      },
    },
    {
      name: '持仓量',
      type: 'line',
      xAxisIndex: 1,
      yAxisIndex: 1,
      data: oi,
      smooth: true,
      showSymbol: false,
      lineStyle: { color: '#5470c6' },
      areaStyle: { opacity: 0.15, color: '#5470c6' },
    },
  ]

  if (hasScores) {
    grids.push({ left: isMobile.value ? 48 : 60, right: isMobile.value ? 12 : 40, top: '88%', height: '10%' })
    xAxes.push({ type: 'category', gridIndex: 2, data: dates, scale: true, boundaryGap: false, axisLabel: { show: false } })
    yAxes.push({ gridIndex: 2, min: 0, max: 100, splitNumber: 2, name: '综合分', nameLocation: 'end', nameTextStyle: { fontSize: 11 } })
    series.push({
      name: '综合分',
      type: 'bar',
      xAxisIndex: 2,
      yAxisIndex: 2,
      data: compositeData,
      barWidth: '60%',
      itemStyle: {
        color: (params: any) => {
          const val = params.value as number | null
          if (val == null) return 'transparent'
          if (val >= 80) return '#ec3a3a'
          if (val >= 50) return '#f89898'
          if (val >= 40) return '#89d6c7'
          return '#26a69a'
        },
      },
    })
  }

  chart.setOption(
    {
      backgroundColor: 'transparent',
      tooltip: {
        trigger: 'axis',
        axisPointer: { type: 'cross' },
        formatter: (params: any) => {
          if (!Array.isArray(params)) return ''
          const date = params[0]?.axisValue || ''
          let html = `<strong>${date}</strong><br/>`
          for (const p of params) {
            if (p.seriesName === 'K 线') {
              const ohlc = p.data as number[]
              const labels = ['开盘', '收盘', '最低', '最高']
              html += labels.map((n, i) => `${p.marker} ${n}: ${ohlc[i] ?? '-'}`).join('<br/>') + '<br/>'
              continue
            }
            let name = p.seriesName
            let val: string
            if (name === '持仓量') val = (p.data as number)?.toLocaleString() ?? '-'
            else if (name === '综合分') val = (p.data as number)?.toFixed(1) ?? '-'
            else val = p.data ?? '-'
            html += `${p.marker} ${name}: ${val}<br/>`
          }
          return html
        },
      },
      legend: { data: legendData, top: 0 },
      grid: grids,
      xAxis: xAxes,
      yAxis: yAxes,
      dataZoom: [
        { type: 'inside', xAxisIndex: xAxisIndices },
        { type: 'slider', xAxisIndex: xAxisIndices, height: 18, bottom: 6 },
      ],
      series,
    },
    true,
  )
}

function resize() {
  chart?.resize()
}

onMounted(() => {
  ensureChart()
  render()
  window.addEventListener('resize', resize)
})

onBeforeUnmount(() => {
  window.removeEventListener('resize', resize)
  chart?.dispose()
  chart = null
})

watch(() => props.data, render, { deep: true })
watch(
  () => theme.isDark,
  () => {
    ensureChart()
    render()
  },
)
watch(isMobile, () => {
  ensureChart()
  render()
})
</script>

<template>
  <div ref="containerRef" class="chart"></div>
</template>

<style scoped>
.chart {
  width: 100%;
  height: 560px;
}
@media (max-width: 768px) {
  .chart {
    height: 420px;
  }
}
</style>
