/**
 * Theme Hook
 * Handles dark mode detection and Dark Reader compatibility
 * Uses MutationObserver for efficient Dark Reader detection
 */

import { useEffect, useState } from 'react'

export function useTheme() {
  const [isDark, setIsDark] = useState(false)
  const [hasDarkReader, setHasDarkReader] = useState(false)

  useEffect(() => {
    const html = document.documentElement

    // Helper function to apply/remove dark mode
    const applyDarkMode = (shouldBeDark: boolean) => {
      setIsDark(shouldBeDark)
      if (shouldBeDark) {
        html.classList.add('dark')
        html.setAttribute('data-theme', 'dark')
      } else {
        html.classList.remove('dark')
        html.setAttribute('data-theme', 'light')
      }
    }

    // Enhanced Dark Reader detection with multiple methods
    const detectDarkReader = (): boolean => {
      // Method 1: Check for Dark Reader data attributes on html element
      const hasDarkReaderAttributes = 
        html.hasAttribute('data-darkreader-mode') ||
        html.hasAttribute('data-darkreader-scheme') ||
        html.hasAttribute('data-darkreader-policy')

      // Method 2: Check for Dark Reader stylesheet or meta tags
      const hasDarkReaderMeta = 
        document.querySelector('meta[name="darkreader"]') !== null ||
        document.querySelector('style[data-darkreader]') !== null

      // Method 3: Check computed styles for filter/invert (Dark Reader uses CSS filters)
      const computedStyle = window.getComputedStyle(html)
      const hasFilter = computedStyle.filter && computedStyle.filter !== 'none'
      const hasInvert = computedStyle.filter?.includes('invert') || 
                       computedStyle.filter?.includes('brightness')

      // Method 4: Check for Dark Reader's characteristic background color
      // Dark Reader often sets a specific dark background
      const bgColor = computedStyle.backgroundColor
      const isDarkReaderBg = bgColor === 'rgb(24, 26, 27)' || 
                            bgColor === 'rgb(18, 18, 18)' ||
                            (window.matchMedia('(prefers-color-scheme: dark)').matches && 
                             bgColor !== 'rgba(0, 0, 0, 0)' &&
                             bgColor !== 'transparent' &&
                             !html.classList.contains('dark'))

      // Method 5: Check for Dark Reader injected styles
      const styleSheets = Array.from(document.styleSheets)
      const hasDarkReaderStylesheet = styleSheets.some(sheet => {
        try {
          const href = sheet.href || ''
          return href.includes('darkreader') || 
                 (sheet.ownerNode as Element)?.getAttribute('data-darkreader') !== null
        } catch {
          return false
        }
      })

      return hasDarkReaderAttributes || 
             hasDarkReaderMeta || 
             (hasFilter && hasInvert) || 
             isDarkReaderBg ||
             hasDarkReaderStylesheet
    }

    // Check system preference
    const checkSystemPreference = (): boolean => {
      return window.matchMedia('(prefers-color-scheme: dark)').matches
    }

    // Update theme based on current state
    const updateTheme = () => {
      const darkReaderDetected = detectDarkReader()
      const systemPrefersDark = checkSystemPreference()
      
      setHasDarkReader(darkReaderDetected)
      
      // Only apply dark mode if system prefers it AND Dark Reader is not active
      if (systemPrefersDark && !darkReaderDetected) {
        applyDarkMode(true)
      } else {
        applyDarkMode(false)
      }
    }

    // Initial check
    updateTheme()

    // Listen for system preference changes
    const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
    const handleSystemPreferenceChange = () => {
      updateTheme()
    }

    // Modern browsers
    if (mediaQuery.addEventListener) {
      mediaQuery.addEventListener('change', handleSystemPreferenceChange)
    } else {
      // Fallback for older browsers
      mediaQuery.addListener(handleSystemPreferenceChange)
    }

    // MutationObserver for Dark Reader attribute changes (more efficient than setInterval)
    const observer = new MutationObserver((mutations) => {
      let shouldUpdate = false
      
      mutations.forEach((mutation) => {
        // Check if Dark Reader attributes were added/removed
        if (mutation.type === 'attributes') {
          const attrName = mutation.attributeName
          if (attrName?.startsWith('data-darkreader') || 
              attrName === 'class' || 
              attrName === 'data-theme') {
            shouldUpdate = true
          }
        }
        
        // Check if Dark Reader elements were added/removed
        if (mutation.type === 'childList') {
          mutation.addedNodes.forEach((node) => {
            if (node.nodeType === Node.ELEMENT_NODE) {
              const el = node as Element
              if (el.hasAttribute?.('data-darkreader') ||
                  el.tagName === 'META' && el.getAttribute('name') === 'darkreader' ||
                  el.tagName === 'STYLE' && el.hasAttribute('data-darkreader')) {
                shouldUpdate = true
              }
            }
          })
        }
      })
      
      if (shouldUpdate) {
        updateTheme()
      }
    })

    // Observe html element for Dark Reader attribute changes
    observer.observe(html, {
      attributes: true,
      attributeFilter: ['data-darkreader-mode', 'data-darkreader-scheme', 'data-darkreader-policy', 'class', 'data-theme'],
      childList: true,
      subtree: false
    })

    // Also observe document head for Dark Reader meta/stylesheets
    if (document.head) {
      observer.observe(document.head, {
        childList: true,
        subtree: false
      })
    }

    // Fallback: Periodic check (reduced frequency, only as safety net)
    // This catches edge cases where MutationObserver might miss something
    const fallbackInterval = setInterval(() => {
      const currentDarkReader = detectDarkReader()
      if (currentDarkReader !== hasDarkReader) {
        updateTheme()
      }
    }, 5000) // Check every 5 seconds (reduced from 2 seconds)

    return () => {
      // Cleanup
      if (mediaQuery.removeEventListener) {
        mediaQuery.removeEventListener('change', handleSystemPreferenceChange)
      } else {
        mediaQuery.removeListener(handleSystemPreferenceChange)
      }
      observer.disconnect()
      clearInterval(fallbackInterval)
    }
  }, [])

  return { isDark, hasDarkReader }
}
