<template>
  <view class="wd-slider-wrapper">
    <view class="wd-slider">
      <view class="wd-slider-rail"></view>
      <view
        class="wd-slider-track"
        :style="{
          left: range ? `${leftPercentage}%` : '0%',
          width: range ? `${rightPercentage - leftPercentage}%` : `${rightPercentage}%`,
          backgroundColor: activeColor,
        }"
      ></view>
      <view
        v-if="range"
        class="wd-slider-thumb left-thumb"
        :class="{ 'active-thumb': isLeftActive }"
        :style="{
          left: `${leftPercentage}%`,
          transform: 'translate(-50%, -50%)',
          borderColor: activeColor,
        }"
        @touchstart="handleLeftThumbTouchStart"
        @touchmove="handleLeftThumbTouchMove"
        @touchend="handleLeftThumbTouchEnd"
      >
        <text
          v-if="showThumbValue || isLeftActive"
          class="wd-slider-thumb-value-inner"
          :class="{ 'active-value': isLeftActive }"
          :style="{ color: computedThumbValueColor }"
        >
          {{ formatValue(currentLeftValue) }}
        </text>
      </view>
      <view
        class="wd-slider-thumb right-thumb"
        :class="{ 'active-thumb': isRightActive }"
        :style="{
          left: `${rightPercentage}%`,
          transform: 'translate(-50%, -50%)',
          borderColor: activeColor,
        }"
        @touchstart="handleRightThumbTouchStart"
        @touchmove="handleRightThumbTouchMove"
        @touchend="handleRightThumbTouchEnd"
      >
        <text
          v-if="showThumbValue || isRightActive"
          class="wd-slider-thumb-value-inner"
          :class="{ 'active-value': isRightActive }"
          :style="{ color: computedThumbValueColor }"
        >
          {{ formatValue(currentRightValue) }}
        </text>
      </view>
    </view>
    <view v-if="showLabels" class="wd-slider-labels">
      <text class="wd-slider-label left-label">{{ formatValue(currentLeftValue) }}</text>
      <text class="wd-slider-label right-label">{{ formatValue(currentRightValue) }}</text>
    </view>
  </view>
</template>

