<template>
  <div :style="boxStyle" class="w-full h-full box-border overflow-hidden relative">
    <svg
      class="absolute left-0 top-0 w-full h-full"
      :viewBox="`0 0 ${width} ${height}`"
      xmlns="http://www.w3.org/2000/svg"
    >
      <!-- 元素渲染 -->
      <template v-for="(el, index) in elements || []" :key="index">
        <!-- 矩形 -->
        <rect
          v-if="el.type === 'rect'"
          :x="el.props.x"
          :y="el.props.y"
          :width="el.props.width"
          :height="el.props.height"
          :fill="el.props.background_color"
          :stroke="el.props.border?.color"
          :stroke-width="el.props.border?.width"
          :rx="el.props.border?.radius"
          :ry="el.props.border?.radius"
        />

        <!-- 文本 -->
        <text
          v-else-if="el.type === 'text'"
          :x="el.props.x"
          :y="el.props.y"
          :fill="el.props.font_color"
          :font-size="el.props.font_size"
          :text-decoration="textDecorMap[el.props.text_decor] || 'none'"
          :style="getCanvasTextStyle(el.props)"
          dominant-baseline="hanging"
        >
          {{ getCanvasText(el.props.text) }}
        </text>

        <!-- 圆弧 -->
        <path
          v-else-if="el.type === 'arc'"
          :d="getArcPath(el.props)"
          :stroke="el.props.color"
          :stroke-width="el.props.width"
          fill="none"
          stroke-linecap="round"
        />

        <!-- 直线（折线） -->
        <polyline
          v-else-if="el.type === 'line'"
          v-show="(el.props.points || []).length > 1"
          :points="getLinePoints(el.props.points)"
          :stroke="el.props.color"
          :stroke-width="el.props.width"
          :stroke-linecap="el.props.round ? 'round' : 'butt'"
          fill="none"
        />

        <!-- 三角形 -->
        <polygon
          v-else-if="el.type === 'triangle'"
          v-show="(el.props.points || []).length >= 3"
          :points="getLinePoints((el.props.points || []).slice(0, 3))"
          :fill="el.props.background_color"
        />
      </template>
    </svg>

    <!-- 图片使用 img 绝对定位到画布上，方便加载本地资源 -->
    <template v-for="(el, index) in imageElements" :key="`img-${index}`">
      <img
        v-if="el.src"
        class="absolute"
        :style="{
          left: `${el.props.x}px`,
          top: `${el.props.y}px`,
          width: `${el.props.width}px`,
          height: `${el.props.height}px`,
          opacity: el.props.alpha / 255
        }"
        :src="el.src"
      />
    </template>
  </div>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { useProjectStore } from '@/store/modules/project'
import { useLanguage } from '../hooks/useLanguage'

type Point = { x: number; y: number }

type RectProps = {
  x: number
  y: number
  width: number
  height: number
  background_color: string
  border: {
    color: string
    width: number
    radius: number
  }
}

type TextProps = {
  x: number
  y: number
  width: number
  font_color: string
  font_size: number
  font_family: string
  text_decor: string
  text: string
}

type ImageProps = {
  x: number
  y: number
  width: number
  height: number
  image: string
  alpha: number
  recolor: string
}

type ArcProps = {
  x: number
  y: number
  start_angle: number
  end_angle: number
  color: string
  width: number
  radius: number
}

type LineProps = {
  color: string
  width: number
  round: boolean
  points: Point[]
}

type TriangleProps = {
  background_color: string
  points: Point[]
}

type CanvasElement =
  | { type: 'rect'; props: RectProps }
  | { type: 'text'; props: TextProps }
  | { type: 'image'; props: ImageProps }
  | { type: 'arc'; props: ArcProps }
  | { type: 'line'; props: LineProps }
  | { type: 'triangle'; props: TriangleProps }

const props = defineProps<{
  width: number
  height: number
  styles: any
  state?: string
  part?: string
  background_color: string
  elements: CanvasElement[]
}>()

