<template>
  <el-dialog draggable append-to-body v-model="show" title="背景颜色" width="440px">
    <el-scrollbar height="400px">
      <div class="w-full flex flex-col items-center">
        <el-segmented v-if="useType === 'both'" v-model="type" :options="typeOptions" />

        <div v-if="type !== 'pure'" class="w-full flex flex-col items-center">
          <h4 class="m-0">预览</h4>
          <div class="w-80% h-60px rounded-4px mb-10px" :style="previewGradient"></div>
        </div>

        <!-- 纯色 -->
        <div v-if="type === 'pure'" class="mt-20px">
          <ColorPicker
            v-model:pureColor="pureColor"
            format="hex8"
            picker-type="chrome"
            use-type="pure"
            isWidget
          />
        </div>

        <!-- 基础渐变 -->
        <div v-else-if="type === 'gradient'" class="w-full">
          <el-form label-width="80px" label-position="left">
            <el-form-item label="渐变方向">
              <el-radio-group v-model="basicDirection">
                <el-radio value="horizontal">水平渐变</el-radio>
                <el-radio value="vertical">垂直渐变</el-radio>
              </el-radio-group>
            </el-form-item>

            <el-form-item label="开始颜色">
              <div class="flex items-center gap-12px w-full">
                <ColorPicker
                  v-model:pureColor="basicStartColor"
                  format="hex8"
                  picker-type="chrome"
                  use-type="pure"
                />
                <div>
                  {{ basicStartColor }}
                </div>
              </div>
            </el-form-item>

            <el-form-item label="结束颜色">
              <div class="flex items-center gap-12px w-full">
                <ColorPicker
                  v-model:pureColor="basicEndColor"
                  format="hex8"
                  picker-type="chrome"
                  use-type="pure"
                />
                <div>
                  {{ basicEndColor }}
                </div>
              </div>
            </el-form-item>

            <el-form-item label="开始点">
              <div class="flex items-center gap-8px w-full">
                <el-slider v-model="basicStartPos" :min="0" :max="255" style="flex: 1" />
                <span class="w-40px text-right text-text-active">
                  {{ basicStartPos }}
                </span>
              </div>
            </el-form-item>

            <el-form-item label="结束点">
              <div class="flex items-center gap-8px w-full">
                <el-slider v-model="basicEndPos" :min="0" :max="255" style="flex: 1" />
                <span class="w-40px text-right text-text-active">
                  {{ basicEndPos }}
                </span>
              </div>
            </el-form-item>
          </el-form>
        </div>

        <!-- 高级渐变 -->
        <div v-else class="w-full">
          <el-form label-position="top" class="advanced-form">
            <el-form-item label="渐变类型">
              <el-radio-group v-model="advancedType" @change="onChangeAdvancedType">
                <el-radio label="linear">线性渐变</el-radio>
                <el-radio label="radial">径向渐变</el-radio>
                <el-radio label="conical">锥形渐变</el-radio>
              </el-radio-group>
            </el-form-item>

            <!-- 线性渐变：起始/结束坐标 -->
            <template v-if="advancedType === 'linear'">
              <el-form-item label="开始坐标">
                <div class="w-full flex items-center gap-8px">
                  <input-number
                    v-model="linearStartX"
                    :min="0"
                    :max="width"
                    size="small"
                    style="flex: 1"
                  >
                    <template #prefix>X</template>
                  </input-number>
                  <input-number
                    v-model="linearStartY"
                    :min="0"
                    :max="height"
                    size="small"
                    style="flex: 1"
                  >
                    <template #prefix>Y</template>
                  </input-number>
                </div>
              </el-form-item>
              <el-form-item label="结束坐标">
                <div class="w-full flex items-center gap-8px">
                  <input-number
                    v-model="linearEndX"
                    :min="0"
                    :max="width"
                    size="small"
                    style="flex: 1"
                  >
                    <template #prefix>X</template>
                  </input-number>
                  <input-number
                    v-model="linearEndY"
                    :min="0"
                    :max="height"
                    size="small"
                    style="flex: 1"
                  >
                    <template #prefix>Y</template>
                  </input-number>
                </div>
              </el-form-item>
            </template>

            <!-- 径向渐变：中心点 -->
            <template v-else-if="advancedType === 'radial'">
              <el-form-item label="中心点坐标">
                <div class="w-full flex items-center gap-8px">
                  <input-number
                    v-model="centerX"
                    :min="0"
                    :max="width"
                    size="small"
                    style="flex: 1"
                  >
                    <template #prefix>X</template>
                  </input-number>
                  <input-number
                    v-model="centerY"
                    :min="0"
                    :max="height"
                    size="small"
                    style="flex: 1"
                  >
                    <template #prefix>Y</template>
                  </input-number>
                </div>
              </el-form-item>
            </template>

            <!-- 锥形渐变：中心点 + 角度 -->
            <template v-else>
              <el-form-item label="中心点坐标">
                <div class="w-full flex items-center gap-8px">
                  <input-number
                    v-model="centerX"
                    :min="0"
                    :max="width"
                    size="small"
                    style="flex: 1"
                  />
                  <input-number
                    v-model="centerY"
                    :min="0"
                    :max="height"
                    size="small"
                    style="flex: 1"
                  />
                </div>
              </el-form-item>
              <el-form-item label="角度">
                <div class="w-full flex items-center gap-8px">
                  <input-number
                    v-model="coneStartAngle"
                    :min="0"
                    :max="3600"
                    size="small"
                    style="width: 100%"
                  >
                    <template #prefix>S</template>
                  </input-number>
                  <input-number
                    v-model="coneEndAngle"
                    :min="0"
                    :max="3600"
                    size="small"
                    style="width: 100%"
                  >
                    <template #prefix>E</template>
                  </input-number>
                </div>
              </el-form-item>
            </template>

            <!-- 渐变点列表 -->
            <el-form-item label="渐变点">
              <div class="w-full flex flex-col gap-12px">
                <el-button type="primary" :disabled="pointsList.length >= 16" @click="addPoint">
                  新增渐变点
                </el-button>
                <div v-for="(pt, index) in pointsList" :key="index" class="gradient-point-item">
                  <el-card shadow="hover" bodyClass="p-10px! relative">
                    <div class="flex gap-12px items-center pr-12px jusitfy-between">
                      <ColorPicker
                        class="flex-1"
                        v-model:pureColor="pt.color"
                        format="hex8"
                        picker-type="chrome"
                        use-type="pure"
                      />
                      <div class="flex-1/3">
                        <div>颜色值</div>
                        <div>{{ pt.color }}</div>
                      </div>
                      <div class="flex-1/3">
                        <div>位置:{{ pt.point }}</div>
                        <div><el-slider v-model="pt.point" :min="0" :max="255" /></div>
                      </div>
                    </div>
                    <div class="absolute right-4px top-0">
                      <el-button v-if="pointsList.length > 2" link @click="removePoint(index)">
                        <LuTrash2 size="14px" />
                      </el-button>
                    </div>
                  </el-card>
                </div>
              </div>
            </el-form-item>
          </el-form>
        </div>
      </div>
    </el-scrollbar>

    <template #footer>
      <el-button type="primary" @click="submit">确定</el-button>
    </template>
  </el-dialog>
  <div v-if="useType != 'pure'" class="trigger" @click="open">
    <slot name="trigger">
      <div class="w-full h-full" :style="triggerStyle"></div>
    </slot>
  </div>
  <ColorPicker
    v-else
    v-model:pureColor="pureColor"
    format="hex8"
    picker-type="chrome"
    use-type="pure"
  />
