<template>
  <div class="custom-popover" ref="popoverRef">
    <div class="popover-trigger" ref="triggerRef" @click.stop="togglePopover">
      <slot name="reference" />
    </div>
    <Teleport to="body">
      <div
        v-if="visible"
        ref="contentRef"
        class="popover-content"
        :class="[placement]"
        :style="contentStyle"
      >
        <slot />
      </div>
    </Teleport>
  </div>
</template>

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

const props = defineProps({
  modelValue: {
    type: Boolean,
    default: false
  },
  placement: {
    type: String,
    default: 'top'
  },
  width: {
    type: [String, Number],
    default: 'auto'
  },
  trigger: {
    type: String,
    default: 'click'
  }
})

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

const popoverRef = ref(null)
const triggerRef = ref(null)
const contentRef = ref(null)
const visible = ref(props.modelValue)
const position = ref({ top: 0, left: 0 })
const popoverId = ref(Math.random().toString(36).substr(2, 9))

if (!window.__currentOpenPopoverId__) {
  window.__currentOpenPopoverId__ = null
}

const contentStyle = computed(() => ({
  width: typeof props.width === 'number' ? `${props.width}px` : props.width,
  ...position.value
}))

const togglePopover = async () => {
  if (visible.value) {
    visible.value = false
    window.__currentOpenPopoverId__ = null
  } else {
    if (window.__currentOpenPopoverId__ && window.__currentOpenPopoverId__ !== popoverId.value) {
      window.dispatchEvent(new CustomEvent('close-other-popovers', { detail: { excludeId: popoverId.value } }))
    }
    if (window.__currentOpenSelectId__) {
      window.dispatchEvent(new CustomEvent('close-other-selects', { detail: { excludeId: null } }))
    }
    visible.value = true
    window.__currentOpenPopoverId__ = popoverId.value
    await nextTick()
    updatePosition()
  }
  emit('update:modelValue', visible.value)
}

const updatePosition = () => {
  if (!triggerRef.value || !contentRef.value) return
  
  const triggerRect = triggerRef.value.getBoundingClientRect()
  const contentRect = contentRef.value.getBoundingClientRect()
  const gap = 25
  
  let top = 0
  let left = 0
  
  switch (props.placement) {
    case 'top':
      top = triggerRect.top - contentRect.height - gap
      left = triggerRect.left + (triggerRect.width - contentRect.width) / 2
      break
    case 'bottom':
      top = triggerRect.bottom + gap
      left = triggerRect.left + (triggerRect.width - contentRect.width) / 2
      break
    case 'left':
      top = triggerRect.top + (triggerRect.height - contentRect.height) / 2
      left = triggerRect.left - contentRect.width - gap
      break
    case 'right':
      top = triggerRect.top + (triggerRect.height - contentRect.height) / 2
      left = triggerRect.right + gap
      break
  }
  
  position.value = {
    top: `${top}px`,
    left: `${left}px`
  }
}

const handleClickOutside = (e) => {
  if (!visible.value) return
  
  const triggerEl = popoverRef.value
  const contentEl = contentRef.value
  
  if (
    triggerEl &&
    !triggerEl.contains(e.target) &&
    contentEl &&
    !contentEl.contains(e.target)
  ) {
    visible.value = false
    window.__currentOpenPopoverId__ = null
    emit('update:modelValue', false)
  }
}

const handleCloseOtherPopovers = (e) => {
  if (e.detail.excludeId !== popoverId.value) {
    visible.value = false
  }
}

const handleCloseOtherSelects = () => {
  visible.value = false
  window.__currentOpenPopoverId__ = null
}

watch(() => props.modelValue, async (val) => {
  visible.value = val
  if (val) {
    await nextTick()
    updatePosition()
  }
})

onMounted(() => {
  document.addEventListener('click', handleClickOutside)
  window.addEventListener('resize', updatePosition)
  window.addEventListener('scroll', updatePosition, true)
  window.addEventListener('close-other-popovers', handleCloseOtherPopovers)
  window.addEventListener('close-other-selects', handleCloseOtherSelects)
})

onBeforeUnmount(() => {
  document.removeEventListener('click', handleClickOutside)
  window.removeEventListener('resize', updatePosition)
  window.removeEventListener('scroll', updatePosition, true)
  window.removeEventListener('close-other-popovers', handleCloseOtherPopovers)
  window.removeEventListener('close-other-selects', handleCloseOtherSelects)
})
</script>

<style scoped>
.custom-popover {
  display: inline-block;
}

.popover-trigger {
  display: inline-block;
}

.popover-content {
  position: fixed;
  background: #ffffff;
  border-radius: 16px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.08);
  border: 1px solid #e8e8e8;
  z-index: 2000;
  animation: popoverFadeIn 0.2s ease;
}

.popover-content.top {
  transform-origin: bottom center;
}

.popover-content.bottom {
  transform-origin: top center;
}

.popover-content.left {
  transform-origin: right center;
}

.popover-content.right {
  transform-origin: left center;
}

@keyframes popoverFadeIn {
  from {
    opacity: 0;
    transform: scale(0.95);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}
</style>
