<template>
  <transition :name="transitionName">
    <view v-if="visible" class="hy-popup-wrapper" :class="positionClass" @click="handleOverlayClick">
      <view class="hy-popup-overlay" :style="{ backgroundColor: overlayBackgroundColor }"></view>
      <view
        class="hy-popup-content"
        :class="[customClass, { 'hy-popup-no-padding': noPadding }]"
        @click.stop
        :style="{
          width: width,
          maxWidth: maxWidth,
          backgroundColor: backgroundColor,
          borderRadius: borderRadius + 'rpx'
        }"
      >
        <!-- 自定义头部插槽 -->
        <slot name="header"></slot>

        <!-- 自定义内容插槽 -->
        <slot></slot>

        <!-- 关闭按钮 -->
        <view class="close-wrap" v-if="showClose" @click="handleClose">
          <u-icon name="close-circle" size="40" color="#999"></u-icon>
          <text>关闭</text>
        </view>
      </view>
    </view>
  </transition>
</template>

<script lang="ts" setup>
import { computed } from 'vue'

// 定义动画类型
const AnimationType = ['scale', 'slide-up', 'slide-down', 'slide-left', 'slide-right', 'fade'] as const
// eslint-disable-next-line no-redeclare
type AnimationType = (typeof AnimationType)[number]

// 定义弹窗位置
const PositionType = ['center', 'top', 'bottom', 'left', 'right'] as const
// eslint-disable-next-line no-redeclare
type PositionType = (typeof PositionType)[number]

// 定义组件的Props
interface Props {
  // v-model绑定值
  modelValue: boolean
  // 是否显示关闭按钮
  showClose?: boolean
  // 点击遮罩层是否可以关闭
  closeOnClickOverlay?: boolean
  // 按ESC键是否可以关闭（仅Web环境）
  closeOnPressEscape?: boolean
  // 自定义class
  customClass?: string
  // 动画类型
  animationType?: AnimationType
  // 弹窗位置
  position?: PositionType
  // 宽度
  width?: string | number
  // 最大宽度
  maxWidth?: string | number
  // 背景色
  backgroundColor?: string
  // 遮罩背景色
  overlayBackgroundColor?: string
  // 圆角大小
  borderRadius?: number
  // 关闭按钮颜色
  closeIconColor?: string
  // 关闭按钮样式
  closeButtonStyle?: object
  // 是否无内边距
  noPadding?: boolean
  // 是否显示遮罩
  showOverlay?: boolean
  // 是否显示已领取遮罩
  showUsedReceived?: boolean
}

// 使用默认值定义Props
const props = withDefaults(defineProps<Props>(), {
  showClose: false,
  closeOnClickOverlay: true,
  closeOnPressEscape: true,
  customClass: '',
  animationType: 'scale',
  position: 'center',
  width: '80%',
  maxWidth: '750rpx',
  backgroundColor: 'transparent',
  overlayBackgroundColor: 'rgba(0, 0, 0, 0.8)',
  borderRadius: 24,
  closeIconColor: '#fff',
  closeButtonStyle: () => ({}),
  noPadding: false,
  showOverlay: true,
  showUsedReceived: false
})

// 定义组件的Events
const emit = defineEmits<{
  'update:modelValue': [value: boolean]
  close: []
  opened: []
  closed: []
}>()

// 处理v-model的双向绑定
const visible = computed({
  get: () => props.modelValue,
  set: (value) => {
    emit('update:modelValue', value)
    if (value) {
      emit('opened')
    } else {
      emit('closed')
    }
  }
})

// 计算动画名称
const transitionName = computed(() => {
  return `hy-popup-${props.animationType}`
})

// 计算位置类名
const positionClass = computed(() => {
  return `hy-popup-position-${props.position}`
})

// 点击关闭按钮
const handleClose = () => {
  visible.value = false
  emit('close')
}

// 点击遮罩层
const handleOverlayClick = () => {
  if (props.closeOnClickOverlay) {
    handleClose()
  }
}
</script>

<style lang="scss" scoped>
.hy-popup-wrapper {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 999;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
}
.close-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 20rpx;
  image {
    width: 62rpx;
    height: 62rpx;
    margin: 46rpx 0 8rpx 0;
  }
  text {
    font-size: 30rpx;
    color: rgba(255, 255, 255, 0.76);
  }
}
// 位置控制
.hy-popup-position-center {
  align-items: center;
  justify-content: center;
}

