<template>
  <view class="chart-container" :style="{ height: height + 'px' }">
    <canvas
      :id="canvasId"
      :canvas-id="canvasId"
      class="w-full h-full"
      @touchstart="touchStart"
      @touchmove="touchMove"
    />
  </view>
</template>

<script setup lang="ts">
import { ref, onMounted, watch, computed, getCurrentInstance } from 'vue'

interface Props {
  type: 'bar' | 'line' | 'pie' | 'ring'
  data: { label: string; value: number; color?: string }[]
  height?: number
  canvasId?: string
  title?: string
}

const props = withDefaults(defineProps<Props>(), {
  height: 200,
  canvasId: '',
  title: '',
})

const colors = ['#368f6f', '#4f8ef7', '#ff9500', '#8e8e93', '#5856d6', '#ff2d55', '#5ac8fa', '#af52de']

const canvasId = computed(() => props.canvasId || `chart-canvas-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`)

let ctx: UniApp.CanvasContext | null = null

onMounted(() => {
  drawChart()
})

watch(() => props.data, () => {
  drawChart()
}, { deep: true })

function drawChart() {
  const instance = getCurrentInstance()
  if (!instance) return

  const query = uni.createSelectorQuery().in(instance.proxy)
  query.select('.chart-container').boundingClientRect((rect: any) => {
    const windowWidth = uni.getSystemInfoSync().windowWidth
    const pageMaxWidth = 430
    const rectWidth = rect ? rect.width : windowWidth - 64
    const cssWidth = Math.min(rectWidth, pageMaxWidth - 64, windowWidth - 64)
    const cssHeight = props.height

    ctx = uni.createCanvasContext(canvasId.value)
    if (!ctx) return

    ctx.clearRect(0, 0, cssWidth, cssHeight)

    if (!props.data || props.data.length === 0) {
      drawEmpty(cssWidth, cssHeight)
      return
    }

    if (props.type === 'pie' || props.type === 'ring') {
      drawPie(cssWidth, cssHeight)
    } else if (props.type === 'bar') {
      drawBar(cssWidth, cssHeight)
    } else if (props.type === 'line') {
      drawLine(cssWidth, cssHeight)
    }

    ctx.draw()
  })
  query.exec()
}

function drawEmpty(width: number, height: number) {
  if (!ctx) return
  ctx.setFontSize(14)
  ctx.setFillStyle('#9ca3af')
  ctx.setTextAlign('center')
  ctx.fillText('暂无数据', width / 2, height / 2)
  ctx.draw()
}

function drawPie(width: number, height: number) {
  if (!ctx) return
  const total = props.data.reduce((sum, item) => sum + item.value, 0)
  const isRing = props.type === 'ring'
  const padding = 16
  const legendHeight = 28
  const chartHeight = height - legendHeight
  const centerX = width / 2
  const centerY = chartHeight / 2
  const radius = Math.min(centerX, centerY) - padding

  let startAngle = -Math.PI / 2

  props.data.forEach((item, index) => {
    const angle = total === 0 ? 0 : (item.value / total) * Math.PI * 2
    const endAngle = startAngle + angle
    const color = item.color || colors[index % colors.length]

    ctx!.beginPath()
    ctx!.moveTo(centerX, centerY)
    ctx!.arc(centerX, centerY, radius, startAngle, endAngle)
    ctx!.closePath()
    ctx!.setFillStyle(color)
    ctx!.fill()

    startAngle = endAngle
  })

  if (isRing) {
    ctx!.beginPath()
    ctx!.arc(centerX, centerY, radius * 0.55, 0, Math.PI * 2)
    ctx!.setFillStyle('rgba(255, 255, 255, 0.85)')
    ctx!.fill()

    ctx!.setFontSize(12)
    ctx!.setFillStyle('#6b7280')
    ctx!.setTextAlign('center')
    ctx!.fillText('总计', centerX, centerY - 6)

    ctx!.setFontSize(18)
    ctx!.setFillStyle('#1f2937')
    ctx!.setTextAlign('center')
    ctx!.fillText(String(total), centerX, centerY + 16)
  }

  // 图例
  drawLegend(width, height - legendHeight + 10)
}

