'use client'

import React, { createContext, useContext, useState, useEffect, useCallback, useRef } from 'react'

/**
 * Performance Context - Adaptive Quality System
 *
 * Monitors device capabilities and runtime performance to automatically
 * adjust visual quality. This ensures smooth 60fps (or 120fps on capable devices)
 * by degrading effects when needed.
 */

// =============================================================================
// TYPES
// =============================================================================

export type QualityLevel = 'high' | 'medium' | 'low' | 'minimal'

export interface PerformanceMetrics {
  /** Frames per second (rolling average) */
  fps: number
  /** Dropped frames in last second */
  droppedFrames: number
  /** Device memory in GB (if available) */
  deviceMemory: number | null
  /** Number of logical CPU cores */
  hardwareConcurrency: number
  /** Whether device prefers reduced motion */
  prefersReducedMotion: boolean
  /** Whether device is on battery/power-save */
  isLowPowerMode: boolean
  /** Current quality level */
  qualityLevel: QualityLevel
}

export interface QualitySettings {
  /** Enable backdrop blur effects */
  enableBlur: boolean
  /** Blur intensity multiplier (0-1) */
  blurIntensity: number
  /** Enable shadow effects */
  enableShadows: boolean
  /** Shadow complexity (0-1) */
  shadowComplexity: number
  /** Enable parallax effects */
  enableParallax: boolean
  /** Parallax intensity multiplier (0-1) */
  parallaxIntensity: number
  /** Enable spring animations */
  enableSpringAnimations: boolean
  /** Animation duration multiplier (0.5-1.5) */
  animationSpeed: number
  /** Enable typewriter effects */
  enableTypewriter: boolean
  /** Max concurrent animations */
  maxConcurrentAnimations: number
}

interface PerformanceContextType {
  metrics: PerformanceMetrics
  settings: QualitySettings
  /** Force a specific quality level (null = auto) */
  forceQuality: (level: QualityLevel | null) => void
  /** Report that an animation started */
  reportAnimationStart: () => void
  /** Report that an animation ended */
  reportAnimationEnd: () => void
  /** Check if we can start another animation */
  canStartAnimation: () => boolean
}

// =============================================================================
// DEFAULT VALUES
// =============================================================================

const DEFAULT_METRICS: PerformanceMetrics = {
  fps: 60,
  droppedFrames: 0,
  deviceMemory: null,
  hardwareConcurrency: 4,
  prefersReducedMotion: false,
  isLowPowerMode: false,
  qualityLevel: 'high',
}

const QUALITY_PRESETS: Record<QualityLevel, QualitySettings> = {
  high: {
    enableBlur: true,
    blurIntensity: 1,
    enableShadows: true,
    shadowComplexity: 1,
    enableParallax: true,
    parallaxIntensity: 1,
    enableSpringAnimations: true,
    animationSpeed: 1,
    enableTypewriter: true,
    maxConcurrentAnimations: 10,
  },
  medium: {
    enableBlur: true,
    blurIntensity: 0.7,
    enableShadows: true,
    shadowComplexity: 0.7,
    enableParallax: true,
    parallaxIntensity: 0.5,
    enableSpringAnimations: true,
    animationSpeed: 0.9,
    enableTypewriter: true,
    maxConcurrentAnimations: 6,
  },
  low: {
    enableBlur: false,
    blurIntensity: 0,
    enableShadows: true,
    shadowComplexity: 0.4,
    enableParallax: false,
    parallaxIntensity: 0,
    enableSpringAnimations: false,
    animationSpeed: 0.7,
    enableTypewriter: true,
    maxConcurrentAnimations: 3,
  },
  minimal: {
    enableBlur: false,
    blurIntensity: 0,
    enableShadows: false,
    shadowComplexity: 0,
    enableParallax: false,
    parallaxIntensity: 0,
    enableSpringAnimations: false,
    animationSpeed: 0.5,
    enableTypewriter: false,
    maxConcurrentAnimations: 1,
  },
}

// =============================================================================
// CONTEXT
// =============================================================================

const PerformanceContext = createContext<PerformanceContextType | null>(null)

// =============================================================================
// PROVIDER
// =============================================================================