.hy-popup-position-top {
  align-items: flex-start;
  justify-content: center;
}

.hy-popup-position-bottom {
  align-items: flex-end;
  justify-content: center;
}

.hy-popup-position-left {
  align-items: center;
  justify-content: flex-start;
}

.hy-popup-position-right {
  align-items: center;
  justify-content: flex-end;
}

.hy-popup-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.hy-popup-content {
  position: relative;
  box-sizing: border-box;
  overflow: hidden;
  padding: 30rpx;
}

.hy-popup-no-padding {
  padding: 0;
}

.hy-popup-close {
  position: absolute;
  top: 20rpx;
  right: 20rpx;
  width: 60rpx;
  height: 60rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background-color: rgba(0, 0, 0, 0.1);
  z-index: 10;
}

.hy-popup-close-icon {
  font-size: 40rpx;
  font-weight: bold;
}

// 通用过渡设置
$transition-duration: 0.3s;
$transition-timing: ease;

// Scale 动画
.hy-popup-scale-enter-active,
.hy-popup-scale-leave-active {
  transition: all $transition-duration $transition-timing;
}

.hy-popup-scale-enter-from .hy-popup-overlay,
.hy-popup-scale-leave-to .hy-popup-overlay {
  opacity: 0;
}

.hy-popup-scale-enter-from .hy-popup-content,
.hy-popup-scale-leave-to .hy-popup-content {
  transform: scale(0.8);
  opacity: 0;
}

// Slide-up 动画
.hy-popup-slide-up-enter-active,
.hy-popup-slide-up-leave-active {
  transition: all $transition-duration $transition-timing;
}

.hy-popup-slide-up-enter-from .hy-popup-overlay,
.hy-popup-slide-up-leave-to .hy-popup-overlay {
  opacity: 0;
}

.hy-popup-slide-up-enter-from .hy-popup-content {
  transform: translateY(100%);
  opacity: 0;
}

.hy-popup-slide-up-leave-to .hy-popup-content {
  transform: translateY(100%);
  opacity: 0;
}

// Slide-down 动画
.hy-popup-slide-down-enter-active,
.hy-popup-slide-down-leave-active {
  transition: all $transition-duration $transition-timing;
}

.hy-popup-slide-down-enter-from .hy-popup-overlay,
.hy-popup-slide-down-leave-to .hy-popup-overlay {
  opacity: 0;
}

.hy-popup-slide-down-enter-from .hy-popup-content {
  transform: translateY(-100%);
  opacity: 0;
}

.hy-popup-slide-down-leave-to .hy-popup-content {
  transform: translateY(-100%);
  opacity: 0;
}

// Slide-left 动画
.hy-popup-slide-left-enter-active,
.hy-popup-slide-left-leave-active {
  transition: all $transition-duration $transition-timing;
}

.hy-popup-slide-left-enter-from .hy-popup-overlay,
.hy-popup-slide-left-leave-to .hy-popup-overlay {
  opacity: 0;
}

.hy-popup-slide-left-enter-from .hy-popup-content {
  transform: translateX(-100%);
  opacity: 0;
}

.hy-popup-slide-left-leave-to .hy-popup-content {
  transform: translateX(-100%);
  opacity: 0;
}

// Slide-right 动画
.hy-popup-slide-right-enter-active,
.hy-popup-slide-right-leave-active {
  transition: all $transition-duration $transition-timing;
}

.hy-popup-slide-right-enter-from .hy-popup-overlay,
.hy-popup-slide-right-leave-to .hy-popup-overlay {
  opacity: 0;
}

.hy-popup-slide-right-enter-from .hy-popup-content {
  transform: translateX(100%);
  opacity: 0;
}

.hy-popup-slide-right-leave-to .hy-popup-content {
  transform: translateX(100%);
  opacity: 0;
}

// Fade 动画
.hy-popup-fade-enter-active,
.hy-popup-fade-leave-active {
  transition: all $transition-duration $transition-timing;
}

.hy-popup-fade-enter-from .hy-popup-overlay,
.hy-popup-fade-leave-to .hy-popup-overlay {
  opacity: 0;
}

.hy-popup-fade-enter-from .hy-popup-content,
.hy-popup-fade-leave-to .hy-popup-content {
  opacity: 0;
}
</style>