</template>
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { ColorPicker } from '..'
import { parseCssGradient, generateCssGradient } from '@/utils'
import { klona } from 'klona'
import { LuTrash2 } from 'vue-icons-plus/lu'

import type { GradientColor } from '@/lvgl-widgets/type'

const pureColor = defineModel<string>('pureColor')
const gradientColor = defineModel<GradientColor | string>('gradientColor')

const props = withDefaults(
  defineProps<{
    useType?: 'pure' | 'gradient' | 'both'
    onlyColor?: boolean
    width?: number
    height?: number
  }>(),
  {
    useType: 'pure'
  }
)
const show = ref(false)

const type = ref<'pure' | 'gradient' | 'advanced'>('pure')
const typeOptions = computed(() => {
  const options = [
    {
      label: '纯色',
      value: 'pure'
    },
    {
      label: '基础渐变',
      value: 'gradient'
    }
  ]
  // 如果宽高存在，则高级渐变可选
  if (props.width && props.height) {
    options.push({
      label: '高级渐变',
      value: 'advanced'
    })
  }

  return options
})

// 内部渐变配置对象
const internalGradient = ref<GradientColor | null>(null)

const ensureGradient = () => {
  if (!internalGradient.value) {
    internalGradient.value = {
      type: 'linear',
      gradientType: 'gradient',
      direction: 'horizontal',
      points: [
        {
          point: 0,
          color: pureColor.value || '#000000FF'
        },
        {
          point: 255,
          color: '#FFFFFFFF'
        }
      ],
      start: {
        x: 0,
        y: 0
      },
      end: {
        x: props.width || 100,
        y: props.height || 100
      }
    }
  }
}

