"use client"

import React, { useState, useEffect, useRef, Suspense, useCallback, useMemo } from "react"
import { motion, AnimatePresence } from "framer-motion"
import { Card, CardContent } from "../ui/card"
import { Button } from "../ui/button"
import { MoonUISkeletonPro as Skeleton } from "../ui/skeleton"
import { cn } from "../../lib/utils"
import { Eye, Loader2, Lock, Sparkles, RefreshCw, Activity, Zap, BarChart3, CheckCircle2, XCircle } from "lucide-react"
import { useSubscription } from "../../hooks/use-subscription"

interface LazyComponentProps {
  children: React.ReactNode
  fallback?: React.ReactNode
  threshold?: number
  rootMargin?: string
  triggerOnce?: boolean
  disabled?: boolean
  onLoad?: () => void
  onVisible?: () => void
  onError?: (error: Error) => void
  showLoadingState?: boolean
  delay?: number
  className?: string
  // Advanced features
  priority?: 'high' | 'normal' | 'low'
  retryCount?: number
  retryDelay?: number
  enableAnalytics?: boolean
  analyticsCallback?: (metrics: LazyLoadMetrics) => void
  prefetch?: boolean
  prefetchDelay?: number
  fadeInDuration?: number
  blurDataURL?: string
  enableProgressiveEnhancement?: boolean
}

interface LazyLoadMetrics {
  loadTime: number
  visibilityTime: number
  retryAttempts: number
  success: boolean
  componentName?: string
  timestamp: number
}

interface LoadingState {
  isVisible: boolean
  isLoaded: boolean
  hasError: boolean
  error?: Error
  retryCount: number
  metrics: LazyLoadMetrics
}