function drawLegend(width: number, y: number) {
  if (!ctx) return
  const total = props.data.reduce((sum, item) => sum + item.value, 0)
  const itemWidth = width / props.data.length

  props.data.forEach((item, index) => {
    const color = item.color || colors[index % colors.length]
    const x = index * itemWidth + itemWidth / 2

    ctx!.setFillStyle(color)
    ctx!.fillRect(x - 28, y, 8, 8)

    ctx!.setFontSize(10)
    ctx!.setFillStyle('#6b7280')
    ctx!.setTextAlign('left')
    ctx!.fillText(item.label, x - 16, y + 8)

    ctx!.setFontSize(10)
    ctx!.setFillStyle('#1f2937')
    ctx!.fillText(String(item.value), x + 12, y + 8)
  })
}

function drawBar(width: number, height: number) {
  if (!ctx) return
  const padding = { top: 24, right: 16, bottom: 36, left: 40 }
  const chartHeight = height - padding.top - padding.bottom
  const chartWidth = width - padding.left - padding.right
  const maxValue = Math.max(...props.data.map(d => d.value))
  const safeMax = maxValue <= 0 ? 1 : maxValue * 1.1
  const barWidth = (chartWidth / props.data.length) * 0.55
  const gap = (chartWidth / props.data.length) * 0.45

  // 网格线
  ctx.setStrokeStyle('rgba(164, 216, 152, 0.25)')
  ctx.setLineWidth(1)
  for (let i = 0; i <= 4; i++) {
    const y = padding.top + (chartHeight / 4) * i
    ctx.beginPath()
    ctx.moveTo(padding.left, y)
    ctx.lineTo(width - padding.right, y)
    ctx.stroke()
  }

  // 坐标轴
  ctx.setStrokeStyle('#d1d5db')
  ctx.beginPath()
  ctx.moveTo(padding.left, padding.top)
  ctx.lineTo(padding.left, height - padding.bottom)
  ctx.lineTo(width - padding.right, height - padding.bottom)
  ctx.stroke()

  // Y 轴刻度
  ctx.setFontSize(10)
  ctx.setFillStyle('#9ca3af')
  ctx.setTextAlign('right')
  for (let i = 0; i <= 4; i++) {
    const value = Math.round((safeMax / 4) * (4 - i))
    const y = padding.top + (chartHeight / 4) * i + 4
    ctx.fillText(String(value), padding.left - 6, y)
  }

  // 柱状图
  props.data.forEach((item, index) => {
    const x = padding.left + gap / 2 + index * (barWidth + gap)
    const barHeight = (item.value / safeMax) * chartHeight
    const y = height - padding.bottom - barHeight
    const color = item.color || colors[index % colors.length]

    ctx!.setFillStyle(color)
    ctx!.fillRect(x, y, barWidth, barHeight)

    // 圆角顶部
    ctx!.beginPath()
    ctx!.arc(x + barWidth / 2, y, barWidth / 2, Math.PI, 0)
    ctx!.setFillStyle(color)
    ctx!.fill()

    // 数值
    if (item.value > 0) {
      ctx!.setFontSize(10)
      ctx!.setFillStyle('#1f2937')
      ctx!.setTextAlign('center')
      ctx!.fillText(String(item.value), x + barWidth / 2, y - 6)
    }

    // 标签
    ctx!.setFontSize(10)
    ctx!.setFillStyle('#6b7280')
    ctx!.setTextAlign('center')
    ctx!.fillText(item.label, x + barWidth / 2, height - padding.bottom + 14)
  })
}