<script setup>
import { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'
import { getCurrentInstance } from 'vue'

// 获取当前组件实例
const instance = getCurrentInstance()

const props = defineProps({
  modelValue: {
    type: Array,
    default: () => [0, 0],
  },
  min: {
    type: Number,
    default: 0,
  },
  max: {
    type: Number,
    default: 100,
  },
  step: {
    type: Number,
    default: 1,
  },
  range: {
    type: Boolean,
    default: false,
  },
  showLabels: {
    type: Boolean,
    default: false,
  },
  showThumbValue: {
    type: Boolean,
    default: true,
  },
  activeColor: {
    type: String,
    default: '#4e80ff',
  },
  thumbValueColor: {
    type: String,
    default: '',
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  formatValue: {
    type: Function,
    default: (value) => {
      // 处理较小的值，确保显示合适的位数
      if (typeof value === 'number') {
        if (value < 10) {
          return value.toFixed(1)
        }
      }
      return value
    },
  },
})

const emit = defineEmits(['update:modelValue', 'change'])

// 当前值
const currentLeftValue = ref(props.range ? props.modelValue[0] : props.min)
const currentRightValue = ref(props.range ? props.modelValue[1] : props.modelValue[0])

// 控制值显示状态
const isLeftActive = ref(false)
const isRightActive = ref(false)

// 轨道宽度
const railWidth = ref(0)

// 计算颜色值
const computedThumbValueColor = computed(() => {
  return props.thumbValueColor || props.activeColor
})

// 初始化时获取轨道宽度
const initRailWidth = () => {
  setTimeout(() => {
    getRailWidth().then((width) => {
      railWidth.value = width
    })
  }, 100) // 延迟一些时间确保DOM已渲染
}

// 在组件挂载后获取轨道宽度
onMounted(() => {
  initRailWidth()

  // 添加窗口大小改变的监听
  uni.onWindowResize(initRailWidth)
})

// 在组件销毁前移除监听
onBeforeUnmount(() => {
  uni.offWindowResize(initRailWidth)
})

// 计算滑块位置的百分比
const leftPercentage = computed(() => {
  return ((currentLeftValue.value - props.min) / (props.max - props.min)) * 100
})

const rightPercentage = computed(() => {
  return ((currentRightValue.value - props.min) / (props.max - props.min)) * 100
})

// 监听外部值变化
watch(
  () => props.modelValue,
  (newVal) => {
    if (props.range) {
      currentLeftValue.value = newVal[0]
      currentRightValue.value = newVal[1]
    } else {
      currentRightValue.value = newVal[0]
    }
  },
  { immediate: true, deep: true },
)

// 根据位置计算值
const calculateValueFromPosition = (position, width) => {
  const percentage = Math.max(0, Math.min(100, (position / width) * 100))
  const rawValue = (percentage / 100) * (props.max - props.min) + props.min

  // 根据步长调整值
  const steps = Math.round((rawValue - props.min) / props.step)
  return props.min + steps * props.step
}

// 触摸事件处理
let startX = 0
let startLeftValue = 0
let startRightValue = 0
let isDragging = false

// 获取滑块轨道宽度
const getRailWidth = () => {
  return new Promise((resolve) => {
    const query = uni.createSelectorQuery()
    if (instance) {
      query.in(instance.proxy)
    }
    query
      .select('.wd-slider-rail')
      .boundingClientRect((data) => {
        if (data) {
          resolve(data.width)
        } else {
          resolve(0)
        }
      })
      .exec()
  })
}

const handleLeftThumbTouchStart = async (e) => {
  if (props.disabled) return

  isDragging = true
  isLeftActive.value = true
  startX = e.touches[0].clientX
  startLeftValue = currentLeftValue.value

  // 使用已存储的轨道宽度或重新获取
  if (!railWidth.value) {
    railWidth.value = await getRailWidth()
  }
}

const handleLeftThumbTouchMove = (e) => {
  if (!isDragging || props.disabled || !railWidth.value) return

  const moveX = e.touches[0].clientX - startX
  const movePercentage = (moveX / railWidth.value) * 100
  const newLeftValue = calculateValueFromPosition(
    ((startLeftValue - props.min) / (props.max - props.min)) * railWidth.value + moveX,
    railWidth.value,
  )

  // 确保左滑块不超过右滑块
  if (newLeftValue <= currentRightValue.value) {
    currentLeftValue.value = newLeftValue
    emitValueChange()
  }
}

const handleLeftThumbTouchEnd = () => {
  if (props.disabled) return

  isDragging = false
  isLeftActive.value = false
  emit(
    'change',
    props.range ? [currentLeftValue.value, currentRightValue.value] : [currentRightValue.value],
  )
}

const handleRightThumbTouchStart = async (e) => {
  if (props.disabled) return

  isDragging = true
  isRightActive.value = true
  startX = e.touches[0].clientX
  startRightValue = currentRightValue.value

  // 使用已存储的轨道宽度或重新获取
  if (!railWidth.value) {
    railWidth.value = await getRailWidth()
  }
}

const handleRightThumbTouchMove = (e) => {
  if (!isDragging || props.disabled || !railWidth.value) return

  const moveX = e.touches[0].clientX - startX
  const movePercentage = (moveX / railWidth.value) * 100
  const newRightValue = calculateValueFromPosition(
    ((startRightValue - props.min) / (props.max - props.min)) * railWidth.value + moveX,
    railWidth.value,
  )

  // 确保右滑块不小于左滑块
  if (props.range) {
    if (newRightValue >= currentLeftValue.value) {
      currentRightValue.value = newRightValue
      emitValueChange()
    }
  } else {
    currentRightValue.value = newRightValue
    emitValueChange()
  }
}

const handleRightThumbTouchEnd = () => {
  if (props.disabled) return

  isDragging = false
  isRightActive.value = false
  emit(
    'change',
    props.range ? [currentLeftValue.value, currentRightValue.value] : [currentRightValue.value],
  )
}

// 发送值变化事件
const emitValueChange = () => {
  emit(
    'update:modelValue',
    props.range ? [currentLeftValue.value, currentRightValue.value] : [currentRightValue.value],
  )
}
</script>

<style lang="scss" scoped>
.wd-slider-wrapper {
  box-sizing: border-box;
  width: 100%;
}

.wd-slider {
  position: relative;
  height: 30px;
  display: flex;
  align-items: center;
}

.wd-slider-rail {
  position: absolute;
  width: 100%;
  height: 4px;
  background-color: #e9e9e9;
  border-radius: 2px;
}

.wd-slider-track {
  position: absolute;
  height: 4px;
  background-color: v-bind('activeColor');
  border-radius: 2px;
}

.wd-slider-thumb {
  position: absolute;

  width: 66rpx;
  height: 42rpx;
  border-radius: 12rpx 12rpx 12rpx 12rpx;
  background-color: #fff;

  border: 2px solid v-bind('activeColor');
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
  z-index: 1;
  top: 50%;
  transition:
    transform 0.2s,
    width 0.2s,
    height 0.2s,
    background-color 0.2s;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  user-select: none;
}

.active-thumb {
  transform: translate(-50%, -50%) scale(0.7) !important;
  z-index: 2;
  border-color: v-bind('activeColor');
  background-color: #f5f8ff;
  width: 42px;
  height: 42px;
}

.wd-slider-thumb-value-inner {
  font-size: 12px;
  color: v-bind('computedThumbValueColor');
  text-align: center;
  transition: all 0.2s;
  line-height: 1;
  font-weight: 500;
  white-space: nowrap; /* 防止数字换行 */
  padding: 0 2px;
}

.active-value {
  font-weight: bold;
  color: v-bind('computedThumbValueColor');
  font-size: 13px;
}

.wd-slider-labels {
  display: flex;
  justify-content: space-between;
  margin-top: 10px;
  font-size: 12px;
  color: #666;
}

.wd-slider-label {
  transform: translateX(-50%);
}

.left-label {
  position: relative;
  left: v-bind(leftPercentage + '%');
}

.right-label {
  position: relative;
  left: v-bind(rightPercentage + '%');
}
</style>
