import {
  createContext,
  useCallback,
  useContext,
  useState,
  useEffect
} from 'react'
import { theme } from 'antd'
import PropTypes from 'prop-types'

const ThemeContext = createContext()

const COLORS = {
  colorPrimary: '#0091FF',
  colorPrimaryDisabledDark: '#0e3a5b',
  colorPrimaryDisabledLight: '#e6f8ff',
  colorSuccess: '#30D158',
  colorWarning: '#FF9230',
  colorError: '#FF4245',
  colorInfo: '#0A84FF',
  colorLink: '#5AC8F5',
  colorCyan: '#5AC8F5',
  colorPink: '#FF69B4',
  colorPurple: '#6B5DFF',
  colorMagenta: '#FF00FF',
  colorVolcano: '#FF4500'
}

export const ThemeProvider = ({ children }) => {
  const [isSystem, setIsSystem] = useState(() => {
    const savedSystem = sessionStorage.getItem('isSystem')
    return savedSystem ? JSON.parse(savedSystem) : true
  })
  const [isDarkMode, setIsDarkMode] = useState(() => {
    const savedTheme = sessionStorage.getItem('isDarkMode')
    return savedTheme ? JSON.parse(savedTheme) : true
  })
  const [isCompact, setIsCompact] = useState(() => {
    const savedCompact = sessionStorage.getItem('isCompact')
    return savedCompact ? JSON.parse(savedCompact) : false
  })

  const [primaryColorOverride, setPrimaryColorOverride] = useState(null)

  // System theme detection
  useEffect(() => {
    const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')

    const handleSystemThemeChange = (e) => {
      if (isSystem) {
        setIsDarkMode(e.matches)
      }
    }

    // Set initial value
    if (isSystem) {
      setIsDarkMode(mediaQuery.matches)
    }

    // Add listener
    mediaQuery.addEventListener('change', handleSystemThemeChange)

    // Cleanup
    return () =>
      mediaQuery.removeEventListener('change', handleSystemThemeChange)
  }, [isSystem])

  useEffect(() => {
    sessionStorage.setItem('isSystem', JSON.stringify(isSystem))
  }, [isSystem])

  useEffect(() => {
    sessionStorage.setItem('isDarkMode', JSON.stringify(isDarkMode))
  }, [isDarkMode])

  useEffect(() => {
    sessionStorage.setItem('isCompact', JSON.stringify(isCompact))
  }, [isCompact])

  const toggleTheme = () => {
    if (isSystem) {
      setIsSystem(false)
    }
    setIsDarkMode(!isDarkMode)
  }

  const toggleSystem = () => {
    setIsSystem(!isSystem)
    if (!isSystem) {
      // When enabling system theme, update to match system preference
      setIsDarkMode(window.matchMedia('(prefers-color-scheme: dark)').matches)
    }
  }

  const toggleCompact = () => {
    setIsCompact(!isCompact)
  }

  const setThemeMode = useCallback((value) => {
    if (value === 'system') {
      setIsSystem(true)
      setIsDarkMode(window.matchMedia('(prefers-color-scheme: dark)').matches)
      return
    }

    setIsSystem(false)
    setIsDarkMode(value === 'dark')
  }, [])

  const setDensityMode = useCallback((value) => {
    setIsCompact(value === 'compact')
  }, [])

  const getThemeAlgorithm = () => {
    var baseAlgorithm
    if (isDarkMode == true) {
      baseAlgorithm = theme.darkAlgorithm
    } else {
      baseAlgorithm = theme.defaultAlgorithm
    }
    return isCompact ? [theme.compactAlgorithm, baseAlgorithm] : [baseAlgorithm]
  }

  const getColors = () => {
    return COLORS
  }

  // Set CSS custom properties for theme colors
  useEffect(() => {
    const root = document.documentElement
    root.style.setProperty(
      '--color-primary',
      primaryColorOverride == null ? COLORS.colorPrimary : primaryColorOverride
    )
    root.style.setProperty(
      '--color-primary-disabled',
      isDarkMode
        ? COLORS.colorPrimaryDisabledDark
        : COLORS.colorPrimaryDisabledLight
    )
    root.style.setProperty('--color-success', COLORS.colorSuccess)
    root.style.setProperty('--color-warning', COLORS.colorWarning)
    root.style.setProperty('--color-error', COLORS.colorError)
    root.style.setProperty('--color-info', COLORS.colorInfo)
    root.style.setProperty('--color-link', COLORS.colorLink)
    root.style.setProperty('--color-cyan', COLORS.colorCyan)
    root.style.setProperty('--color-pink', COLORS.colorPink)
    root.style.setProperty('--color-purple', COLORS.colorPurple)
    root.style.setProperty('--color-magenta', COLORS.colorMagenta)
    root.style.setProperty('--color-volcano', COLORS.colorVolcano)
    root.style.setProperty(
      '--layout-header-bg',
      isDarkMode ? '#141414' : '#ffffff'
    )
    root.style.setProperty(
      '--layout-modal-bg',
      isDarkMode ? '#1f1f1f' : '#ffffff'
    )
  }, [isDarkMode, primaryColorOverride])

  const themeConfig = {
    algorithm: getThemeAlgorithm(),
    token: {
      ...COLORS,
      colorPrimary:
        primaryColorOverride == null
          ? COLORS.colorPrimary
          : primaryColorOverride,
      borderRadius: '12px'
    },
    components: {
      Layout: {
        headerBg: isDarkMode ? '#141414' : '#ffffff'
      }
    }
  }

  return (
    <ThemeContext.Provider
      value={{
        isDarkMode,
        toggleTheme,
        isCompact,
        toggleCompact,
        isSystem,
        toggleSystem,
        setThemeMode,
        setDensityMode,
        getColors,
        setPrimaryColorOverride,
        themeConfig
      }}
    >
      {children}
    </ThemeContext.Provider>
  )
}

ThemeProvider.propTypes = {
  children: PropTypes.node.isRequired
}

// eslint-disable-next-line react-refresh/only-export-components
export const useThemeContext = () => {
  const context = useContext(ThemeContext)
  if (!context) {
    throw new Error('useThemeContext must be used within a ThemeProvider')
  }
  return context
}