function drawLine(width: number, height: number) {
  if (!ctx) return
  const padding = { top: 24, right: 16, bottom: 36, left: 40 }
  const chartHeight = height - padding.top - padding.bottom
  const chartWidth = width - padding.left - padding.right
  const maxValue = Math.max(...props.data.map(d => d.value))
  const allZero = maxValue <= 0
  const safeMax = allZero ? 1 : maxValue * 1.1
  const pointGap = props.data.length > 1 ? chartWidth / (props.data.length - 1) : chartWidth / 2

  // 网格线
  ctx.setStrokeStyle('rgba(164, 216, 152, 0.25)')
  ctx.setLineWidth(1)
  for (let i = 0; i <= 4; i++) {
    const y = padding.top + (chartHeight / 4) * i
    ctx.beginPath()
    ctx.moveTo(padding.left, y)
    ctx.lineTo(width - padding.right, y)
    ctx.stroke()
  }

  // 坐标轴
  ctx.setStrokeStyle('#d1d5db')
  ctx.beginPath()
  ctx.moveTo(padding.left, padding.top)
  ctx.lineTo(padding.left, height - padding.bottom)
  ctx.lineTo(width - padding.right, height - padding.bottom)
  ctx.stroke()

  // Y 轴刻度
  ctx.setFontSize(10)
  ctx.setFillStyle('#9ca3af')
  ctx.setTextAlign('right')
  for (let i = 0; i <= 4; i++) {
    const value = Math.round((safeMax / 4) * (4 - i))
    const y = padding.top + (chartHeight / 4) * i + 4
    ctx.fillText(String(value), padding.left - 6, y)
  }

  const points: { x: number; y: number }[] = []
  props.data.forEach((item, index) => {
    const x = padding.left + index * pointGap
    const y = height - padding.bottom - (item.value / safeMax) * chartHeight
    points.push({ x, y })
  })

  if (allZero) {
    ctx.setFontSize(12)
    ctx.setFillStyle('#9ca3af')
    ctx.setTextAlign('center')
    ctx.fillText('暂无数据', width / 2, height / 2)
  } else {
    // 填充面积
    ctx.beginPath()
    ctx.moveTo(points[0].x, height - padding.bottom)
    points.forEach((point) => {
      ctx!.lineTo(point.x, point.y)
    })
    ctx.lineTo(points[points.length - 1].x, height - padding.bottom)
    ctx.closePath()
    ctx.setFillStyle('rgba(54, 143, 111, 0.12)')
    ctx.fill()

    // 绘制线条
    ctx.setStrokeStyle('#368f6f')
    ctx.setLineWidth(2)
    ctx.beginPath()
    points.forEach((point, index) => {
      if (index === 0) {
        ctx!.moveTo(point.x, point.y)
      } else {
        ctx!.lineTo(point.x, point.y)
      }
    })
    ctx.stroke()

    // 数据点和数值
    points.forEach((point, index) => {
      ctx!.beginPath()
      ctx!.arc(point.x, point.y, 4, 0, Math.PI * 2)
      ctx!.setFillStyle('#ffffff')
      ctx!.fill()

      ctx!.beginPath()
      ctx!.arc(point.x, point.y, 4, 0, Math.PI * 2)
      ctx!.setStrokeStyle('#368f6f')
      ctx!.setLineWidth(2)
      ctx!.stroke()

      ctx!.setFontSize(10)
      ctx!.setFillStyle('#1f2937')
      ctx!.setTextAlign('center')
      ctx!.fillText(String(props.data[index].value), point.x, point.y - 10)
    })
  }

  // X 轴标签
  points.forEach((point, index) => {
    ctx!.setFontSize(10)
    ctx!.setFillStyle('#6b7280')
    ctx!.setTextAlign('center')
    ctx!.fillText(props.data[index].label, point.x, height - padding.bottom + 14)
  })
}

// 触摸事件处理
let touchStartX = 0
function touchStart(e: any) {
  touchStartX = e.touches[0].x
}

function touchMove(e: any) {
  // 可以添加滑动交互
}
</script>

<style scoped>
.chart-container {
  width: 100%;
}
</style>