const emitGradientChange = () => {
  if (!internalGradient.value) return
  gradientColor.value = klona(internalGradient.value)
}

// 外部 v-model 同步到内部对象
watch(
  () => gradientColor.value,
  (val) => {
    if (!val) {
      internalGradient.value = null
      return
    }
    if (typeof val === 'string') {
      internalGradient.value = parseCssGradient(val) || null
    } else {
      internalGradient.value = klona(val)
      type.value = val.gradientType === 'gradient' ? 'gradient' : 'advanced'
    }
  },
  { immediate: true }
)

watch(type, (val) => {
  if (!internalGradient.value) return
  internalGradient.value.gradientType = val === 'gradient' ? 'gradient' : 'advanced'
  // 保留前2个渐变点
  if (val === 'gradient') {
    internalGradient.value.type = 'linear'
    const points = internalGradient.value.points
    if (points && points.length > 2) {
      internalGradient.value.points = points.slice(0, 2)
    }
  }
})

// 打开弹窗时，根据当前是否有渐变自动切换 tab
const open = () => {
  if (gradientColor.value) {
    ensureGradient()
  }
  show.value = true
}

defineExpose({
  open
})

// 触发器样式：优先使用渐变，否则使用纯色
const triggerStyle = computed(() => {
  if (gradientColor.value) {
    if (typeof gradientColor.value === 'string') {
      return {
        backgroundImage: gradientColor.value as string
      }
    }
    return {
      backgroundImage: generateCssGradient(
        gradientColor.value as GradientColor,
        props.width,
        props.height
      )
    }
  }

  return {
    background: pureColor.value || '#ffffffff'
  }
})

// 预览渐变色
const previewGradient = computed(() => {
  return {
    background: internalGradient.value
      ? generateCssGradient(internalGradient.value, props.width, props.height)
      : '#ffffff00'
  }
})

// 基础渐变：方向
const basicDirection = computed({
  get() {
    ensureGradient()
    return internalGradient.value?.direction || 'horizontal'
  },
  set(val: 'horizontal' | 'vertical') {
    ensureGradient()
    if (!internalGradient.value) return
    internalGradient.value.direction = val
    internalGradient.value.type = 'linear'
  }
})

// 基础渐变：起始/结束颜色
const basicStartColor = computed({
  get() {
    ensureGradient()
    return internalGradient.value?.points?.[0]?.color || '#000000FF'
  },
  set(val: string) {
    ensureGradient()
    if (!internalGradient.value?.points) return
    internalGradient.value.points[0].color = val
  }
})

const basicEndColor = computed({
  get() {
    ensureGradient()
    const pts = internalGradient.value?.points || []
    return pts[pts.length - 1]?.color || '#FFFFFFFF'
  },
  set(val: string) {
    ensureGradient()
    if (!internalGradient.value?.points) return
    const pts = internalGradient.value.points
    pts[pts.length - 1].color = val
  }
})

// 基础渐变：起始/结束点（0~255），若起始 > 结束，则交换
const basicStartPos = computed({
  get() {
    ensureGradient()
    const pos = internalGradient.value?.points?.[0]?.point
    return pos ?? 0
  },
  set(val: number) {
    ensureGradient()
    if (!internalGradient.value?.points) return
    const pts = internalGradient.value.points
    let v = Math.min(255, Math.max(0, val))

    pts[0].point = v
  }
})

const basicEndPos = computed({
  get() {
    ensureGradient()
    const pts = internalGradient.value?.points
    const pos = pts?.[pts.length - 1]?.point
    return pos ?? 255
  },
  set(val: number) {
    ensureGradient()
    if (!internalGradient.value?.points) return
    const pts = internalGradient.value.points
    let v = Math.min(255, Math.max(0, val))

    pts[pts.length - 1].point = v
  }
})

// 高级渐变：类型
const advancedType = computed({
  get() {
    ensureGradient()
    return internalGradient.value?.type || 'linear'
  },
  set(val: GradientColor['type']) {
    ensureGradient()
    if (!internalGradient.value) return
    internalGradient.value.type = val
  }
})

// 线性渐变：起始/结束坐标（0~100，对应控件宽高百分比）
const linearStartX = computed({
  get() {
    ensureGradient()
    return internalGradient.value?.start?.x ?? 0
  },
  set(val: number) {
    ensureGradient()
    if (!internalGradient.value) return
    if (!internalGradient.value.start) internalGradient.value.start = { x: 0, y: 0 }
    internalGradient.value.start.x = Math.max(0, val)
  }
})

const linearStartY = computed({
  get() {
    ensureGradient()
    return internalGradient.value?.start?.y ?? 0
  },
  set(val: number) {
    ensureGradient()
    if (!internalGradient.value) return
    if (!internalGradient.value.start) internalGradient.value.start = { x: 0, y: 0 }
    internalGradient.value.start.y = Math.max(0, val)
  }
})