const LazyComponentInternal: React.FC<LazyComponentProps> = ({
  children,
  fallback,
  threshold = 0.1,
  rootMargin = "50px",
  triggerOnce = true,
  disabled = false,
  onLoad,
  onVisible,
  onError,
  showLoadingState = true,
  delay = 0,
  className,
  priority = 'normal',
  retryCount = 3,
  retryDelay = 1000,
  enableAnalytics = false,
  analyticsCallback,
  prefetch = false,
  prefetchDelay = 2000,
  fadeInDuration = 300,
  blurDataURL,
  enableProgressiveEnhancement = true
}) => {
  const [loadingState, setLoadingState] = useState<LoadingState>({
    isVisible: disabled,
    isLoaded: disabled,
    hasError: false,
    retryCount: 0,
    metrics: {
      loadTime: 0,
      visibilityTime: 0,
      retryAttempts: 0,
      success: false,
      timestamp: Date.now()
    }
  })
  const [hasTriggered, setHasTriggered] = useState(false)
  const containerRef = useRef<HTMLDivElement>(null)
  const visibilityTimeRef = useRef<number>(0)
  const loadStartTimeRef = useRef<number>(0)

  // Retry logic
  const handleRetry = useCallback(() => {
    setLoadingState(prev => ({
      ...prev,
      hasError: false,
      retryCount: prev.retryCount + 1
    }))
    loadStartTimeRef.current = Date.now()
    
    // Simulate retry with delay
    setTimeout(() => {
      try {
        setLoadingState(prev => ({
          ...prev,
          isLoaded: true,
          hasError: false,
          metrics: {
            ...prev.metrics,
            loadTime: Date.now() - loadStartTimeRef.current,
            success: true,
            retryAttempts: prev.retryCount
          }
        }))
        
        if (enableAnalytics && analyticsCallback) {
          analyticsCallback(loadingState.metrics)
        }
        
        onLoad?.()
      } catch (error) {
        if (loadingState.retryCount < retryCount) {
          setTimeout(handleRetry, retryDelay)
        } else {
          setLoadingState(prev => ({
            ...prev,
            hasError: true,
            error: error as Error
          }))
          onError?.(error as Error)
        }
      }
    }, delay)
  }, [delay, retryCount, retryDelay, onLoad, onError, enableAnalytics, analyticsCallback, loadingState.metrics, loadingState.retryCount])

  // Prefetch logic
  useEffect(() => {
    if (prefetch && !disabled) {
      const prefetchTimer = setTimeout(() => {
        // Prefetch logic here
        console.log('Prefetching component...')
      }, prefetchDelay)
      
      return () => clearTimeout(prefetchTimer)
    }
  }, [prefetch, prefetchDelay, disabled])

  useEffect(() => {
    if (disabled) {
      setLoadingState(prev => ({
        ...prev,
        isVisible: true,
        isLoaded: true
      }))
      return
    }

    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting && (!triggerOnce || !hasTriggered)) {
          visibilityTimeRef.current = Date.now()
          
          if (delay > 0) {
            setTimeout(() => {
              setLoadingState(prev => ({ ...prev, isVisible: true }))
              setHasTriggered(true)
              onVisible?.()
              
              loadStartTimeRef.current = Date.now()
              
              // Simulate loading with priority
              const loadDelay = priority === 'high' ? delay * 0.5 : priority === 'low' ? delay * 1.5 : delay
              
              setTimeout(() => {
                try {
                  setLoadingState(prev => ({
                    ...prev,
                    isLoaded: true,
                    metrics: {
                      ...prev.metrics,
                      loadTime: Date.now() - loadStartTimeRef.current,
                      visibilityTime: Date.now() - visibilityTimeRef.current,
                      success: true
                    }
                  }))
                  
                  if (enableAnalytics && analyticsCallback) {
                    analyticsCallback(loadingState.metrics)
                  }
                  
                  onLoad?.()
                } catch (error) {
                  handleRetry()
                }
              }, loadDelay)
            }, 100)
          } else {
            setLoadingState(prev => ({
              ...prev,
              isVisible: true,
              isLoaded: true
            }))
            setHasTriggered(true)
            onVisible?.()
            onLoad?.()
          }
        } else if (!entry.isIntersecting && !triggerOnce) {
          setLoadingState(prev => ({
            ...prev,
            isVisible: false,
            isLoaded: false
          }))
        }
      },
      {
        threshold,
        rootMargin
      }
    )

    if (containerRef.current) {
      observer.observe(containerRef.current)
    }

    return () => {
      if (containerRef.current) {
        observer.unobserve(containerRef.current)
      }
    }
  }, [threshold, rootMargin, triggerOnce, delay, disabled, hasTriggered, onLoad, onVisible, priority, enableAnalytics, analyticsCallback, handleRetry])

  const renderFallback = () => {
    if (loadingState.hasError) {
      return (
        <motion.div
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          className="flex items-center justify-center p-8 border border-destructive/50 rounded-lg bg-destructive/10"
        >
          <div className="text-center space-y-3">
            <XCircle className="h-8 w-8 mx-auto text-destructive" />
            <div>
              <p className="text-sm font-medium">Failed to load component</p>
              <p className="text-xs text-muted-foreground mt-1">
                {loadingState.error?.message || 'An error occurred'}
              </p>
            </div>
            {loadingState.retryCount < retryCount && (
              <Button
                size="sm"
                variant="outline"
                onClick={handleRetry}
                className="mt-2"
              >
                <RefreshCw className="h-3 w-3 mr-2" />
                Retry ({loadingState.retryCount}/{retryCount})
              </Button>
            )}
          </div>
        </motion.div>
      )
    }
    
    if (fallback) {
      return fallback
    }

    if (showLoadingState) {
      return (
        <motion.div
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          className="relative"
        >
          {blurDataURL && enableProgressiveEnhancement ? (
            <div className="relative overflow-hidden rounded-lg">
              <img
                src={blurDataURL}
                alt="Loading placeholder"
                className="w-full h-32 object-cover filter blur-xl"
              />
              <div className="absolute inset-0 bg-background/50 backdrop-blur-sm" />
            </div>
          ) : (
            <div className="flex items-center justify-center p-8 bg-muted/50 rounded-lg">
              <div className="text-center space-y-3">
                {delay > 0 && loadingState.isVisible && !loadingState.isLoaded ? (
                  <>
                    <div className="relative">
                      <Loader2 className="h-8 w-8 animate-spin mx-auto text-primary" />
                      {priority === 'high' && (
                        <Zap className="h-3 w-3 absolute -top-1 -right-1 text-yellow-500" />
                      )}
                    </div>
                    <div className="space-y-1">
                      <p className="text-sm font-medium">Loading component...</p>
                      <p className="text-xs text-muted-foreground">
                        Priority: {priority} • Attempt {loadingState.retryCount + 1}
                      </p>
                    </div>
                  </>
                ) : (
                  <>
                    <Eye className="h-8 w-8 mx-auto text-muted-foreground" />
                    <p className="text-sm text-muted-foreground">
                      Scroll to load content
                    </p>
                  </>
                )}
              </div>
            </div>
          )}
          
          {enableAnalytics && loadingState.isVisible && !loadingState.isLoaded && (
            <div className="absolute top-2 right-2 flex items-center gap-2 text-xs text-muted-foreground bg-background/80 backdrop-blur-sm px-2 py-1 rounded">
              <Activity className="h-3 w-3" />
              <span>Tracking performance</span>
            </div>
          )}
        </motion.div>
      )
    }

    return <Skeleton className="w-full h-32" />
  }

  return (
    <div ref={containerRef} className={cn("w-full", className)}>
      <AnimatePresence mode="wait">
        {loadingState.isLoaded ? (
          <motion.div
            key="content"
            initial={{ opacity: 0, y: 20 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -20 }}
            transition={{ duration: fadeInDuration / 1000 }}
          >
            {enableAnalytics && (
              <div className="absolute -top-8 right-0 flex items-center gap-2 text-xs text-muted-foreground bg-background/80 backdrop-blur-sm px-2 py-1 rounded">
                <CheckCircle2 className="h-3 w-3 text-green-500" />
                <span>Loaded in {loadingState.metrics.loadTime}ms</span>
              </div>
            )}
            {children}
          </motion.div>
        ) : (
          <motion.div
            key="fallback"
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.2 }}
          >
            {renderFallback()}
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  )
}

