<template>
  <view 
    class="star-rating"
    @touchstart="onTouchStart"
    @touchmove="onTouchMove"
    @touchend="onTouchEnd"
  >
    <!-- 星星容器 -->
    <view 
      v-for="(item, index) in count" 
      :key="index" 
      class="star-container"
      @click="handleClick(index)"
    >
      <!-- 灰色背景星星 -->
      <view class="star-background">
        <u-icon name="star-fill" :color="inactiveColor" :size="size"></u-icon>
      </view>
      <!-- 黄色前景星星，使用宽度百分比控制 -->
      <view 
        class="star-foreground" 
        :style="{ width: getStarWidth(index), color: activeColor }"
      >
        <u-icon name="star-fill" :color="activeColor" :size="size"></u-icon>
      </view>
    </view>
    
    <!-- 可选：显示评分值 -->
    <text v-if="showScore" class="score-text">{{ displayValue }}</text>
  </view>
</template>

<script>
export default {
  name: 'StarRating',
  props: {
    // 当前评分值（支持小数）
    value: {
      type: Number,
      default: 0
    },
    // 星星总数
    count: {
      type: Number,
      default: 5
    },
    // 是否禁用点击
    disabled: {
      type: Boolean,
      default: false
    },
    // 是否显示分数
    showScore: {
      type: Boolean,
      default: false
    },
    // 星星大小
    size: {
      type: [Number, String],
      default: 28
    },
    // 选中颜色
    activeColor: {
      type: String,
      default: '#ffd21e'
    },
    // 未选中颜色
    inactiveColor: {
      type: String,
      default: '#e0e0e0'
    },
    // 是否允许半星
    allowHalf: {
      type: Boolean,
      default: true
    },
    // 点击时是否启用动画
    animation: {
      type: Boolean,
      default: true
    },
    // 是否启用滑动评分
    swipeable: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      currentValue: this.value,
      // 滑动相关
      startX: 0,
      starWidth: 0,
      isSwiping: false,
      touchId: null
    }
  },
  computed: {
    // 格式化显示的值
    displayValue() {
      return this.currentValue.toFixed(1);
    }
  },
  watch: {
    value(newVal) {
      this.currentValue = newVal;
    }
  },
  mounted() {
    // 获取星星宽度，用于滑动计算
    this.$nextTick(() => {
      this.calculateStarWidth();
    });
  },
  methods: {
    // 计算每个星星的填充百分比
    getStarWidth(index) {
      const starIndex = index + 1;
      const value = this.currentValue;
      
      // 如果当前星星完全填充
      if (value >= starIndex) {
        return '100%';
      }
      
      // 如果当前星星部分填充
      if (value > starIndex - 1) {
        if (this.allowHalf) {
          // 计算小数部分
          const decimalPart = value - (starIndex - 1);
          return (decimalPart * 100) + '%';
        } else {
          // 如果不允许半星，则要么全满要么全空
          return '0%';
        }
      }
      
      // 当前星星为空
      return '0%';
    },
    
    // 计算星星宽度
    calculateStarWidth() {
      const query = uni.createSelectorQuery().in(this);
      query.select('.star-container').boundingClientRect(data => {
        if (data) {
          this.starWidth = data.width;
        }
      }).exec();
    },
    
    // 触摸开始
    onTouchStart(e) {
      if (this.disabled || !this.swipeable) return;
      
      this.isSwiping = true;
      this.startX = e.touches[0].clientX;
      this.touchId = Date.now();
    },
    
    // 触摸移动
    onTouchMove(e) {
      if (this.disabled || !this.swipeable || !this.isSwiping) return;
      
      const currentX = e.touches[0].clientX;
      const deltaX = currentX - this.startX;
      
      // 如果没有星星宽度数据，则返回
      if (!this.starWidth) return;
      
      // 计算移动的距离对应的星星数量
      let starDelta = deltaX / this.starWidth;
      
      // 根据移动方向计算新评分
      let newValue = this.currentValue;
      
      if (starDelta > 0) {
        // 向右滑动，增加评分
        newValue = Math.min(this.count, this.currentValue + starDelta);
      } else if (starDelta < 0) {
        // 向左滑动，减少评分
        newValue = Math.max(0, this.currentValue + starDelta);
      }
      
      // 如果不允许半星，则取整
      if (!this.allowHalf) {
        newValue = Math.round(newValue);
      } else {
        // 允许半星时，保留一位小数
        newValue = Math.round(newValue * 2) / 2;
      }
      
      // 限制范围
      newValue = Math.max(0, Math.min(newValue, this.count));
      
      // 更新值
      if (newValue !== this.currentValue) {
        this.currentValue = newValue;
        
        // 节流触发事件
        if (this.touchId) {
          clearTimeout(this.touchId);
          this.touchId = setTimeout(() => {
            this.$emit('input', this.currentValue);
            this.$emit('change', this.currentValue);
          }, 50);
        }
      }
    },
    
    // 触摸结束
    onTouchEnd(e) {
      if (this.disabled || !this.swipeable) return;
      
      this.isSwiping = false;
      
      // 触发最终事件
      this.$emit('input', this.currentValue);
      this.$emit('change', this.currentValue);
      
      // 添加动画效果
      if (this.animation) {
        this.animateAllStars();
      }
      
      if (this.touchId) {
        clearTimeout(this.touchId);
        this.touchId = null;
      }
    },
    
    // 处理星星点击
    handleClick(index) {
      if (this.disabled) return;
      
      const starIndex = index + 1;
      let newValue;
      
      if (this.allowHalf) {
        // 如果允许半星，点击时切换 0.5 的增量
        const currentStarValue = this.currentValue;
        if (currentStarValue >= starIndex) {
          // 如果点击已选中的星星，则减0.5
          newValue = starIndex - 0.5;
        } else if (currentStarValue >= starIndex - 0.5) {
          // 如果点击半星，则设为全星
          newValue = starIndex;
        } else {
          // 如果点击未选中的星星，则设为半星
          newValue = starIndex - 0.5;
        }
      } else {
        // 如果不允许半星，则直接设为整星
        newValue = starIndex;
      }
      
      // 限制在0到count之间
      newValue = Math.max(0, Math.min(newValue, this.count));
      
      // 更新值
      this.currentValue = newValue;
      
      // 触发动画
      if (this.animation) {
        this.animateStar(index);
      }
      
      // 触发事件
      this.$emit('input', newValue);
      this.$emit('change', newValue);
    },
    
    // 星星点击动画
    animateStar(index) {
      const stars = this.$el.querySelectorAll('.star-container');
      if (stars && stars[index]) {
        stars[index].classList.add('star-animate');
        setTimeout(() => {
          stars[index].classList.remove('star-animate');
        }, 300);
      }
    },
    
    // 所有星星动画
    animateAllStars() {
      const stars = this.$el.querySelectorAll('.star-container');
      if (stars) {
        stars.forEach((star, index) => {
          if (this.currentValue > index) {
            setTimeout(() => {
              star.classList.add('star-animate');
              setTimeout(() => {
                star.classList.remove('star-animate');
              }, 300);
            }, index * 50);
          }
        });
      }
    },
    
    // 设置评分（可以从外部调用）
    setRating(value) {
      if (this.disabled) return;
      
      let newValue = parseFloat(value);
      if (isNaN(newValue)) return;
      
      // 限制范围
      newValue = Math.max(0, Math.min(newValue, this.count));
      
      // 如果不允许半星，则四舍五入到整数
      if (!this.allowHalf) {
        newValue = Math.round(newValue);
      } else {
        // 允许半星时，保留一位小数
        newValue = Math.round(newValue * 2) / 2;
      }
      
      this.currentValue = newValue;
      this.$emit('input', newValue);
      this.$emit('change', newValue);
      
      // 触发动画
      if (this.animation) {
        this.animateAllStars();
      }
    },
    
    // 重置评分
    reset() {
      this.currentValue = 0;
      this.$emit('input', 0);
      this.$emit('change', 0);
    }
  }
}
</script>

