<script setup>
import { computed, onMounted, ref, watch } from "vue";
import { useNamespace, useLocale } from "@yh-ui/hooks";
import { useComponentTheme } from "@yh-ui/theme";
defineOptions({
  name: "YhMessage"
});
const props = defineProps({
  message: { type: [String, Object], required: false },
  type: { type: null, required: false, default: "info" },
  icon: { type: [String, Object], required: false },
  showClose: { type: Boolean, required: false, default: false },
  duration: { type: Number, required: false, default: 3e3 },
  offset: { type: Number, required: false, default: 20 },
  id: { type: String, required: false },
  dangerouslyUseHTMLString: { type: Boolean, required: false, default: false },
  center: { type: Boolean, required: false, default: false },
  onClose: { type: Function, required: false },
  zIndex: { type: Number, required: false },
  customClass: { type: String, required: false },
  grouping: { type: Boolean, required: false, default: false },
  repeatNum: { type: Number, required: false, default: 1 },
  placement: { type: null, required: false, default: "top" },
  themeOverrides: { type: null, required: false }
});
const emit = defineEmits(["destroy"]);
const ns = useNamespace("message");
const { t } = useLocale();
const { themeStyle } = useComponentTheme(
  "message",
  computed(() => props.themeOverrides)
);
const visible = ref(false);
let timer = null;
const messageClasses = computed(() => [
  ns.b(),
  ns.m(props.type),
  ns.m(props.placement),
  ns.is("center", props.center),
  ns.is("closable", props.showClose),
  props.customClass
]);
const messageStyles = computed(() => {
  const styles = {
    zIndex: props.zIndex
  };
  if (props.placement?.startsWith("top")) {
    styles.top = `${props.offset}px`;
  } else {
    styles.bottom = `${props.offset}px`;
  }
  return styles;
});
const showRepeatNum = computed(() => props.grouping && (props.repeatNum || 1) > 1);
const startTimer = () => {
  if (props.duration > 0) {
    timer = setTimeout(() => {
      close();
    }, props.duration);
  }
};
const clearTimer = () => {
  if (timer) {
    clearTimeout(timer);
    timer = null;
  }
};
const close = () => {
  if (!visible.value) return;
  visible.value = false;
  props.onClose?.();
};
const handleMouseEnter = () => {
  clearTimer();
};
const handleMouseLeave = () => {
  startTimer();
};
const onDestroy = () => {
  emit("destroy");
};
watch(
  () => props.duration,
  () => {
    clearTimer();
    startTimer();
  }
);
watch(
  () => props.repeatNum,
  () => {
    clearTimer();
    startTimer();
  }
);
onMounted(() => {
  visible.value = true;
  startTimer();
});
defineExpose({
  visible,
  close
});
</script>

<template>
  <transition :name="ns.b('fade')" @after-leave="onDestroy">
    <div
      v-show="visible"
      :class="messageClasses"
      :style="[themeStyle, messageStyles]"
      role="alert"
      @mouseenter="handleMouseEnter"
      @mouseleave="handleMouseLeave"
    >
      <!-- 图标 -->
      <div :class="ns.e('icon')">
        <slot name="icon">
          <!-- 这里可以根据 iconName 渲染对应的图标 SVG -->
          <span :class="ns.em('icon', type)">
            <svg
              v-if="type === 'success'"
              viewBox="0 0 1024 1024"
              xmlns="http://www.w3.org/2000/svg"
            >
              <path
                fill="currentColor"
                d="M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm-55.808 536.384-99.52-99.584a38.4 38.4 0 1 0-54.336 54.336l126.72 126.72a38.272 38.272 0 0 0 54.336 0l262.4-262.464a38.4 38.4 0 1 0-54.272-54.336L456.192 600.384z"
              />
            </svg>
            <svg
              v-else-if="type === 'warning'"
              viewBox="0 0 1024 1024"
              xmlns="http://www.w3.org/2000/svg"
            >
              <path
                fill="currentColor"
                d="M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm0 192a58.432 58.432 0 0 0-58.24 63.744l23.36 256.384a35.072 35.072 0 0 0 69.76 0l23.296-256.384A58.432 58.432 0 0 0 512 256zm0 512a51.2 51.2 0 1 0 0-102.4 51.2 51.2 0 0 0 0 102.4z"
              />
            </svg>
            <svg
              v-else-if="type === 'info'"
              viewBox="0 0 1024 1024"
              xmlns="http://www.w3.org/2000/svg"
            >
              <path
                fill="currentColor"
                d="M512 64a448 448 0 1 1 0 896.064A448 448 0 0 1 512 64zm67.2 275.072c0-23.232-8.832-44.8-23.68-59.648-14.976-14.848-36.48-23.68-59.648-23.68-23.168 0-44.672 8.832-59.648 23.68-14.848 14.848-23.68 36.416-23.68 59.648 0 23.168 8.832 44.672 23.68 59.648 14.976 14.976 36.48 23.808 59.648 23.808 23.168 0 44.672-8.832 59.648-23.808 14.848-14.976 23.68-36.48 23.68-59.648zm-12.8 166.4h-128a32 32 0 0 0-32 32v256a32 32 0 0 0 32 32h128a32 32 0 0 0 32-32v-256a32 32 0 0 0-32-32z"
              />
            </svg>
            <svg
              v-else-if="type === 'error'"
              viewBox="0 0 1024 1024"
              xmlns="http://www.w3.org/2000/svg"
            >
              <path
                fill="currentColor"
                d="M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm0 393.664L407.936 353.6a38.4 38.4 0 1 0-54.336 54.336L457.664 512 353.6 616.064a38.4 38.4 0 1 0 54.336 54.336L512 566.336 616.064 670.4a38.4 38.4 0 1 0 54.336-54.336L566.336 512 670.4 407.936a38.4 38.4 0 1 0-54.336-54.336L512 457.664z"
              />
            </svg>
          </span>
        </slot>
      </div>

      <!-- 内容 -->
      <div :class="ns.e('content')">
        <slot>
          <p v-if="!dangerouslyUseHTMLString" :class="ns.e('text')">
            {{ message }}
          </p>
          <!-- eslint-disable vue/no-v-html -->
          <p v-else :class="ns.e('text')" v-html="message"></p>
          <!-- eslint-enable vue/no-v-html -->
        </slot>

        <!-- 重复次数标记 -->
        <div v-if="showRepeatNum" :class="ns.e('badge')">
          {{ repeatNum }}
        </div>
      </div>

      <!-- 关闭按钮 -->
      <div v-if="showClose" :class="ns.e('close')" :aria-label="t('message.close')" @click="close">
        <svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
          <path
            fill="currentColor"
            d="M764.288 214.592 512 466.88 259.712 214.592a31.936 31.936 0 0 0-45.12 45.12L466.752 512 214.528 764.224a31.936 31.936 0 1 0 45.12 45.184L512 557.184l252.288 252.288a31.936 31.936 0 0 0 45.12-45.12L557.12 512.064l252.288-252.352a31.936 31.936 0 1 0-45.12-45.184z"
          />
        </svg>
      </div>
    </div>
  </transition>
