"use client"

import React, { useRef, useState, useCallback, useEffect, useMemo } from "react"
import { motion, useMotionValue, useSpring, useTransform } from "framer-motion"
import { cn } from "../../lib/utils"
import { Card, CardContent } from "../ui/card"
import { Button } from "../ui/button"
import { Lock, Sparkles } from "lucide-react"
import { useSubscription } from "../../hooks/use-subscription"
import { cva, type VariantProps } from "class-variance-authority"

const hoverCard3DVariants = cva(
  "relative rounded-lg border bg-card text-card-foreground shadow-sm transition-all duration-200",
  {
    variants: {
      variant: {
        subtle: "hover:bg-card/95",
        dramatic: "hover:bg-gradient-to-br hover:from-card hover:to-card/80",
        gaming: "hover:border-primary/50 hover:shadow-lg hover:shadow-primary/25",
        elegant: "hover:border-border/50 hover:bg-gradient-to-br hover:from-card hover:via-card/95 hover:to-card/90",
        neon: "hover:border-primary hover:shadow-[0_0_30px_rgba(var(--primary),0.3)]"
      },
      shadowIntensity: {
        none: "",
        light: "hover:shadow-md",
        medium: "hover:shadow-lg",
        heavy: "hover:shadow-xl",
        extreme: "hover:shadow-2xl"
      },
      glowEffect: {
        none: "",
        subtle: "",
        vibrant: "",
        neon: ""
      }
    },
    defaultVariants: {
      variant: "subtle",
      shadowIntensity: "medium",
      glowEffect: "none"
    }
  }
)

export interface SpringConfig {
  stiffness?: number
  damping?: number
  mass?: number
  velocity?: number
  restSpeed?: number
  restDelta?: number
}

export type OverlayRenderProp = (props: {
  isHovered: boolean
  rotateX: number
  rotateY: number
}) => React.ReactNode

export interface HoverCard3DProps 
  extends React.HTMLAttributes<HTMLDivElement>,
    VariantProps<typeof hoverCard3DVariants> {
  /**
   * The perspective value for 3D transformation
   * @default 1000
   */
  perspective?: number
  
  /**
   * Maximum rotation angle in degrees
   * @default 15
   */
  maxRotation?: number
  
  /**
   * @deprecated Use maxRotation instead
   */
  rotationIntensity?: number
  
  /**
   * Scale factor when hovered
   * @default 1.05
   */
  scale?: number
  
  /**
   * Spring animation configuration
   */
  springConfig?: SpringConfig
  
  /**
   * Animation speed multiplier (0-1)
   * @default 1
   */
  animationSpeed?: number
  
  /**
   * Static or dynamic overlay content
   */
  overlay?: React.ReactNode | OverlayRenderProp
  
  /**
   * Show overlay even when not hovered
   * @default false
   */
  overlayAlwaysVisible?: boolean
  
  /**
   * Glow color (CSS color value)
   */
  glowColor?: string
  
  /**
   * Glow blur amount in pixels
   * @default 20
   */
  glowBlur?: number
  
  /**
   * Glow spread amount
   * @default 1.2
   */
  glowSpread?: number
  
  /**
   * Enable touch support for mobile devices
   * @default true
   */
  enableTouch?: boolean
  
  /**
   * Enable keyboard navigation
   * @default true
   */
  enableKeyboard?: boolean
  
  /**
   * Callback when hover starts
   */
  onHoverStart?: () => void
  
  /**
   * Callback when hover ends
   */
  onHoverEnd?: () => void
  
  /**
   * Callback when rotation changes
   */
  onRotationChange?: (rotateX: number, rotateY: number) => void
  
  /**
   * Animation delay in ms
   * @default 0
   */
  animationDelay?: number
  
  /**
   * ARIA label for accessibility
   */
  ariaLabel?: string
  
  /**
   * Auto focus on mount
   * @default false
   */
  autoFocus?: boolean
  
  /**
   * Control which axes can rotate
   * @default { x: true, y: true }
   */
  rotateAxes?: {
    x?: boolean
    y?: boolean
  }
}

