"use client"

import React, { useRef, useState, useCallback, useEffect } from "react"
import { motion, useMotionValue, useTransform, animate, AnimatePresence } from "framer-motion"
import { cn } from "../../lib/utils"
import { Card, CardContent } from "../ui/card"
import { Button } from "../ui/button"
import { Lock, Sparkles, ZoomIn, ZoomOut, Maximize2, RotateCw, Minimize2 } from "lucide-react"
import { useSubscription } from "../../hooks/use-subscription"

interface PinchZoomProps {
  children: React.ReactNode
  minZoom?: number
  maxZoom?: number
  initialZoom?: number
  className?: string
  contentClassName?: string
  onZoomChange?: (zoom: number) => void
  showControls?: boolean
  showIndicator?: boolean
  doubleTapBehavior?: 'zoom' | 'reset'
  wheelScaling?: boolean
  dragEnabled?: boolean
  zoomStep?: number
  smoothZoom?: boolean
  boundaryConstraints?: boolean
}

const PinchZoomInternal = React.forwardRef<HTMLDivElement, PinchZoomProps>(
  ({
    children,
    minZoom = 0.5,
    maxZoom = 3,
    initialZoom = 1,
    className,
    contentClassName,
    onZoomChange,
    showControls = true,
    showIndicator = true,
    doubleTapBehavior = 'zoom',
    wheelScaling = true,
    dragEnabled = true,
    zoomStep = 0.5,
    smoothZoom = true,
    boundaryConstraints = true,
    ...props
  }, ref) => {
    const containerRef = useRef<HTMLDivElement>(null)
    const contentRef = useRef<HTMLDivElement>(null)
    const [isDragging, setIsDragging] = useState(false)
    const [showZoomIndicator, setShowZoomIndicator] = useState(false)
    const [lastTap, setLastTap] = useState(0)
    const [isHovered, setIsHovered] = useState(false)
    const [isFullscreen, setIsFullscreen] = useState(false)
    
    const scale = useMotionValue(initialZoom)
    const x = useMotionValue(0)
    const y = useMotionValue(0)
    
    const constrainedScale = useTransform(scale, (value) => {
      return Math.min(Math.max(value, minZoom), maxZoom)
    })
    
    // Zoom yüzdesi için transform
    const zoomPercentage = useTransform(scale, (value) => {
      return Math.round(value * 100)
    })
    
    // Sınırları hesapla
    const calculateConstraints = useCallback(() => {
      if (!containerRef.current || !contentRef.current || !boundaryConstraints) return { left: 0, right: 0, top: 0, bottom: 0 }
      
      const containerRect = containerRef.current.getBoundingClientRect()
      const currentScale = scale.get()
      
      const scaledWidth = containerRect.width * currentScale
      const scaledHeight = containerRect.height * currentScale
      
      const maxX = Math.max(0, (scaledWidth - containerRect.width) / 2)
      const maxY = Math.max(0, (scaledHeight - containerRect.height) / 2)
      
      return {
        left: -maxX,
        right: maxX,
        top: -maxY,
        bottom: maxY
      }
    }, [scale, boundaryConstraints])
    
    // Browser zoom'unu engelle (sadece Ctrl/Cmd basılıyken)
    useEffect(() => {
      if (!containerRef.current || !wheelScaling) return
      
      const container = containerRef.current
      const handleWheelPrevent = (e: WheelEvent) => {
        // Sadece component üzerinde ve Ctrl/Cmd basılıyken preventDefault yap
        if (isHovered && wheelScaling && (e.ctrlKey || e.metaKey)) {
          e.preventDefault()
        }
      }
      
      // Passive: false ile event listener ekle
      container.addEventListener('wheel', handleWheelPrevent, { passive: false })
      
      return () => {
        container.removeEventListener('wheel', handleWheelPrevent)
      }
    }, [isHovered, wheelScaling])
    
    const handleWheel = useCallback((event: React.WheelEvent) => {
      if (!wheelScaling) return
      
      // Ctrl (veya Mac'te Cmd) basılı değilse zoom yapma
      if (!event.ctrlKey && !event.metaKey) return
      
      event.preventDefault()
      
      const delta = -event.deltaY / 1000
      const currentScale = scale.get()
      const newScale = Math.min(Math.max(currentScale + delta, minZoom), maxZoom)
      
      // Zoom noktasını hesapla (mouse pozisyonuna göre)
      if (containerRef.current) {
        const rect = containerRef.current.getBoundingClientRect()
        const centerX = (event.clientX - rect.left) / rect.width - 0.5
        const centerY = (event.clientY - rect.top) / rect.height - 0.5
        
        const scaleDiff = newScale - currentScale
        const currentX = x.get()
        const currentY = y.get()
        
        // Zoom noktasına göre pozisyonu ayarla
        const newX = currentX - centerX * rect.width * scaleDiff
        const newY = currentY - centerY * rect.height * scaleDiff
        
        if (smoothZoom) {
          animate(x, newX, { duration: 0.2 })
          animate(y, newY, { duration: 0.2 })
        } else {
          x.set(newX)
          y.set(newY)
        }
      }
      
      if (smoothZoom) {
        animate(scale, newScale, { duration: 0.2 })
      } else {
        scale.set(newScale)
      }
      
      onZoomChange?.(newScale)
      
      // Zoom göstergesini göster
      if (showIndicator) {
        setShowZoomIndicator(true)
        setTimeout(() => setShowZoomIndicator(false), 1500)
      }
    }, [scale, x, y, minZoom, maxZoom, onZoomChange, wheelScaling, smoothZoom, showIndicator])
    
    const handleDoubleClick = useCallback((event: React.MouseEvent) => {
      event.preventDefault()
      
      const currentScale = scale.get()
      let newScale: number
      
      if (doubleTapBehavior === 'reset') {
        newScale = initialZoom
      } else {
        // Zoom to point functionality
        newScale = currentScale > 1 ? 1 : 2
        
        if (newScale > 1 && containerRef.current) {
          const rect = containerRef.current.getBoundingClientRect()
          const centerX = (event.clientX - rect.left) / rect.width - 0.5
          const centerY = (event.clientY - rect.top) / rect.height - 0.5
          
          // Tıklanan noktaya zoom yap
          const targetX = -centerX * rect.width * (newScale - 1)
          const targetY = -centerY * rect.height * (newScale - 1)
          
          animate(x, targetX, { 
            duration: 0.3,
            type: "spring",
            stiffness: 300
          })
          animate(y, targetY, { 
            duration: 0.3,
            type: "spring",
            stiffness: 300
          })
        }
      }
      
      animate(scale, Math.min(Math.max(newScale, minZoom), maxZoom), { 
        duration: 0.3,
        type: "spring",
        stiffness: 300
      })
      
      if (newScale === 1 || doubleTapBehavior === 'reset') {
        animate(x, 0, { duration: 0.3 })
        animate(y, 0, { duration: 0.3 })
      }
      
      onZoomChange?.(newScale)
      
      if (showIndicator) {
        setShowZoomIndicator(true)
        setTimeout(() => setShowZoomIndicator(false), 1500)
      }
    }, [scale, x, y, minZoom, maxZoom, initialZoom, onZoomChange, doubleTapBehavior, showIndicator])
    
    // Touch gestures için çift dokunma
    const handleTouchEnd = useCallback((event: React.TouchEvent) => {
      const now = Date.now()
      const timeSinceLastTap = now - lastTap
      
      if (timeSinceLastTap < 300 && timeSinceLastTap > 0) {
        // Çift dokunma algılandı
        const touch = event.changedTouches[0]
        const fakeMouseEvent = {
          clientX: touch.clientX,
          clientY: touch.clientY,
          preventDefault: () => {}
        } as React.MouseEvent
        
        handleDoubleClick(fakeMouseEvent)
      }
      
      setLastTap(now)
    }, [lastTap, handleDoubleClick])
    
    const resetZoom = useCallback(() => {
      animate(scale, initialZoom, { 
        duration: 0.3,
        type: "spring",
        stiffness: 300
      })
      animate(x, 0, { 
        duration: 0.3,
        type: "spring",
        stiffness: 300
      })
      animate(y, 0, { 
        duration: 0.3,
        type: "spring",
        stiffness: 300
      })
      onZoomChange?.(initialZoom)
    }, [scale, x, y, initialZoom, onZoomChange])
    
    // Programmatik zoom kontrolleri
    const zoomIn = useCallback(() => {
      const currentScale = scale.get()
      const newScale = Math.min(currentScale + zoomStep, maxZoom)
      
      animate(scale, newScale, { 
        duration: 0.3,
        type: "spring",
        stiffness: 300
      })
      
      onZoomChange?.(newScale)
      
      if (showIndicator) {
        setShowZoomIndicator(true)
        setTimeout(() => setShowZoomIndicator(false), 1500)
      }
    }, [scale, maxZoom, zoomStep, onZoomChange, showIndicator])
    
    const zoomOut = useCallback(() => {
      const currentScale = scale.get()
      const newScale = Math.max(currentScale - zoomStep, minZoom)
      
      animate(scale, newScale, { 
        duration: 0.3,
        type: "spring",
        stiffness: 300
      })
      
      // Zoom out yapınca sınırları kontrol et
      if (newScale < scale.get()) {
        const constraints = calculateConstraints()
        const currentX = x.get()
        const currentY = y.get()
        
        if (currentX < constraints.left || currentX > constraints.right) {
          animate(x, 0, { duration: 0.3 })
        }
        if (currentY < constraints.top || currentY > constraints.bottom) {
          animate(y, 0, { duration: 0.3 })
        }
      }
      
      onZoomChange?.(newScale)
      
      if (showIndicator) {
        setShowZoomIndicator(true)
        setTimeout(() => setShowZoomIndicator(false), 1500)
      }
    }, [scale, minZoom, zoomStep, x, y, calculateConstraints, onZoomChange, showIndicator])
    
    const fitToScreen = useCallback(() => {
      resetZoom()
    }, [resetZoom])
    
    // Fullscreen toggle
    const toggleFullscreen = useCallback(() => {
      if (!containerRef.current) return
      
      if (!document.fullscreenElement) {
        // Fullscreen'e gir
        const element = containerRef.current.parentElement || containerRef.current
        element.requestFullscreen().then(() => {
          setIsFullscreen(true)
        }).catch((err) => {
          console.error("Fullscreen error:", err)
        })
      } else {
        // Fullscreen'den çık
        document.exitFullscreen().then(() => {
          setIsFullscreen(false)
        }).catch((err) => {
          console.error("Exit fullscreen error:", err)
        })
      }
    }, [])
    
    // Fullscreen değişikliklerini dinle
    useEffect(() => {
      const handleFullscreenChange = () => {
        setIsFullscreen(!!document.fullscreenElement)
      }
      
      document.addEventListener('fullscreenchange', handleFullscreenChange)
      document.addEventListener('webkitfullscreenchange', handleFullscreenChange)
      document.addEventListener('mozfullscreenchange', handleFullscreenChange)
      document.addEventListener('MSFullscreenChange', handleFullscreenChange)
      
      return () => {
        document.removeEventListener('fullscreenchange', handleFullscreenChange)
        document.removeEventListener('webkitfullscreenchange', handleFullscreenChange)
        document.removeEventListener('mozfullscreenchange', handleFullscreenChange)
        document.removeEventListener('MSFullscreenChange', handleFullscreenChange)
      }
    }, [])
    
    // Keyboard zoom shortcuts (Ctrl/Cmd + ve -)
    useEffect(() => {
      if (!isHovered || !wheelScaling) return
      
      const handleKeyDown = (e: KeyboardEvent) => {
        if (!e.ctrlKey && !e.metaKey) return
        
        if (e.key === '+' || e.key === '=') {
          e.preventDefault()
          zoomIn()
        } else if (e.key === '-' || e.key === '_') {
          e.preventDefault()
          zoomOut()
        } else if (e.key === '0') {
          e.preventDefault()
          resetZoom()
        }
      }
      
      document.addEventListener('keydown', handleKeyDown)
      
      return () => {
        document.removeEventListener('keydown', handleKeyDown)
      }
    }, [isHovered, wheelScaling, zoomIn, zoomOut, resetZoom])
    
    // Drag sınırlarını güncelle
    useEffect(() => {
      const unsubscribe = scale.onChange(() => {
        const constraints = calculateConstraints()
        const currentX = x.get()
        const currentY = y.get()
        
        // Sınırlar dışında mı kontrol et
        if (boundaryConstraints) {
          if (currentX < constraints.left || currentX > constraints.right) {
            animate(x, Math.max(constraints.left, Math.min(constraints.right, currentX)), { duration: 0.2 })
          }
          if (currentY < constraints.top || currentY > constraints.bottom) {
            animate(y, Math.max(constraints.top, Math.min(constraints.bottom, currentY)), { duration: 0.2 })
          }
        }
      })
      
      return unsubscribe
    }, [scale, x, y, calculateConstraints, boundaryConstraints])
    
    return (
      <div
        ref={ref}
        className={cn(
          "relative overflow-hidden touch-none select-none",
          dragEnabled && "cursor-grab active:cursor-grabbing",
          isFullscreen && "fixed inset-0 z-50 bg-background",
          className
        )}
        onWheel={handleWheel}
        onDoubleClick={handleDoubleClick}
        onTouchEnd={handleTouchEnd}
        onMouseEnter={() => setIsHovered(true)}
        onMouseLeave={() => setIsHovered(false)}
        {...props}
      >
        <div ref={containerRef} className="w-full h-full">
          <motion.div
            ref={contentRef}
            drag={dragEnabled}
            dragElastic={0.1}
            dragMomentum={false}
            dragConstraints={boundaryConstraints ? calculateConstraints() : false}
            onDragStart={() => setIsDragging(true)}
            onDragEnd={() => setIsDragging(false)}
            style={{
              scale: constrainedScale,
              x,
              y,
            }}
            className={cn(
              "w-full h-full flex items-center justify-center",
              isDragging && "cursor-grabbing",
              contentClassName
            )}
          >
            {children}
          </motion.div>
        </div>
        
        {/* Zoom Indicator */}
        <AnimatePresence>
          {showIndicator && showZoomIndicator && (
            <motion.div
              initial={{ opacity: 0, scale: 0.8 }}
              animate={{ opacity: 1, scale: 1 }}
              exit={{ opacity: 0, scale: 0.8 }}
              transition={{ duration: 0.2 }}
              className="absolute top-4 left-1/2 -translate-x-1/2 px-3 py-1.5 bg-black/80 dark:bg-white/80 text-white dark:text-black rounded-full text-sm font-medium pointer-events-none"
            >
              {zoomPercentage.get()}%
            </motion.div>
          )}
        </AnimatePresence>
        
        {/* Control Buttons */}
        {showControls && (
          <div className="absolute bottom-4 right-4 flex gap-2">
            <button
              onClick={zoomOut}
              disabled={scale.get() <= minZoom}
              className={cn(
                "p-2 bg-background/80 backdrop-blur-sm border rounded-md",
                "hover:bg-background/90 transition-all duration-200",
                "disabled:opacity-50 disabled:cursor-not-allowed",
                "shadow-sm hover:shadow-md"
              )}
              aria-label="Zoom out"
            >
              <ZoomOut className="w-4 h-4" />
            </button>
            <button
              onClick={zoomIn}
              disabled={scale.get() >= maxZoom}
              className={cn(
                "p-2 bg-background/80 backdrop-blur-sm border rounded-md",
                "hover:bg-background/90 transition-all duration-200",
                "disabled:opacity-50 disabled:cursor-not-allowed",
                "shadow-sm hover:shadow-md"
              )}
              aria-label="Zoom in"
            >
              <ZoomIn className="w-4 h-4" />
            </button>
            <button
              onClick={resetZoom}
              className={cn(
                "p-2 bg-background/80 backdrop-blur-sm border rounded-md",
                "hover:bg-background/90 transition-all duration-200",
                "shadow-sm hover:shadow-md"
              )}
              aria-label="Reset zoom"
            >
              <RotateCw className="w-4 h-4" />
            </button>
            <button
              onClick={toggleFullscreen}
              className={cn(
                "p-2 bg-background/80 backdrop-blur-sm border rounded-md",
                "hover:bg-background/90 transition-all duration-200",
                "shadow-sm hover:shadow-md"
              )}
              aria-label={isFullscreen ? "Exit fullscreen" : "Enter fullscreen"}
            >
              {isFullscreen ? (
                <Minimize2 className="w-4 h-4" />
              ) : (
                <Maximize2 className="w-4 h-4" />
              )}
            </button>
          </div>
        )}
        
        {/* Zoom Level Info */}
        {showControls && (
          <div className="absolute bottom-4 left-4 px-3 py-1.5 bg-background/80 backdrop-blur-sm border rounded-md text-sm">
            <div className="flex items-center gap-2">
              <span>{Math.round(scale.get() * 100)}%</span>
              {wheelScaling && !showZoomIndicator && (
                <span className="text-xs text-muted-foreground">
                  (Ctrl+Scroll to zoom)
                </span>
              )}
            </div>
          </div>
        )}
      </div>
    )
  }
)

PinchZoomInternal.displayName = "PinchZoomInternal"

export const PinchZoom = React.forwardRef<HTMLDivElement, PinchZoomProps>(
  ({ className, ...props }, ref) => {
    // Check if we're in docs mode or have pro access
    const { hasProAccess, isLoading } = useSubscription()
    
    // In docs mode, always show the component
    
    // If not in docs mode and no pro access, show upgrade prompt
    if (!isLoading && !hasProAccess) {
      return (
        <Card className={cn("w-fit", 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">
                  Pinch Zoom 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 <PinchZoomInternal className={className} ref={ref} {...props} />
  }
)

PinchZoom.displayName = "PinchZoom"