// directives/hoverEffects.ts
import { Directive } from 'vue'

export interface HoverOptions {
    type?: 'lift' | 'scale' | 'tilt' | 'glow' | 'rotate' | 'slide-up' | 'slide-down' | 'bounce' | 'shake'
    duration?: number | string
    easing?: string
    intensity?: number // Scale factor for the effect (0.1 = subtle, 1.0 = normal, 2.0 = dramatic)
    transform?: string // Custom transform for hover state
    boxShadow?: string // Custom box shadow for hover state
    backgroundColor?: string // Custom background color for hover state
    borderColor?: string // Custom border color for hover state
    color?: string // Custom text color for hover state
    scale?: number // Custom scale value
    translateY?: number // Custom Y translation in pixels
    translateX?: number // Custom X translation in pixels
    rotateZ?: number // Custom rotation in degrees
    disabled?: boolean // Disable hover effects
}

export type HoverValue = string | HoverOptions

interface HoverElement extends HTMLElement {
    _hoverOptions?: HoverOptions
    _originalStyles?: {
        transition?: string
        transform?: string
        boxShadow?: string
        backgroundColor?: string
        borderColor?: string
        color?: string
    }
    _mouseEnterHandler?: (e: MouseEvent) => void
    _mouseLeaveHandler?: (e: MouseEvent) => void
}

function setupHoverEffects(el: HoverElement, binding: any) {
    // Clean up existing handlers
    if (el._mouseEnterHandler) {
        el.removeEventListener('mouseenter', el._mouseEnterHandler)
        el.removeEventListener('mouseleave', el._mouseLeaveHandler!)
    }

    let options: HoverOptions = {}

    if (typeof binding.value === 'string') {
        options = { type: binding.value }
    } else if (typeof binding.value === 'object') {
        options = { ...binding.value }
    }

    const {
        type = 'lift',
        duration = '0.3s',
        easing = 'ease',
        intensity = 1.0,
        transform,
        boxShadow,
        backgroundColor,
        borderColor,
        color,
        scale,
        translateY,
        translateX,
        rotateZ,
        disabled = false
    } = options

    el._hoverOptions = options

    if (disabled) return

    // Store original styles
    const computedStyle = window.getComputedStyle(el)
    el._originalStyles = {
        transition: computedStyle.transition,
        transform: computedStyle.transform,
        boxShadow: computedStyle.boxShadow,
        backgroundColor: computedStyle.backgroundColor,
        borderColor: computedStyle.borderColor,
        color: computedStyle.color
    }

    // Set base transition
    el.style.transition = `all ${duration} ${easing}`

    // Get hover effects based on type
    const hoverEffects = getHoverEffects(type, intensity, {
        transform,
        boxShadow,
        backgroundColor,
        borderColor,
        color,
        scale,
        translateY,
        translateX,
        rotateZ
    })

    // Mouse enter handler
    el._mouseEnterHandler = (e: MouseEvent) => {
        Object.assign(el.style, hoverEffects.enter)
    }

    // Mouse leave handler
    el._mouseLeaveHandler = (e: MouseEvent) => {
        Object.assign(el.style, hoverEffects.leave)
    }

    el.addEventListener('mouseenter', el._mouseEnterHandler)
    el.addEventListener('mouseleave', el._mouseLeaveHandler)
}

function getHoverEffects(
    type: string,
    intensity: number,
    customValues: Partial<HoverOptions>
) {
    const effects = {
        enter: {} as any,
        leave: {} as any
    }

    // Custom values take precedence
    if (customValues.transform) {
        effects.enter.transform = customValues.transform
        effects.leave.transform = 'none'
        return effects
    }

    // Preset effects
    switch (type) {
        case 'lift':
            effects.enter.transform = `translateY(${customValues.translateY || -8 * intensity}px) scale(${customValues.scale || 1 + 0.02 * intensity})`
            effects.enter.boxShadow = customValues.boxShadow || `0 ${10 * intensity}px ${25 * intensity}px rgba(0,0,0,0.15)`
            break

        case 'scale':
            effects.enter.transform = `scale(${customValues.scale || 1 + 0.05 * intensity})`
            break

        case 'tilt':
            effects.enter.transform = `perspective(1000px) rotateY(${customValues.rotateZ || 5 * intensity}deg) scale(${1 + 0.02 * intensity})`
            break

        case 'glow':
            effects.enter.boxShadow = customValues.boxShadow || `0 0 ${20 * intensity}px rgba(59, 130, 246, 0.5)`
            effects.enter.transform = `scale(${1 + 0.02 * intensity})`
            break

        case 'rotate':
            effects.enter.transform = `rotate(${customValues.rotateZ || 5 * intensity}deg) scale(${1 + 0.02 * intensity})`
            break

        case 'slide-up':
            effects.enter.transform = `translateY(${customValues.translateY || -5 * intensity}px)`
            break

        case 'slide-down':
            effects.enter.transform = `translateY(${customValues.translateY || 5 * intensity}px)`
            break

        case 'bounce':
            effects.enter.transform = `translateY(${-3 * intensity}px) scale(${1 + 0.05 * intensity})`
            effects.enter.transition = `all 0.2s cubic-bezier(0.68, -0.55, 0.265, 1.55)`
            break

        case 'shake':
            effects.enter.animation = `shake-${intensity} 0.5s ease-in-out`
            break
    }

    // Add custom color effects
    if (customValues.backgroundColor) {
        effects.enter.backgroundColor = customValues.backgroundColor
    }
    if (customValues.borderColor) {
        effects.enter.borderColor = customValues.borderColor
    }
    if (customValues.color) {
        effects.enter.color = customValues.color
    }

    // Leave effects (return to original)
    effects.leave.transform = 'none'
    effects.leave.boxShadow = ''
    effects.leave.backgroundColor = ''
    effects.leave.borderColor = ''
    effects.leave.color = ''
    effects.leave.animation = ''

    return effects
}

export const hoverEffects: Directive = {
    mounted(el: HoverElement, binding) {
        setupHoverEffects(el, binding)
    },

    updated(el: HoverElement, binding) {
        if (JSON.stringify(binding.value) !== JSON.stringify(binding.oldValue)) {
            setupHoverEffects(el, binding)
        }
    },

    unmounted(el: HoverElement) {
        if (el._mouseEnterHandler) {
            el.removeEventListener('mouseenter', el._mouseEnterHandler)
            el.removeEventListener('mouseleave', el._mouseLeaveHandler!)
        }
    }
}

// Add shake keyframes to document if not already added
if (typeof window !== 'undefined') {
    const addShakeKeyframes = () => {
        if (document.querySelector('#hover-directive-styles')) return

        const style = document.createElement('style')
        style.id = 'hover-directive-styles'
        style.innerHTML = `
      @keyframes shake-1 {
        0%, 100% { transform: translateX(0); }
        25% { transform: translateX(-2px); }
        75% { transform: translateX(2px); }
      }
      @keyframes shake-2 {
        0%, 100% { transform: translateX(0); }
        25% { transform: translateX(-5px); }
        75% { transform: translateX(5px); }
      }
    `
        document.head.appendChild(style)
    }

    // Add styles when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', addShakeKeyframes)
    } else {
        addShakeKeyframes()
    }
}
