const defaultOptions = {
  size: 300,
  color1: 'rgba(128, 119, 255, 0.5)',
  color2: 'rgba(231, 76, 255, 0.5)',
  angle: 148,
  opacity: 0.5,
  blur: 50,
  duration: 0.15
}

const createGlowElement = (container, options) => {
  const glow = document.createElement('div')
  const gradient = `conic-gradient(from ${options.angle}deg, ${options.color1} 0%, ${options.color2} 50%, ${options.color1} 100%)`
  glow.style.cssText = `
    position: absolute;
    left: 0;
    top: 0;
    width: ${options.size}px;
    height: ${options.size}px;
    background: ${gradient};
    border-radius: 50%;
    pointer-events: none;
    opacity: 0;
    transition: opacity ${options.duration}s ease;
    will-change: transform;
    filter: blur(${options.blur}px) drop-shadow(0 4px 4px rgba(0,0,0,0.25));
    z-index: 1;
  `
  container.style.position = 'relative'
  container.style.overflow = 'hidden'
  container.appendChild(glow)
  return glow
}

const updateGlowPosition = (glow, x, y, options) => {
  glow.style.transform = `translate(${x - options.size / 2}px, ${y - options.size / 2}px)`
}

const mouseGlowDirective = {
  mounted(el, binding) {
    const options = { ...defaultOptions, ...binding.value }
    const glow = createGlowElement(el, options)
    let animationFrameId = null
    let isVisible = false

    const handleMouseMove = (e) => {
      if (animationFrameId !== null) {
        cancelAnimationFrame(animationFrameId)
      }

      animationFrameId = requestAnimationFrame(() => {
        const rect = el.getBoundingClientRect()
        const x = e.clientX - rect.left
        const y = e.clientY - rect.top
        updateGlowPosition(glow, x, y, options)
        animationFrameId = null
      })
    }

    const handleMouseEnter = () => {
      if (!isVisible) {
        glow.style.opacity = options.opacity?.toString() || defaultOptions.opacity.toString()
        isVisible = true
      }
    }

    const handleMouseLeave = () => {
      if (isVisible) {
        glow.style.opacity = '0'
        isVisible = false
      }
    }

    el.addEventListener('mousemove', handleMouseMove, { passive: true })
    el.addEventListener('mouseenter', handleMouseEnter, { passive: true })
    el.addEventListener('mouseleave', handleMouseLeave, { passive: true })

    el._mouseGlowDirective = {
      glow,
      handleMouseMove,
      handleMouseEnter,
      handleMouseLeave,
      animationFrameId: () => animationFrameId
    }
  },

  updated(el, binding) {
    const directiveData = el._mouseGlowDirective
    if (directiveData) {
      const options = { ...defaultOptions, ...binding.value }
      const { glow } = directiveData

      const gradient = `conic-gradient(from ${options.angle}deg, ${options.color1} 0%, ${options.color2} 50%, ${options.color1} 100%)`

      glow.style.width = `${options.size}px`
      glow.style.height = `${options.size}px`
      glow.style.background = gradient
      glow.style.filter = `blur(${options.blur}px) drop-shadow(0 4px 4px rgba(0,0,0,0.25))`
      glow.style.transition = `opacity ${options.duration}s ease`
    }
  },

  unmounted(el) {
    const directiveData = el._mouseGlowDirective
    if (directiveData) {
      const { glow, handleMouseMove, handleMouseEnter, handleMouseLeave, animationFrameId } = directiveData

      const frameId = animationFrameId()
      if (frameId !== null) {
        cancelAnimationFrame(frameId)
      }

      el.removeEventListener('mousemove', handleMouseMove)
      el.removeEventListener('mouseenter', handleMouseEnter)
      el.removeEventListener('mouseleave', handleMouseLeave)

      glow.remove()
      delete el._mouseGlowDirective
    }
  }
}

export default mouseGlowDirective