export function PerformanceProvider({ children }: { children: React.ReactNode }) {
  const [metrics, setMetrics] = useState<PerformanceMetrics>(DEFAULT_METRICS)
  const [forcedQuality, setForcedQuality] = useState<QualityLevel | null>(null)
  const [activeAnimations, setActiveAnimations] = useState(0)

  const frameTimesRef = useRef<number[]>([])
  const lastFrameTimeRef = useRef<number>(performance.now())
  const rafIdRef = useRef<number | null>(null)

  // Detect device capabilities on mount
  useEffect(() => {
    if (typeof window === 'undefined') return

    const detectCapabilities = () => {
      // Hardware concurrency
      const cores = navigator.hardwareConcurrency || 4

      // Device memory (Chrome only)
      const memory = (navigator as any).deviceMemory || null

      // Reduced motion preference
      const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches

      // Battery/power save mode (approximation)
      let lowPower = false
      if ('getBattery' in navigator) {
        (navigator as any).getBattery?.().then((battery: any) => {
          lowPower = battery.level < 0.2 && !battery.charging
          setMetrics(prev => ({ ...prev, isLowPowerMode: lowPower }))
        })
      }

      // Determine initial quality level
      let initialQuality: QualityLevel = 'high'
      if (reducedMotion) {
        initialQuality = 'minimal'
      } else if (cores <= 2 || (memory && memory <= 2)) {
        initialQuality = 'low'
      } else if (cores <= 4 || (memory && memory <= 4)) {
        initialQuality = 'medium'
      }

      setMetrics(prev => ({
        ...prev,
        hardwareConcurrency: cores,
        deviceMemory: memory,
        prefersReducedMotion: reducedMotion,
        qualityLevel: initialQuality,
      }))
    }

    detectCapabilities()

    // Listen for reduced motion changes
    const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)')
    const handleChange = (e: MediaQueryListEvent) => {
      setMetrics(prev => ({
        ...prev,
        prefersReducedMotion: e.matches,
        qualityLevel: e.matches ? 'minimal' : prev.qualityLevel,
      }))
    }
    mediaQuery.addEventListener('change', handleChange)

    return () => mediaQuery.removeEventListener('change', handleChange)
  }, [])

  // FPS monitoring loop
  useEffect(() => {
    if (typeof window === 'undefined') return

    let frameCount = 0
    let lastFpsUpdate = performance.now()

    const measureFrame = (timestamp: number) => {
      const delta = timestamp - lastFrameTimeRef.current
      lastFrameTimeRef.current = timestamp

      // Track frame times (keep last 60)
      frameTimesRef.current.push(delta)
      if (frameTimesRef.current.length > 60) {
        frameTimesRef.current.shift()
      }

      frameCount++

      // Update FPS every second
      if (timestamp - lastFpsUpdate >= 1000) {
        const avgFrameTime =
          frameTimesRef.current.reduce((a, b) => a + b, 0) / frameTimesRef.current.length
        const fps = Math.round(1000 / avgFrameTime)

        // Count dropped frames (frames > 20ms = dropped at 60fps)
        const dropped = frameTimesRef.current.filter(t => t > 20).length

        setMetrics(prev => {
          // Auto-adjust quality based on performance
          let newQuality = prev.qualityLevel
          if (!forcedQuality) {
            if (dropped > 10 && prev.qualityLevel !== 'minimal') {
              // Downgrade
              const levels: QualityLevel[] = ['high', 'medium', 'low', 'minimal']
              const currentIndex = levels.indexOf(prev.qualityLevel)
              newQuality = levels[Math.min(currentIndex + 1, levels.length - 1)]
            } else if (dropped === 0 && fps >= 58 && prev.qualityLevel !== 'high') {
              // Consider upgrade (only if stable for a while)
              // This is conservative - we don't want to oscillate
            }
          }

          return {
            ...prev,
            fps,
            droppedFrames: dropped,
            qualityLevel: forcedQuality || newQuality,
          }
        })

        frameCount = 0
        lastFpsUpdate = timestamp
      }

      rafIdRef.current = requestAnimationFrame(measureFrame)
    }

    rafIdRef.current = requestAnimationFrame(measureFrame)

    return () => {
      if (rafIdRef.current) {
        cancelAnimationFrame(rafIdRef.current)
      }
    }
  }, [forcedQuality])

  // Get current settings based on quality level
  const settings = QUALITY_PRESETS[forcedQuality || metrics.qualityLevel]

  // Force quality level
  const forceQuality = useCallback((level: QualityLevel | null) => {
    setForcedQuality(level)
    if (level) {
      setMetrics(prev => ({ ...prev, qualityLevel: level }))
    }
  }, [])

  // Animation tracking
  const reportAnimationStart = useCallback(() => {
    setActiveAnimations(prev => prev + 1)
  }, [])

  const reportAnimationEnd = useCallback(() => {
    setActiveAnimations(prev => Math.max(0, prev - 1))
  }, [])

  const canStartAnimation = useCallback(() => {
    return activeAnimations < settings.maxConcurrentAnimations
  }, [activeAnimations, settings.maxConcurrentAnimations])

  return (
    <PerformanceContext.Provider
      value={{
        metrics,
        settings,
        forceQuality,
        reportAnimationStart,
        reportAnimationEnd,
        canStartAnimation,
      }}
    >
      {children}
    </PerformanceContext.Provider>
  )
}

// =============================================================================
// HOOKS
// =============================================================================

export function usePerformance() {
  const context = useContext(PerformanceContext)
  if (!context) {
    // Return defaults if used outside provider
    return {
      metrics: DEFAULT_METRICS,
      settings: QUALITY_PRESETS.high,
      forceQuality: () => {},
      reportAnimationStart: () => {},
      reportAnimationEnd: () => {},
      canStartAnimation: () => true,
    }
  }
  return context
}

/**
 * Hook to get adaptive blur value
 */
export function useAdaptiveBlur(baseBlur: number): number {
  const { settings } = usePerformance()
  if (!settings.enableBlur) return 0
  return Math.round(baseBlur * settings.blurIntensity)
}

/**
 * Hook to get adaptive shadow
 */
export function useAdaptiveShadow(baseShadow: string, fallbackShadow: string = 'none'): string {
  const { settings } = usePerformance()
  if (!settings.enableShadows) return fallbackShadow
  // Could also reduce shadow complexity here
  return baseShadow
}

/**
 * Hook for reduced motion check
 */
export function usePrefersReducedMotion(): boolean {
  const { metrics } = usePerformance()
  return metrics.prefersReducedMotion
}

/**
 * Hook to get animation duration with performance adjustment
 */
export function useAdaptiveAnimationDuration(baseDuration: number): number {
  const { settings } = usePerformance()
  return Math.round(baseDuration * settings.animationSpeed)
}