// Lazy Image Component
export interface LazyImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, 'onProgress'> {
  src: string
  alt: string
  fallbackSrc?: string
  showPlaceholder?: boolean
  threshold?: number
  rootMargin?: string
  onLoad?: () => void
  onError?: () => void
  className?: string
  // Advanced features
  quality?: number
  priority?: boolean
  blur?: boolean
  blurDataURL?: string
  aspectRatio?: string
  objectFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'
  sizes?: string
  srcSet?: string
  enableProgressiveLoading?: boolean
  onProgress?: (progress: number) => void
}

export const LazyImage: React.FC<LazyImageProps> = ({
  src,
  alt,
  fallbackSrc,
  showPlaceholder = true,
  threshold = 0.1,
  rootMargin = "50px",
  onLoad,
  onError,
  className,
  quality = 85,
  priority = false,
  blur = true,
  blurDataURL,
  aspectRatio,
  objectFit = 'cover',
  sizes,
  srcSet,
  enableProgressiveLoading = false,
  onProgress,
  ...restProps
}) => {
  // Filter out LazyImage specific props and event handlers that shouldn't be passed to img element
  const { onDrag, onDragStart, onDragEnd, onDragOver, onDrop, onAnimationStart, onAnimationEnd, onAnimationIteration, ...props } = restProps
  const [imageSrc, setImageSrc] = useState<string | null>(priority ? src : null)
  const [imageError, setImageError] = useState(false)
  const [isVisible, setIsVisible] = useState(priority)
  const [loadProgress, setLoadProgress] = useState(0)
  const [isLoading, setIsLoading] = useState(false)
  const imgRef = useRef<HTMLImageElement>(null)
  const containerRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          setIsVisible(true)
          observer.disconnect()
        }
      },
      { threshold, rootMargin }
    )

    if (containerRef.current) {
      observer.observe(containerRef.current)
    }

    return () => observer.disconnect()
  }, [threshold, rootMargin])

  useEffect(() => {
    if (!isVisible || imageSrc) return

    setIsLoading(true)
    const img = new Image()
    
    // Progressive loading simulation
    if (enableProgressiveLoading) {
      let progress = 0
      const progressInterval = setInterval(() => {
        progress += Math.random() * 30
        if (progress > 90) progress = 90
        setLoadProgress(progress)
        onProgress?.(progress)
      }, 100)
      
      img.onload = () => {
        clearInterval(progressInterval)
        setLoadProgress(100)
        onProgress?.(100)
        setImageSrc(src)
        setIsLoading(false)
        onLoad?.()
      }
    } else {
      img.onload = () => {
        setImageSrc(src)
        setIsLoading(false)
        onLoad?.()
      }
    }
    
    img.onerror = () => {
      setImageError(true)
      setIsLoading(false)
      if (fallbackSrc) {
        setImageSrc(fallbackSrc)
      }
      onError?.()
    }
    
    // Add quality parameter to image URL if supported
    const qualityParam = src.includes('?') ? `&q=${quality}` : `?q=${quality}`
    img.src = src + (src.includes('http') ? qualityParam : '')
  }, [isVisible, src, fallbackSrc, onLoad, onError, quality, enableProgressiveLoading, onProgress, imageSrc])

  return (
    <div 
      ref={containerRef} 
      className={cn("relative overflow-hidden bg-muted", className)}
      style={aspectRatio ? { aspectRatio } : undefined}
    >
      <AnimatePresence mode="wait">
        {/* Blur placeholder */}
        {blur && blurDataURL && !imageSrc && (
          <motion.img
            key="blur"
            src={blurDataURL}
            alt=""
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            className="absolute inset-0 w-full h-full object-cover filter blur-xl scale-110"
          />
        )}
        
        {/* Main image */}
        {imageSrc && (
          <motion.img
            key="main"
            ref={imgRef}
            src={imageSrc}
            alt={alt}
            sizes={sizes}
            srcSet={srcSet}
            initial={{ opacity: 0, scale: 1.02 }}
            animate={{ opacity: 1, scale: 1 }}
            transition={{ duration: 0.4 }}
            className={cn("w-full h-full", `object-${objectFit}`)}
            {...props}
          />
        )}
        
        {/* Loading state */}
        {isLoading && showPlaceholder && (
          <motion.div
            key="loading"
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            className="absolute inset-0 flex items-center justify-center bg-background/50 backdrop-blur-sm"
          >
            <div className="text-center">
              <Loader2 className="h-8 w-8 animate-spin mx-auto text-primary mb-2" />
              {enableProgressiveLoading && (
                <div className="w-32 h-1 bg-muted rounded-full overflow-hidden">
                  <motion.div
                    className="h-full bg-primary"
                    initial={{ width: 0 }}
                    animate={{ width: `${loadProgress}%` }}
                  />
                </div>
              )}
            </div>
          </motion.div>
        )}
        
        {/* Skeleton placeholder */}
        {!imageSrc && !isLoading && showPlaceholder && (
          <Skeleton className="absolute inset-0" />
        )}
        
        {/* Error state */}
        {imageError && !fallbackSrc && (
          <motion.div 
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            className="absolute inset-0 flex items-center justify-center bg-muted"
          >
            <div className="text-center">
              <XCircle className="h-8 w-8 mx-auto text-muted-foreground mb-2" />
              <p className="text-sm text-muted-foreground">Failed to load image</p>
            </div>
          </motion.div>
        )}
      </AnimatePresence>
      
      {/* Priority badge */}
      {priority && (
        <div className="absolute top-2 right-2 bg-yellow-500/90 text-yellow-900 text-xs px-2 py-1 rounded flex items-center gap-1">
          <Zap className="h-3 w-3" />
          Priority
        </div>
      )}
    </div>
  )
}

