<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 } 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: 'chart-canvas',
  title: '',
})

const colors = ['#4f8ef7', '#34c759', '#ff9500', '#ff3b30', '#5856d6', '#ff2d55', '#5ac8fa', '#af52de']

let ctx: UniApp.CanvasContext | null = null

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

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

function drawChart() {
  ctx = uni.createCanvasContext(props.canvasId)
  if (!ctx) return

  const { windowWidth } = uni.getSystemInfoSync()
  const canvasWidth = windowWidth - 32 // 减去padding
  const canvasHeight = props.height

  ctx.clearRect(0, 0, canvasWidth, canvasHeight)

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

  ctx.draw()
}

function drawPie(width: number, height: number) {
  if (!ctx) return
  const total = props.data.reduce((sum, item) => sum + item.value, 0)
  let startAngle = -Math.PI / 2
  const centerX = width / 2
  const centerY = height / 2
  const radius = Math.min(centerX, centerY) - 40

  props.data.forEach((item, index) => {
    const angle = (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()

    // 标签
    const midAngle = startAngle + angle / 2
    const labelX = centerX + Math.cos(midAngle) * (radius + 15)
    const labelY = centerY + Math.sin(midAngle) * (radius + 15)
    ctx!.setFontSize(10)
    ctx!.setFillStyle('#666')
    ctx!.fillText(`${item.label}`, labelX - 15, labelY)
    ctx!.fillText(`${item.value}`, labelX - 5, labelY + 12)

    startAngle = endAngle
  })

  // 如果是 ring 类型，绘制中心圆
  if (props.type === 'ring') {
    ctx!.beginPath()
    ctx!.arc(centerX, centerY, radius * 0.6, 0, Math.PI * 2)
    ctx!.setFillStyle('#fff')
    ctx!.fill()
    ctx!.setFontSize(14)
    ctx!.setFillStyle('#333')
    ctx!.setTextAlign('center')
    ctx!.fillText('总计', centerX, centerY - 5)
    ctx!.fillText(String(total), centerX, centerY + 15)
  }
}

function drawBar(width: number, height: number) {
  if (!ctx) return
  const padding = 30
  const chartHeight = height - padding * 2
  const chartWidth = width - padding * 2
  const maxValue = Math.max(...props.data.map(d => d.value))
  const barWidth = (chartWidth / props.data.length) * 0.6
  const gap = (chartWidth / props.data.length) * 0.4

  // 绘制坐标轴
  ctx.setStrokeStyle('#e0e0e0')
  ctx.beginPath()
  ctx.moveTo(padding, padding)
  ctx.lineTo(padding, height - padding)
  ctx.lineTo(width - padding, height - padding)
  ctx.stroke()

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

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

    // 数值
    ctx!.setFontSize(10)
    ctx!.setFillStyle('#333')
    ctx!.fillText(String(item.value), x + barWidth / 2 - 5, y - 5)

    // 标签
    ctx!.setFontSize(10)
    ctx!.setFillStyle('#666')
    ctx!.fillText(item.label, x, height - padding + 15)
  })
}

function drawLine(width: number, height: number) {
  if (!ctx) return
  const padding = 30
  const chartHeight = height - padding * 2
  const chartWidth = width - padding * 2
  const maxValue = Math.max(...props.data.map(d => d.value))
  const pointGap = chartWidth / (props.data.length - 1)

  // 绘制坐标轴
  ctx.setStrokeStyle('#e0e0e0')
  ctx.beginPath()
  ctx.moveTo(padding, padding)
  ctx.lineTo(padding, height - padding)
  ctx.lineTo(width - padding, height - padding)
  ctx.stroke()

  // 绘制线条
  ctx.setStrokeStyle('#4f8ef7')
  ctx.setLineWidth(2)
  ctx.beginPath()

  const points: { x: number; y: number }[] = []
  props.data.forEach((item, index) => {
    const x = padding + index * pointGap
    const y = height - padding - (item.value / maxValue) * chartHeight
    points.push({ x, y })
    if (index === 0) {
      ctx!.moveTo(x, y)
    } else {
      ctx!.lineTo(x, y)
    }
  })
  ctx.stroke()

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

    ctx!.setFontSize(10)
    ctx!.setFillStyle('#333')
    ctx!.fillText(String(props.data[index].value), point.x - 5, point.y - 10)
    ctx!.setFillStyle('#666')
    ctx!.fillText(props.data[index].label, point.x - 10, height - padding + 15)
  })
}

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

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