<script setup>
import { computed, ref, watch } from "vue";
import { useNamespace, useLocale } from "@yh-ui/hooks";
import { useConfig } from "@yh-ui/hooks";
import { useComponentTheme } from "@yh-ui/theme";
import { rateProps, rateEmits } from "./rate";
defineOptions({
  name: "YhRate"
});
const props = defineProps(rateProps);
const emit = defineEmits(rateEmits);
const ns = useNamespace("rate");
const { tRaw } = useLocale();
const { themeStyle } = useComponentTheme(
  "rate",
  computed(() => props.themeOverrides)
);
const { globalSize } = useConfig();
const currentValue = ref(props.modelValue);
const hoverIndex = ref(-1);
const isPointerAtLeftHalf = ref(props.modelValue !== Math.floor(props.modelValue));
watch(
  () => props.modelValue,
  (val) => {
    currentValue.value = val;
    isPointerAtLeftHalf.value = val !== Math.floor(val);
  },
  { immediate: true }
);
const activeColor = computed(() => {
  if (typeof props.colors === "string") return props.colors;
  if (Array.isArray(props.colors)) {
    const v = currentValue.value;
    if (v <= 2) return props.colors[0] || "#F7BA2A";
    if (v <= 4) return props.colors[1] || "#F7BA2A";
    return props.colors[2] || "#F7BA2A";
  }
  return "#F7BA2A";
});
const voidColorValue = computed(() => props.disabled ? props.disabledVoidColor : props.voidColor);
const getStarWidth = (item) => {
  if (item <= Math.floor(currentValue.value)) return "100%";
  if (item === Math.ceil(currentValue.value) && currentValue.value % 1 !== 0) {
    return currentValue.value % 1 * 100 + "%";
  }
  return "0%";
};
const handleMouseMove = (item, e) => {
  if (props.disabled) return;
  hoverIndex.value = item;
  if (props.allowHalf) {
    const target = e.currentTarget;
    const rect = target.getBoundingClientRect();
    isPointerAtLeftHalf.value = (e.clientX - rect.left) * 2 <= rect.width;
    currentValue.value = isPointerAtLeftHalf.value ? item - 0.5 : item;
  } else {
    currentValue.value = item;
  }
};
const handleMouseLeave = () => {
  if (props.disabled) return;
  currentValue.value = props.modelValue;
  hoverIndex.value = -1;
  isPointerAtLeftHalf.value = props.modelValue !== Math.floor(props.modelValue);
};
const handleItemClick = (item) => {
  if (props.disabled) return;
  let val = props.allowHalf && isPointerAtLeftHalf.value ? item - 0.5 : item;
  if (props.clearable && val === props.modelValue) val = 0;
  emit("update:modelValue", val);
  emit("change", val);
};
const rateText = computed(() => {
  if (props.showScore) return props.scoreTemplate.replace("{value}", String(currentValue.value));
  if (props.showText) {
    const texts = props.texts.length > 0 ? props.texts : tRaw("rate.texts");
    return texts[Math.ceil(currentValue.value) - 1] || "";
  }
  return "";
});
const actualSize = computed(() => props.size || globalSize.value || "default");
const iconSize = computed(() => ({ large: 24, default: 20, small: 16 })[actualSize.value] || 20);
const starPath = "M512 747.52l-228.16 119.84 43.52-254.08L142.08 434.24l255.04-37.12L512 166.08l114.88 231.04 255.04 37.12-184.64 179.2 43.52 254.08z";
</script>

<template>
  <div
    :class="[ns.b(), ns.m(actualSize), ns.is('disabled', disabled)]"
    :style="themeStyle"
    @mouseleave="handleMouseLeave"
  >
    <div
      v-for="item in max"
      :key="item"
      :class="[ns.e('item'), ns.is('hover', hoverIndex === item)]"
      :style="{
  width: iconSize + 'px',
  height: iconSize + 'px'
}"
      @mousemove="handleMouseMove(item, $event)"
      @click="handleItemClick(item)"
    >
      <slot
        name="icon"
        :index="item"
        :width="getStarWidth(item)"
        :active-color="activeColor"
        :void-color="voidColorValue"
      >
        <!-- 基础层：底色星星 -->
        <svg
          :class="[ns.e('star-icon'), ns.is('void')]"
          :style="{
  color: voidColorValue
}"
          viewBox="0 0 1024 1024"
        >
          <path :d="starPath" fill="currentColor" />
        </svg>

        <!-- 填充层：金色星星（带裁剪） -->
        <div
          :class="ns.e('star-content')"
          :style="{
  width: getStarWidth(item),
  color: activeColor
}"
        >
          <svg
            :class="ns.e('star-icon')"
            :style="{
  width: iconSize + 'px'
}"
            viewBox="0 0 1024 1024"
          >
            <path :d="starPath" fill="currentColor" />
          </svg>
        </div>
      </slot>
    </div>

    <span v-if="showScore || showText" :class="ns.e('text')" :style="{
  color: textColor
}">
      {{ rateText }}
    </span>
  </div>
</template>

<style>
@charset "UTF-8";
/**
 * YH-UI Sass Variables
 * 原具体的 CSS 变量输出规则 (:root, html.dark 等) 已移至 root.scss，以防止各组件样式编译时产生重复的全局变量 CSS 冗余。
 */
.yh-rate {
  --yh-rate-void-color: #c6d1de;
  --yh-rate-fill-color: #f7ba2a;
  --yh-rate-disabled-void-color: #eff2f7;
  --yh-rate-text-color: #1f2d3d;
  --yh-rate-font-size: 14px;
  --yh-rate-icon-margin: 6px;
  display: inline-flex;
  align-items: center;
  line-height: normal;
}
.yh-rate__item {
  position: relative;
  display: inline-block;
  margin-right: var(--yh-rate-icon-margin);
  cursor: pointer;
  vertical-align: middle;
  transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.yh-rate__item:last-child {
  margin-right: 0;
}
.yh-rate__item.is-hover {
  transform: scale(1.15);
}

.yh-rate__star-icon {
  display: block;
  width: 100%;
  height: 100%;
  color: var(--yh-rate-void-color);
}
.yh-rate__star-icon.is-void {
  color: var(--yh-rate-void-color);
}

.yh-rate__star-content {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  overflow: hidden;
  pointer-events: none;
  transition: width 0.1s;
  color: var(--yh-rate-fill-color);
}
.yh-rate__star-content .yh-rate__star-icon {
  height: 100%;
  max-width: none;
  color: inherit;
}

.yh-rate__text {
  margin-left: 10px;
  font-size: var(--yh-rate-font-size);
  color: var(--yh-rate-text-color);
}

.yh-rate.is-disabled {
  opacity: 0.8;
  --yh-rate-void-color: var(--yh-rate-disabled-void-color);
}
.yh-rate.is-disabled .yh-rate__item {
  cursor: not-allowed;
}
.yh-rate.is-disabled .yh-rate__item.is-hover {
  transform: none;
}
</style>