// Lazy List Component
export interface LazyListProps<T> {
  items: T[]
  renderItem: (item: T, index: number) => React.ReactNode
  itemHeight?: number
  batchSize?: number
  threshold?: number
  className?: string
  // Advanced features
  enableVirtualization?: boolean
  overscan?: number
  showLoadingIndicator?: boolean
  loadingIndicator?: React.ReactNode
  emptyState?: React.ReactNode
  onBatchLoad?: (startIndex: number, endIndex: number) => void
  enableSmoothScroll?: boolean
  staggerAnimation?: boolean
  animationDelay?: number
}

export function LazyList<T>({
  items,
  renderItem,
  itemHeight = 100,
  batchSize = 10,
  threshold = 0.5,
  className,
  enableVirtualization = false,
  overscan = 3,
  showLoadingIndicator = true,
  loadingIndicator,
  emptyState,
  onBatchLoad,
  enableSmoothScroll = true,
  staggerAnimation = true,
  animationDelay = 50
}: LazyListProps<T>) {
  const [visibleItems, setVisibleItems] = useState<T[]>([])
  const [currentBatch, setCurrentBatch] = useState(0)
  const [isLoading, setIsLoading] = useState(false)
  const loadingRef = useRef<HTMLDivElement>(null)
  const containerRef = useRef<HTMLDivElement>(null)
  const [scrollPosition, setScrollPosition] = useState(0)

  useEffect(() => {
    setVisibleItems(items.slice(0, batchSize))
    setCurrentBatch(1)
  }, [items, batchSize])

  // Handle scroll for virtualization
  const handleScroll = useCallback((e: Event) => {
    if (enableVirtualization && containerRef.current) {
      setScrollPosition((e.target as HTMLElement).scrollTop)
    }
  }, [enableVirtualization])

  useEffect(() => {
    const container = containerRef.current
    if (enableVirtualization && container) {
      container.addEventListener('scroll', handleScroll)
      return () => container.removeEventListener('scroll', handleScroll)
    }
  }, [enableVirtualization, handleScroll])

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting && currentBatch * batchSize < items.length && !isLoading) {
          setIsLoading(true)
          
          // Simulate loading delay
          setTimeout(() => {
            const nextBatch = currentBatch + 1
            const startIndex = currentBatch * batchSize
            const endIndex = nextBatch * batchSize
            const newItems = items.slice(0, endIndex)
            
            setVisibleItems(newItems)
            setCurrentBatch(nextBatch)
            setIsLoading(false)
            
            onBatchLoad?.(startIndex, endIndex)
          }, 300)
        }
      },
      { threshold }
    )

    if (loadingRef.current) {
      observer.observe(loadingRef.current)
    }

    return () => observer.disconnect()
  }, [currentBatch, items, batchSize, threshold, isLoading, onBatchLoad])

  // Calculate visible range for virtualization
  const visibleRange = useMemo(() => {
    if (!enableVirtualization) return { start: 0, end: visibleItems.length }
    
    const start = Math.floor(scrollPosition / itemHeight) - overscan
    const visibleCount = Math.ceil(400 / itemHeight) // Assuming container height of 400px
    const end = start + visibleCount + overscan * 2
    
    return {
      start: Math.max(0, start),
      end: Math.min(visibleItems.length, end)
    }
  }, [scrollPosition, itemHeight, overscan, visibleItems.length, enableVirtualization])

  if (items.length === 0 && emptyState) {
    return (
      <div className={cn("flex items-center justify-center p-8", className)}>
        {emptyState}
      </div>
    )
  }

  return (
    <div 
      ref={containerRef}
      className={cn(
        "relative",
        enableVirtualization && "overflow-auto max-h-[400px]",
        enableSmoothScroll && "scroll-smooth",
        className
      )}
    >
      {enableVirtualization ? (
        // Virtualized rendering
        <>
          <div style={{ height: visibleItems.length * itemHeight }} />
          <div className="absolute top-0 left-0 right-0">
            {visibleItems.slice(visibleRange.start, visibleRange.end).map((item, index) => {
              const actualIndex = visibleRange.start + index
              return (
                <motion.div
                  key={actualIndex}
                  initial={staggerAnimation ? { opacity: 0, x: -20 } : { opacity: 1 }}
                  animate={{ opacity: 1, x: 0 }}
                  transition={staggerAnimation ? { 
                    delay: index * (animationDelay / 1000),
                    duration: 0.3
                  } : undefined}
                  style={{ 
                    position: 'absolute',
                    top: actualIndex * itemHeight,
                    left: 0,
                    right: 0,
                    height: itemHeight
                  }}
                >
                  {renderItem(item, actualIndex)}
                </motion.div>
              )
            })}
          </div>
        </>
      ) : (
        // Regular lazy loading
        <div className="space-y-2">
          {visibleItems.map((item, index) => (
            <motion.div
              key={index}
              initial={staggerAnimation ? { opacity: 0, y: 20 } : { opacity: 1 }}
              animate={{ opacity: 1, y: 0 }}
              transition={staggerAnimation ? { 
                delay: (index % batchSize) * (animationDelay / 1000),
                duration: 0.3
              } : undefined}
              style={{ minHeight: itemHeight }}
            >
              {renderItem(item, index)}
            </motion.div>
          ))}
        </div>
      )}
      
      {currentBatch * batchSize < items.length && (
        <div ref={loadingRef} className="flex justify-center py-4">
          {showLoadingIndicator && (
            loadingIndicator || (
              <div className="flex items-center gap-2">
                <Loader2 className="h-5 w-5 animate-spin text-primary" />
                <span className="text-sm text-muted-foreground">
                  Loading more items...
                </span>
              </div>
            )
          )}
        </div>
      )}
      
      {/* Progress indicator */}
      {items.length > batchSize && (
        <div className="sticky bottom-0 left-0 right-0 bg-gradient-to-t from-background to-transparent pt-8 pb-2">
          <div className="flex items-center justify-center gap-2 text-xs text-muted-foreground">
            <BarChart3 className="h-3 w-3" />
            <span>
              Showing {visibleItems.length} of {items.length} items
            </span>
          </div>
        </div>
      )}
    </div>
  )
}

export const LazyComponent: React.FC<LazyComponentProps> = ({ className, ...props }) => {
  // 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">
                Lazy Component 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 <LazyComponentInternal className={className} {...props} />
}

// Export types removed to fix conflict