<template>
  <div
    :style="{
      ...styleMap?.mainStyle
    }"
    class="relative w-full h-full box-border overflow-hidden relative"
  >
    <ImageBg
      v-if="styleMap?.mainStyle?.imageSrc"
      :src="styleMap?.mainStyle?.imageSrc"
      :imageStyle="styleMap?.mainStyle?.imageStyle"
    />

    <div
      class="absolute inset-0 w-full h-full"
      :style="{ transform: `rotate(${props.rotate}deg)` }"
    >
      <svg
        :viewBox="`0 0 ${width} ${height}`"
        preserveAspectRatio="xMidYMid meet"
        class="w-full h-full block"
        xmlns="http://www.w3.org/2000/svg"
      >
        <defs>
          <!-- 背景条图片 pattern：保持图像原始尺寸，居中显示 -->
          <pattern
            v-if="styleMap?.mainStyle?.curve?.imageSrc"
            :id="`${arcId}-bg-pattern`"
            patternUnits="userSpaceOnUse"
            :width="width"
            :height="height"
            x="0"
            y="0"
          >
            <image :href="styleMap.mainStyle.curve.imageSrc" transform="translate(-50%, -50%)" />
          </pattern>
          <!-- 进度值条图片 pattern：保持图像原始尺寸，居中显示 -->
          <pattern
            v-if="styleMap?.indicatorStyle?.curve?.imageSrc"
            :id="`${arcId}-indicator-pattern`"
            patternUnits="userSpaceOnUse"
            :width="width"
            :height="height"
            x="0"
            y="0"
          >
            <image
              :href="styleMap.indicatorStyle.curve.imageSrc"
              transform="translate(-50%, -50%)"
            />
          </pattern>
        </defs>
        <!-- 背景条：绘制完整的起始到结束角度 -->
        <path
          :d="bgPath"
          fill="none"
          :stroke="
            styleMap?.mainStyle?.curve?.imageSrc
              ? `url(#${arcId}-bg-pattern)`
              : styleMap?.mainStyle?.curve?.color || '#eeeeee'
          "
          :stroke-width="styleMap?.mainStyle?.curve?.width ?? 1"
          :stroke-linecap="styleMap?.mainStyle?.curve?.radius ? 'round' : 'butt'"
          :opacity="styleMap?.mainStyle?.curve?.opacity"
        />

        <!-- 进度值条 -->
        <path
          :d="valuePath"
          fill="none"
          :stroke="
            styleMap?.indicatorStyle?.curve?.imageSrc
              ? `url(#${arcId}-indicator-pattern)`
              : styleMap?.indicatorStyle?.curve?.color || '#2092f5'
          "
          :stroke-width="styleMap?.indicatorStyle?.curve?.width ?? 1"
          :stroke-linecap="styleMap?.indicatorStyle?.curve?.radius ? 'round' : 'butt'"
          :opacity="styleMap?.indicatorStyle?.curve?.opacity"
        />

        <!-- 进度圆点：无背景图时用实心圆 -->
        <circle
          v-if="dotPos && !styleMap?.knobStyle?.imageSrc"
          :cx="dotPos.x"
          :cy="dotPos.y"
          :r="knobRadius.radius"
          :fill="styleMap?.knobStyle?.backgroundColor || '#2092f5'"
        />
      </svg>

      <!-- 进度圆点背景图：与 SVG 同坐标系，用 ImageBg 统一实现 -->
      <div
        v-if="dotPos && styleMap?.knobStyle?.imageSrc"
        class="absolute overflow-hidden pointer-events-none"
        :style="knobOverlayStyle"
      >
        <ImageBg :src="styleMap.knobStyle.imageSrc" :imageStyle="styleMap.knobStyle.imageStyle" />
      </div>
    </div>
  </div>
</template>

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

import ImageBg from '../ImageBg.vue'

const arcId = ref('arc-' + Math.random().toString(36).slice(2))

const props = defineProps<{
  width: number
  height: number
  styles: any
  state?: string
  part?: string
  mode: 'normal' | 'symmetrical' | 'reverse'
  rangeStart: number
  rangeEnd: number
  angleStart: number
  angleEnd: number
  value: number
  rotate: number
  // 偏移开关
  rotateOffset?: boolean
  // 偏移量(度数)
  rotateOffsetValue?: number
}>()

const projectStore = useProjectStore()

const styleMap = useWidgetStyle({
  widget: 'lv_arc',
  props
})

const cx = computed(() => {
  const { width, height } = props
  const min = Math.min(width, height)
  return min / 2
})

/** 弧线半径：与背景/进度条一致，留出边距避免贴边 */
const trackRadius = computed(() => {
  const { width, height } = props
  const min = Math.min(width, height)
  const curveWidth = styleMap.value?.mainStyle?.curve?.width ?? 12
  return Math.max(4, min / 2 - curveWidth / 2 - knobRadius.value.padding)
})

/** 从 schema 的 styles 中解析 knob 的 padding.left 作为圆点半径 */
const knobRadius = computed(() => {
  const defaultIndicatorStyle = projectStore.globalStyle
    ?.find((item) => item.widget === 'lv_arc')
    ?.part?.find((item) => item.partName === 'indicator')?.defaultStyle

  const defaultKnobStyle = projectStore.globalStyle
    ?.find((item) => item.widget === 'lv_arc')
    ?.part?.find((item) => item.partName === 'knob')?.defaultStyle

  const indicatorStyle = props.styles?.find(
    (s: any) => s.part?.name === 'indicator' && s.part.state === props.state
  )
  const knobStyle = props.styles?.find(
    (s: any) => s.part?.name === 'knob' && s.part.state === props.state
  )
  const padding = knobStyle?.padding?.left ?? defaultKnobStyle?.padding?.left
  const r = indicatorStyle?.curve?.width ?? defaultIndicatorStyle?.curve?.width ?? 12

  return {
    radius: r / 2 + padding,
    padding: padding,
    width: r
  }
})