const HoverCard3DInternal = React.forwardRef<HTMLDivElement, HoverCard3DProps>(
  ({ 
    children, 
    className,
    variant,
    shadowIntensity,
    glowEffect,
    perspective = 1000,
    maxRotation = 15,
    rotationIntensity,
    scale = 1.05,
    springConfig = { 
      stiffness: 200, 
      damping: 15,
      mass: 1,
      velocity: 0
    },
    animationSpeed = 1,
    overlay,
    overlayAlwaysVisible = false,
    glowColor = "rgb(var(--primary))",
    glowBlur = 20,
    glowSpread = 1.2,
    enableTouch = true,
    enableKeyboard = true,
    onHoverStart,
    onHoverEnd,
    onRotationChange,
    animationDelay = 0,
    ariaLabel,
    autoFocus = false,
    rotateAxes = { x: true, y: true },
    ...restProps 
  }, ref) => {
    // Filter out drag and animation event handlers to avoid conflicts with Framer Motion
    const { onDrag, onDragStart, onDragEnd, onDragOver, onDrop, onAnimationStart, onAnimationEnd, onAnimationIteration, ...props } = restProps
    const cardRef = useRef<HTMLDivElement>(null)
    const [isHovered, setIsHovered] = useState(false)
    const [isFocused, setIsFocused] = useState(false)
    
    // Use maxRotation, fallback to rotationIntensity for backwards compatibility
    const rotation = maxRotation || rotationIntensity || 15

    const x = useMotionValue(0)
    const y = useMotionValue(0)

    const springX = useSpring(x, {
      ...springConfig,
      stiffness: springConfig.stiffness! * animationSpeed,
      damping: springConfig.damping! / animationSpeed
    })
    const springY = useSpring(y, {
      ...springConfig,
      stiffness: springConfig.stiffness! * animationSpeed,
      damping: springConfig.damping! / animationSpeed
    })

    const rotateX = useTransform(
      springY, 
      [-1, 1], 
      rotateAxes.x ? [rotation, -rotation] : [0, 0]
    )
    const rotateY = useTransform(
      springX, 
      [-1, 1], 
      rotateAxes.y ? [-rotation, rotation] : [0, 0]
    )

    const handleMouseMove = useCallback((e: React.MouseEvent | React.TouchEvent) => {
      if (!cardRef.current) return

      const rect = cardRef.current.getBoundingClientRect()
      const centerX = rect.left + rect.width / 2
      const centerY = rect.top + rect.height / 2
      
      let clientX: number, clientY: number
      
      if ('touches' in e && enableTouch) {
        clientX = e.touches[0].clientX
        clientY = e.touches[0].clientY
      } else if ('clientX' in e) {
        clientX = e.clientX
        clientY = e.clientY
      } else {
        return
      }

      const rotateXValue = (clientY - centerY) / (rect.height / 2)
      const rotateYValue = (clientX - centerX) / (rect.width / 2)

      x.set(rotateYValue)
      y.set(rotateXValue)
      
      if (onRotationChange) {
        onRotationChange(rotateX.get(), rotateY.get())
      }
    }, [enableTouch, x, y, rotateX, rotateY, onRotationChange])

    const handleMouseEnter = useCallback(() => {
      setIsHovered(true)
      onHoverStart?.()
    }, [onHoverStart])

    const handleMouseLeave = useCallback(() => {
      setIsHovered(false)
      x.set(0)
      y.set(0)
      onHoverEnd?.()
    }, [x, y, onHoverEnd])

    const handleKeyDown = useCallback((e: React.KeyboardEvent) => {
      if (!enableKeyboard || !isFocused) return

      const step = 0.1
      let newX = x.get()
      let newY = y.get()

      switch (e.key) {
        case 'ArrowUp':
          newY = Math.max(-0.5, newY - step)
          y.set(newY)
          e.preventDefault()
          break
        case 'ArrowDown':
          newY = Math.min(0.5, newY + step)
          y.set(newY)
          e.preventDefault()
          break
        case 'ArrowLeft':
          newX = Math.max(-0.5, newX - step)
          x.set(newX)
          e.preventDefault()
          break
        case 'ArrowRight':
          newX = Math.min(0.5, newX + step)
          x.set(newX)
          e.preventDefault()
          break
        case 'Enter':
        case ' ':
          setIsHovered(!isHovered)
          if (!isHovered) {
            onHoverStart?.()
          } else {
            onHoverEnd?.()
          }
          e.preventDefault()
          break
        case 'Escape':
          x.set(0)
          y.set(0)
          setIsHovered(false)
          onHoverEnd?.()
          e.preventDefault()
          break
      }
      
      if (onRotationChange) {
        onRotationChange(rotateX.get(), rotateY.get())
      }
    }, [enableKeyboard, isFocused, x, y, isHovered, onHoverStart, onHoverEnd, rotateX, rotateY, onRotationChange])

    useEffect(() => {
      if (autoFocus && cardRef.current) {
        cardRef.current.focus()
      }
    }, [autoFocus])

    const overlayContent = useMemo(() => {
      if (!overlay) return null
      
      if (typeof overlay === 'function') {
        return overlay({
          isHovered,
          rotateX: rotateX.get(),
          rotateY: rotateY.get()
        })
      }
      
      return overlay
    }, [overlay, isHovered, rotateX, rotateY])

    const glowStyle = useMemo(() => {
      if (glowEffect === 'none') return {}
      
      let opacity = 0
      let blur = glowBlur
      let spread = glowSpread
      
      switch (glowEffect) {
        case 'subtle':
          opacity = isHovered ? 0.3 : 0
          break
        case 'vibrant':
          opacity = isHovered ? 0.6 : 0
          blur = glowBlur * 1.5
          break
        case 'neon':
          opacity = isHovered ? 0.8 : 0
          blur = glowBlur * 2
          spread = glowSpread * 1.3
          break
      }
      
      return {
        opacity,
        filter: `blur(${blur}px)`,
        scale: spread,
        backgroundColor: glowColor
      }
    }, [glowEffect, isHovered, glowBlur, glowSpread, glowColor])

    return (
      <div style={{ perspective: `${perspective}px` }}>
        <motion.div
          ref={(node) => {
            cardRef.current = node
            if (typeof ref === "function") {
              ref(node)
            } else if (ref) {
              ref.current = node
            }
          }}
          className={cn(
            hoverCard3DVariants({ variant, shadowIntensity, glowEffect }),
            "focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
            className
          )}
          onMouseMove={handleMouseMove}
          onMouseEnter={handleMouseEnter}
          onMouseLeave={handleMouseLeave}
          onTouchMove={enableTouch ? handleMouseMove : undefined}
          onTouchStart={enableTouch ? handleMouseEnter : undefined}
          onTouchEnd={enableTouch ? handleMouseLeave : undefined}
          onKeyDown={handleKeyDown}
          onFocus={() => setIsFocused(true)}
          onBlur={() => setIsFocused(false)}
          style={{
            transformStyle: "preserve-3d",
            transformOrigin: "center center",
            rotateX: isHovered || isFocused ? rotateX : 0,
            rotateY: isHovered || isFocused ? rotateY : 0,
            scale: isHovered || isFocused ? scale : 1,
          }}
          transition={{ 
            type: "spring",
            stiffness: springConfig.stiffness,
            damping: springConfig.damping,
            duration: 0.15 * (1 / animationSpeed),
            delay: animationDelay / 1000
          }}
          tabIndex={enableKeyboard ? 0 : undefined}
          role={enableKeyboard ? "button" : undefined}
          aria-label={ariaLabel}
          {...props}
        >
        <motion.div
          className="relative z-10"
          animate={{
            z: isHovered || isFocused ? 20 : 0,
          }}
          transition={{ duration: 0.2 * (1 / animationSpeed) }}
        >
          {children}
        </motion.div>

        {/* Overlay */}
        {overlayContent && (
          <motion.div
            className="absolute inset-0 rounded-lg pointer-events-none z-20"
            animate={{
              opacity: overlayAlwaysVisible ? 1 : (isHovered || isFocused ? 1 : 0),
            }}
            transition={{ duration: 0.3 * (1 / animationSpeed) }}
          >
            {overlayContent}
          </motion.div>
        )}

        {/* Gradient overlay */}
        {variant !== 'subtle' && (
          <motion.div
            className={cn(
              "absolute inset-0 rounded-lg pointer-events-none",
              variant === 'dramatic' && "bg-gradient-to-br from-white/10 via-transparent to-black/10",
              variant === 'gaming' && "bg-gradient-to-br from-primary/10 via-transparent to-primary/5",
              variant === 'elegant' && "bg-gradient-to-br from-white/5 via-transparent to-black/5",
              variant === 'neon' && "bg-gradient-to-br from-primary/20 via-transparent to-primary/10"
            )}
            animate={{
              opacity: isHovered || isFocused ? 1 : 0,
            }}
            transition={{ duration: 0.3 * (1 / animationSpeed) }}
          />
        )}

        {/* Glow effect */}
        {glowEffect !== 'none' && (
          <motion.div
            className="absolute inset-0 rounded-lg pointer-events-none"
            animate={glowStyle}
            transition={{ duration: 0.3 * (1 / animationSpeed) }}
            style={{ zIndex: -1 }}
          />
        )}
      </motion.div>
      </div>
    )
  }
)