<style lang="scss" scoped>
.star-rating {
  display: inline-flex;
  align-items: center;
  font-size: 0;
  touch-action: pan-x;
  user-select: none;
  
  .star-container {
    position: relative;
    display: inline-block;
    width: 56rpx;
    height: 56rpx;
    // margin-right: 8rpx;
    transition: transform 0.3s ease;
    
    &:last-child {
      margin-right: 0;
    }
    
    &.star-animate {
      animation: starPulse 0.3s ease;
    }
    
    .star-background {
      position: absolute;
      top: 0;
      left: 0;
      z-index: 1;
    }
    
    .star-foreground {
      position: absolute;
      top: 0;
      left: 0;
      z-index: 2;
      overflow: hidden;
      height: 56rpx;
    }
  }
  
  .score-text {
    margin-left: 16rpx;
    font-size: 28rpx;
    color: #f0ad4e;
    font-weight: 500;
  }
}

// 动画效果
@keyframes starPulse {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.2);
  }
  100% {
    transform: scale(1);
  }
}

// 设置不同大小的星星
.star-rating.size-small {
  .star-container {
    width: 32rpx;
    height: 32rpx;
    margin-right: 4rpx;
    
    .star-foreground {
      height: 32rpx;
    }
  }
}

.star-rating.size-large {
  .star-container {
    width: 80rpx;
    height: 80rpx;
    margin-right: 12rpx;
    
    .star-foreground {
      height: 80rpx;
    }
  }
}

// 禁用状态
.star-rating.disabled {
  opacity: 0.6;
  
  .star-container {
    cursor: not-allowed;
  }
}
</style>