/**
 * 极坐标转直角坐标
 * SVG 角度习惯：0度在右侧(3点钟)，需调整使0度在上方(12点钟)
 */
function polarToCartesian(
  centerX: number,
  centerY: number,
  radius: number,
  angleInDegrees: number
) {
  // LVGL 习惯通常 0 度在右侧，如果需要 0 度在上方，这里减去 90
  // 这里我们遵循标准：angleStart 为输入值
  // 当angleInDegress为360时，需要偏移一点
  if (angleInDegrees === 360) {
    angleInDegrees = 359.999
  }
  const radians = ((angleInDegrees - 0) * Math.PI) / 180.0
  return {
    x: centerX + radius * Math.cos(radians),
    y: centerY + radius * Math.sin(radians)
  }
}

/**
 * 生成 SVG 弧线路径指令
 * 始终从 startAngle 顺时针画到 endAngle，得到“近整圆、缺口在底部”的环（图2效果）
 */
function describeArc(x: number, y: number, radius: number, startAngle: number, endAngle: number) {
  const start = polarToCartesian(x, y, radius, startAngle)
  const end = polarToCartesian(x, y, radius, endAngle)
  // 顺时针扫过的角度（0~360）
  let clockwiseSpan = (endAngle - startAngle) % 360
  if (clockwiseSpan <= 0) clockwiseSpan += 360
  if (clockwiseSpan === 0) clockwiseSpan = 360
  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(' ')
}

// 1. 背景路径
const bgPath = computed(() => {
  const r = trackRadius.value
  return describeArc(cx.value, cx.value, r, props.angleStart, props.angleEnd)
})

// 顺时针从 angleStart 到 angleEnd 的弧度跨度（0~360）
const clockwiseSpan = computed(() => {
  const { angleStart, angleEnd } = props
  let s = (angleEnd - angleStart) % 360
  if (s <= 0) s += 360
  return s === 0 ? 360 : s
})

// 2. 进度计算逻辑（与 describeArc 的顺时针方向一致）
const progressData = computed(() => {
  const { value, rangeStart, rangeEnd, angleStart, angleEnd, mode } = props

  const rangeDiff = rangeEnd - rangeStart
  const ratio =
    Math.abs(rangeDiff) < 1e-9 ? 0 : Math.max(0, Math.min(1, (value - rangeStart) / rangeDiff))

  const span = clockwiseSpan.value
  let startA = angleStart
  let endA = angleEnd

  if (mode === 'normal') {
    // 从 angleStart 顺时针填充 span * ratio
    endA = angleStart + span * ratio
  } else if (mode === 'reverse') {
    startA = angleEnd - span * ratio
    endA = angleEnd
  } else if (mode === 'symmetrical') {
    const midAngle = angleStart + span / 2
    const midValue = (rangeStart + rangeEnd) / 2
    const rangeToEnd = rangeEnd - midValue
    const rangeToStart = midValue - rangeStart

    if (value >= midValue && Math.abs(rangeToEnd) >= 1e-9) {
      startA = midAngle
      const halfRatio = Math.max(0, Math.min(1, (value - midValue) / rangeToEnd))
      endA = midAngle + (span / 2) * halfRatio
    } else if (value < midValue && Math.abs(rangeToStart) >= 1e-9) {
      endA = midAngle
      const halfRatio = Math.max(0, Math.min(1, (midValue - value) / rangeToStart))
      startA = midAngle - (span / 2) * halfRatio
    } else {
      startA = midAngle
      endA = midAngle
    }
  }

  return { startA, endA }
})

// 3. 值路径（与背景弧同半径）
const valuePath = computed(() => {
  const { startA, endA } = progressData.value
  if (startA === endA) return ''
  return describeArc(cx.value, cx.value, trackRadius.value, startA, endA)
})

// 4. 圆点位置（与弧同半径）
const dotPos = computed(() => {
  // 原始结束角：normal / symmetrical 用 endA，reverse 用 startA
  const baseAngle = props.mode === 'reverse' ? progressData.value.startA : progressData.value.endA
  // 仅对“结束值原点”做偏移，不整体偏移整条进度弧
  const offset = props.rotateOffset ? (props.rotateOffsetValue ?? 0) : 0
  const angle = baseAngle + offset
  return polarToCartesian(cx.value, cx.value, trackRadius.value, angle)
})

/** 进度圆点 overlay 的定位样式（与 viewBox 比例一致，用 ImageBg 时使用） */
const knobOverlayStyle = computed(() => {
  if (!dotPos.value || !props.width || !props.height) return {}
  const { x, y } = dotPos.value
  const r = knobRadius.value.radius
  return {
    left: `${((x - r) / props.width) * 100}%`,
    top: `${((y - r) / props.height) * 100}%`,
    width: `${((r * 2) / props.width) * 100}%`,
    height: `${((r * 2) / props.height) * 100}%`,
    borderRadius: '50%'
  }
})
</script>