HoverCard3DInternal.displayName = "HoverCard3DInternal"

export const HoverCard3D = React.forwardRef<HTMLDivElement, HoverCard3DProps>(
  (props, ref) => {
    // Pro package - always show component
    const { hasProAccess, isLoading } = useSubscription()
    
    // Show upgrade prompt if no pro access
    if (!isLoading && !hasProAccess) {
      return (
        <Card className={cn("w-fit", props.className)}>
          <CardContent className="py-6 text-center">
            <div className="space-y-4">
              <div className="rounded-full bg-purple-100 dark:bg-purple-900/30 p-3 w-fit mx-auto">
                <Lock className="h-6 w-6 text-purple-600 dark:text-purple-400" />
              </div>
              <div>
                <h3 className="font-semibold text-sm mb-2">Pro Feature</h3>
                <p className="text-muted-foreground text-xs mb-4">
                  3D Hover Card is available exclusively to MoonUI Pro subscribers.
                </p>
                <a href="/pricing">
                  <Button size="sm">
                    <Sparkles className="mr-2 h-4 w-4" />
                    Upgrade to Pro
                  </Button>
                </a>
              </div>
            </div>
          </CardContent>
        </Card>
      )
    }

    return <HoverCard3DInternal {...props} ref={ref} />
  }
)

HoverCard3D.displayName = "HoverCard3D"

export { hoverCard3DVariants }