const linearEndX = computed({
  get() {
    ensureGradient()
    return internalGradient.value?.end?.x ?? 100
  },
  set(val: number) {
    ensureGradient()
    if (!internalGradient.value) return
    if (!internalGradient.value.end) internalGradient.value.end = { x: 100, y: 100 }
    internalGradient.value.end.x = Math.max(0, val)
  }
})

const linearEndY = computed({
  get() {
    ensureGradient()
    return internalGradient.value?.end?.y ?? 100
  },
  set(val: number) {
    ensureGradient()
    if (!internalGradient.value) return
    if (!internalGradient.value.end) internalGradient.value.end = { x: 100, y: 100 }
    internalGradient.value.end.y = Math.max(0, val)
  }
})

// 径向/锥形渐变：中心点（0~100，默认 50）
const centerX = computed({
  get() {
    ensureGradient()
    return internalGradient.value?.center?.x ?? 50
  },
  set(val: number) {
    ensureGradient()
    if (!internalGradient.value) return
    if (!internalGradient.value.center) internalGradient.value.center = { x: 50, y: 50 }
    internalGradient.value.center.x = Math.max(0, val)
  }
})

const centerY = computed({
  get() {
    ensureGradient()
    return internalGradient.value?.center?.y ?? 50
  },
  set(val: number) {
    ensureGradient()
    if (!internalGradient.value) return
    if (!internalGradient.value.center) internalGradient.value.center = { x: 50, y: 50 }
    internalGradient.value.center.y = Math.max(0, val)
  }
})

// 锥形渐变：角度 0~3600
const coneStartAngle = computed({
  get() {
    ensureGradient()
    return internalGradient.value?.angle?.start ?? 0
  },
  set(val: number) {
    ensureGradient()
    if (!internalGradient.value) return
    if (!internalGradient.value.angle) internalGradient.value.angle = { start: 0, end: 360 }
    internalGradient.value.angle.start = Math.min(3600, Math.max(0, val))
  }
})

const coneEndAngle = computed({
  get() {
    ensureGradient()
    return internalGradient.value?.angle?.end ?? 360
  },
  set(val: number) {
    ensureGradient()
    if (!internalGradient.value) return
    if (!internalGradient.value.angle) internalGradient.value.angle = { start: 0, end: 360 }
    internalGradient.value.angle.end = Math.min(3600, Math.max(0, val))
  }
})

// 高级渐变：渐变点列表（最少 2，最多 16）
const pointsList = computed({
  get() {
    ensureGradient()
    if (!internalGradient.value!.points || internalGradient.value!.points.length < 2) {
      internalGradient.value!.points = [
        { color: '#000000FF', point: 0 },
        { color: '#FFFFFFFF', point: 255 }
      ]
    }
    return internalGradient.value!.points!
  },
  set(val) {
    if (!internalGradient.value) return
    internalGradient.value.points = val
  }
})

const sortPointsByPosition = () => {
  if (!internalGradient.value?.points) return
  internalGradient.value.points = internalGradient.value.points.sort((a, b) => {
    const pa = a.point ?? a.point
    const pb = b.point ?? b.point
    return pa - pb
  })
}

const addPoint = () => {
  ensureGradient()
  if (!internalGradient.value?.points) return
  if (internalGradient.value.points.length >= 16) return

  const last = internalGradient.value.points[internalGradient.value.points.length - 1]
  const lastPos = last.point ?? 255
  const newPos = Math.min(255, lastPos + 10)

  internalGradient.value.points.push({
    color: '#FFFFFFFF',
    point: newPos
  })
  sortPointsByPosition()
}

const removePoint = (index: number) => {
  ensureGradient()
  if (!internalGradient.value?.points) return
  if (internalGradient.value.points.length <= 2) return
  internalGradient.value.points.splice(index, 1)
}

const onChangeAdvancedType = (val) => {
  ensureGradient()
  if (!internalGradient.value) return
  if (val === 'linear') {
    internalGradient.value.end = {
      x: props.width || 100,
      y: props.height || 100
    }
  } else {
    internalGradient.value.center = {
      x: (props.width || 100) / 2,
      y: (props.height || 100) / 2
    }
  }
}

const submit = () => {
  emitGradientChange()
  show.value = false
}
</script>

<style scoped>
.trigger {
  width: 24px;
  height: 24px;
  border-radius: 4px;
  overflow: hidden;
  cursor: pointer;
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
  background-repeat: repeat;
  margin-right: 10px;
}
.trigger-bg {
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
}
</style>
