import '@/styles/globals.css'
import type { AppProps } from 'next/app'
import Router from 'next/router'
import { useI18n } from '@/hooks/useI18n'
import { useKeyboardShortcuts } from '@/hooks/useKeyboardShortcuts'
import React from 'react'
import { nostrAuthService } from '@/lib/nostrAuth'
import { relaySessionManager } from '@/lib/relaySessionManager'
import { publishWorker } from '@/lib/publishWorker'
import { swSyncHandler } from '@/lib/swSyncHandler'
import { swClient } from '@/lib/swClient'
import { ToastProvider } from '@/components/ui/ToastContainer'

function I18nProvider({ children }: { children: React.ReactNode }): React.ReactElement {
  const [initialLocale, setInitialLocale] = React.useState<'fr' | 'en'>('fr')
  const [localeLoaded, setLocaleLoaded] = React.useState(false)

  React.useEffect(() => {
    const loadLocale = async (): Promise<void> => {
      try {
        // Migrate from localStorage if needed
        const { localeStorage } = await import('@/lib/localeStorage')
        await localeStorage.migrateFromLocalStorage()

        // Load from IndexedDB
        const savedLocale = await localeStorage.getLocale()
        if (savedLocale) {
          setInitialLocale(savedLocale)
          setLocaleLoaded(true)
          return
        }
      } catch {
        // Fallback to browser locale detection
      }

      // Fallback: Try to detect browser locale
      if (typeof window !== 'undefined') {
        const browserLocale = navigator.language.split('-')[0]
        setInitialLocale(browserLocale === 'en' ? 'en' : 'fr')
      }
      setLocaleLoaded(true)
    }

    void loadLocale()
  }, [])

  const { loaded } = useI18n(initialLocale)

  if (!localeLoaded || !loaded) {
    return <div className="min-h-screen bg-cyber-darker flex items-center justify-center text-neon-cyan">Loading...</div>
  }

  return children as React.ReactElement
}

export default function App({ Component, pageProps }: AppProps): React.ReactElement {
  useRelaySessionInitialization()
  useServiceWorkerInitialization()
  usePublishWorkerLifecycle()
  usePlatformSyncOnNavigation()
  useUserSyncOnNavigationAndAuth()
  useKeyboardShortcuts()

  return (
    <I18nProvider>
      <ToastProvider>
        <Component {...pageProps} />
      </ToastProvider>
    </I18nProvider>
  )
}

function useRelaySessionInitialization(): void {
  React.useEffect(() => {
    void relaySessionManager.initialize()
  }, [])
}

function useServiceWorkerInitialization(): void {
  React.useEffect(() => {
    if (typeof window !== 'undefined') {
      void swSyncHandler.initialize()
    }
  }, [])
}

function usePublishWorkerLifecycle(): void {
  React.useEffect(() => {
    void publishWorker.start()
    return () => {
      void publishWorker.stop()
    }
  }, [])
}

function usePlatformSyncOnNavigation(): void {
  React.useEffect(() => {
    const startPlatformSync = async (): Promise<void> => {
      try {
        const isReady = await swClient.isReady()
        if (isReady) {
          await swClient.startPlatformSync()
        }
      } catch (error) {
        console.warn('[App] Service Worker not available for platform sync:', error)
      }
    }
    void startPlatformSync()
    const handleRouteChange = (): void => {
      void startPlatformSync()
    }
    Router.events?.on('routeChangeComplete', handleRouteChange)
    return () => {
      Router.events?.off('routeChangeComplete', handleRouteChange)
      void swClient.stopPlatformSync()
    }
  }, [])
}

function useUserSyncOnNavigationAndAuth(): void {
  React.useEffect(() => {
    const startUserSync = async (): Promise<void> => {
      const state = nostrAuthService.getState()
      if (!state.connected || !state.pubkey) {
        return
      }
      try {
        const isReady = await swClient.isReady()
        if (isReady) {
          await swClient.startUserSync(state.pubkey)
        }
      } catch (error) {
        console.warn('[App] Service Worker not available for user content sync:', error)
      }
    }
    void startUserSync()
    const handleRouteChange = (): void => {
      void startUserSync()
    }
    Router.events?.on('routeChangeComplete', handleRouteChange)
    const unsubscribe = nostrAuthService.subscribe((state) => {
      if (state.connected && state.pubkey) {
        void startUserSync()
      }
    })
    return () => {
      Router.events?.off('routeChangeComplete', handleRouteChange)
      unsubscribe()
    }
  }, [])
}