const projectStore = useProjectStore()
const { resolveText, getResolvedFontStyle } = useLanguage()

const boxStyle = computed(() => {
  return {
    width: `${props.width}px`,
    height: `${props.height}px`,
    backgroundColor: props.background_color
  }
})

// 文本装饰映射
const textDecorMap: Record<string, string> = {
  LV_TEXT_DECOR_NONE: 'none',
  LV_TEXT_DECOR_UNDERLINE: 'underline',
  LV_TEXT_DECOR_STRIKETHROUGH: 'line-through',
  'LV_TEXT_DECOR_UNDERLINE | LV_TEXT_DECOR_STRIKETHROUGH': 'underline line-through'
}

// 计算图片元素及其本地路径
const imageElements = computed(() => {
  return (props.elements || [])
    .filter((el): el is { type: 'image'; props: ImageProps } => el.type === 'image')
    .map((el) => {
      let src = ''
      const id = el.props.image
      const project = projectStore.project
      if (id && project) {
        const imgRes = project.resources.images.find((img) => img.id === id)
        if (imgRes) {
          src = `local:///${(projectStore.projectPath + imgRes.path).replaceAll('\\', '/')}`
        }
      }
      return { ...el, src }
    })
})

const getCanvasText = (text: string) => resolveText(text).text

const getCanvasTextStyle = (textProps: TextProps) => {
  const resolvedStyle = getResolvedFontStyle(textProps.text)
  if (!resolvedStyle.fontSize && textProps.font_size) {
    resolvedStyle.fontSize = `${textProps.font_size}px`
  }

  if (
    !resolvedStyle.fontFamily &&
    textProps.font_family &&
    textProps.font_family !== 'montserratMedium'
  ) {
    const font = projectStore.project?.resources.fonts.find(
      (item) => item.id === textProps.font_family
    )
    if (font?.fileName) {
      resolvedStyle.fontFamily = `'${font.fileName}'`
    }
  }

  return resolvedStyle
}

// 直线/多边形 points 字符串
const getLinePoints = (points: Point[] = []) => {
  return points.map((p) => `${p.x},${p.y}`).join(' ')
}

// 极坐标转直角坐标
const polarToCartesian = (
  centerX: number,
  centerY: number,
  radius: number,
  angleInDegrees: number
) => {
  const radians = (angleInDegrees * Math.PI) / 180.0
  return {
    x: centerX + radius * Math.cos(radians),
    y: centerY + radius * Math.sin(radians)
  }
}

// 生成圆弧路径（始终顺时针）
const describeArc = (
  x: number,
  y: number,
  radius: number,
  startAngle: number,
  endAngle: number
) => {
  // 归一化角度到 [0, 360)
  const s = ((startAngle % 360) + 360) % 360
  const e = ((endAngle % 360) + 360) % 360

  let clockwiseSpan = (e - s + 360) % 360
  // 0 或 360 视作整圆，这里用 359.999° 避免 SVG 报错
  if (clockwiseSpan === 0) clockwiseSpan = 359.999

  const start = polarToCartesian(x, y, radius, s)
  const end = polarToCartesian(x, y, radius, s + clockwiseSpan)

  const largeArcFlag = clockwiseSpan > 180 ? '1' : '0'
  const sweepFlag = '1'
  return [
    'M',
    start.x,
    start.y,
    'A',
    radius,
    radius,
    0,
    largeArcFlag,
    sweepFlag,
    end.x,
    end.y
  ].join(' ')
}

const getArcPath = (p: ArcProps) => {
  const cx = Number.isFinite(p.x) ? p.x : 0
  const cy = Number.isFinite(p.y) ? p.y : 0
  const radius = Number(p.radius)
  const start = Number(p.start_angle)
  const end = Number(p.end_angle)

  if (!Number.isFinite(radius) || radius <= 0) return ''
  if (!Number.isFinite(start) || !Number.isFinite(end)) return ''

  return describeArc(cx, cy, radius, start, end)
}
</script>

<style scoped></style>