</template>

<style>
@charset "UTF-8";
/**
 * YH-UI Sass Variables
 * 原具体的 CSS 变量输出规则 (:root, html.dark 等) 已移至 root.scss，以防止各组件样式编译时产生重复的全局变量 CSS 冗余。
 */
.yh-message {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  padding: 15px 20px;
  background-color: var(--yh-message-bg-color);
  border: 1px solid var(--yh-message-border-color);
  border-radius: var(--yh-border-radius-base);
  box-shadow: var(--yh-message-shadow);
  transition: all var(--yh-duration-base) var(--yh-timing-ease-in-out);
  overflow: hidden;
  pointer-events: auto; /* 改为 auto，更符合常规交互 */
  min-width: 380px;
  box-sizing: border-box;
  z-index: var(--yh-z-index-message, 3000);
}
.yh-message--top-left {
  left: 16px;
  transform: none;
}

.yh-message--top-right {
  left: auto;
  right: 16px;
  transform: none;
}

.yh-message--bottom-left {
  left: 16px;
  transform: none;
}

.yh-message--bottom-right {
  left: auto;
  right: 16px;
  transform: none;
}

.yh-message.is-center {
  justify-content: center;
  text-align: center;
}
.yh-message.is-center .yh-message__content {
  justify-content: center;
}
.yh-message.is-center .yh-message__text {
  text-align: center;
}

.yh-message.is-closable {
  padding-right: 42px;
}

.yh-message__icon {
  margin-right: 10px;
  font-size: 18px;
  line-height: 1;
}
.yh-message__icon svg {
  width: 18px;
  height: 18px;
  vertical-align: middle;
}
.yh-message__icon--success {
  color: var(--yh-color-success);
}

.yh-message__icon--warning {
  color: var(--yh-color-warning);
}

.yh-message__icon--info {
  color: var(--yh-color-info);
}

.yh-message__icon--error {
  color: var(--yh-color-danger);
}

.yh-message__content {
  flex: 1;
  display: flex;
  align-items: center;
  padding: 0;
  font-size: var(--yh-font-size-base);
  line-height: 1.5;
}

.yh-message__text {
  margin: 0;
  color: var(--yh-message-text-color);
  word-break: break-word;
}

.yh-message__badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 6px;
  margin-left: 8px;
  font-size: 12px;
  line-height: 18px;
  color: #ffffff;
  background-color: var(--yh-color-danger);
  border-radius: 10px;
  font-weight: var(--yh-font-weight-semibold);
}

.yh-message__close {
  position: absolute;
  top: 50%;
  right: 15px;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  cursor: pointer;
  color: var(--yh-message-close-color);
  transition: color var(--yh-duration-fast);
}
.yh-message__close:hover {
  color: var(--yh-message-close-hover-color);
}
.yh-message__close svg {
  width: 100%;
  height: 100%;
}

.yh-message--success {
  background-color: var(--yh-color-success-light-9);
  border-color: var(--yh-color-success-light-7);
}
.yh-message--success .yh-message__text {
  color: var(--yh-color-success-dark-2);
}

.yh-message--warning {
  background-color: var(--yh-color-warning-light-9);
  border-color: var(--yh-color-warning-light-7);
}
.yh-message--warning .yh-message__text {
  color: var(--yh-color-warning-dark-2);
}

.yh-message--info {
  background-color: var(--yh-color-info-light-9);
  border-color: var(--yh-color-info-light-7);
}
.yh-message--info .yh-message__text {
  color: var(--yh-color-info-dark-2);
}

.yh-message--error {
  background-color: var(--yh-color-danger-light-9);
  border-color: var(--yh-color-danger-light-7);
}
.yh-message--error .yh-message__text {
  color: var(--yh-color-danger-dark-2);
}

.yh-message-fade-enter-active {
  transition: all var(--yh-duration-base) var(--yh-timing-ease-out);
}
.yh-message-fade-leave-active {
  transition: all var(--yh-duration-base) var(--yh-timing-ease-in);
}
.yh-message-fade-enter-from {
  opacity: 0;
  transform: translateX(-50%) translateY(-20px);
}
.yh-message-fade-leave-to {
  opacity: 0;
  transform: translateX(-50%) translateY(-20px);
}
</style>
