import { createApp } from 'vue'
import type { DirectiveBinding } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import { createPinia } from 'pinia'
import { routes } from './routes'
import App from './App.vue'
import './app.css'
import { library } from '@fortawesome/fontawesome-svg-core'
import { plugin as Slicksort } from 'vue-slicksort'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { logger } from './utils/logger'
import { typedStorage, STORAGE_KEYS } from './utils/storage'
import { faMobile, faTablet, faDesktop, faStar } from '@fortawesome/free-solid-svg-icons'
import { faStar as faStarRegular } from '@fortawesome/free-regular-svg-icons'
import {
  faAndroid,
  faBrave,
  faChrome,
  faEdge,
  faFirefoxBrowser,
  faSafari,
  faApple,
  faUbuntu,
  faLinux,
  faGithub,
  faYoutube
} from '@fortawesome/free-brands-svg-icons'

library.add(
  faAndroid,
  faBrave,
  faChrome,
  faEdge,
  faFirefoxBrowser,
  faSafari,
  faApple,
  faUbuntu,
  faLinux,
  faGithub,
  faYoutube,
  faMobile,
  faTablet,
  faDesktop,
  faStar,
  faStarRegular
)

// Heavy libraries (KaTeX, Highlight.js, MathLive) are now lazy-loaded in components that use them
// This significantly reduces initial bundle size
// dracula.css is now lazy-loaded in CodeDisplay.vue where it's used

// Import only the most frequently used icons globally to reduce initial bundle size
// Navigation and feature-specific icons are imported directly in their components
import {
  PhPlus,
  PhX,
  PhPencil,
  PhTrash,
  PhSpinnerGap,
  PhArrowsClockwise
} from '@phosphor-icons/vue'

// Detect iOS PWA
const isIOSPWA = () => {
  return (
    (window.navigator as { standalone?: boolean }).standalone === true ||
    (window.matchMedia &&
      window.matchMedia('(display-mode: standalone)').matches &&
      /iPad|iPhone|iPod/.test(navigator.userAgent))
  )
}

const registerServiceWorker = async () => {
  if ('serviceWorker' in navigator) {
    try {
      const registration = await navigator.serviceWorker.register('/sw.js', {
        scope: '/'
      })

      logger.info(`Service worker registered successfully with scope: ${registration.scope}`)

      // Handle service worker updates
      registration.addEventListener('updatefound', () => {
        const newWorker = registration.installing
        newWorker?.addEventListener('statechange', () => {
          if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
            // New version is available
            logger.info('New service worker version available')
            const message = isIOSPWA()
              ? 'New app version available. The app will restart to update.'
              : 'New version available. Update now?'

            if (confirm(message)) {
              if (isIOSPWA()) {
                // iOS PWA: Clear caches but preserve user data
                logger.info('iOS PWA: Clearing caches but preserving localStorage')
                caches
                  .keys()
                  .then((cacheNames) =>
                    Promise.all(cacheNames.map((cacheName) => caches.delete(cacheName)))
                  )
                  .then(() => {
                    newWorker.postMessage({ type: 'SKIP_WAITING' })
                  })
              } else {
                newWorker.postMessage({ type: 'SKIP_WAITING' })
              }
            }
          }
        })
      })

      // Listen for service worker controller change and reload
      navigator.serviceWorker.addEventListener('controllerchange', () => {
        logger.info('Service worker controller changed - reloading page')

        // Check if email verification is in progress using typed storage flag
        const emailVerificationInProgress =
          typedStorage.get(STORAGE_KEYS.EMAIL_VERIFICATION_IN_PROGRESS) === 'true'

        // Also check URL parameters as a fallback
        const currentUrl = window.location.href
        const url = new URL(currentUrl)
        const urlPath = url.pathname
        const urlParams = new URLSearchParams(url.search)
        const isEmailVerificationUrl =
          urlPath === '/verify-email' && urlParams.has('email') && urlParams.has('code')

        // Don't reload if email verification is in progress (either by flag or URL)
        if (emailVerificationInProgress || isEmailVerificationUrl) {
          logger.info('Skipping reload during email verification process')
          return
        }

        if (isIOSPWA()) {
          // iOS PWA: Show instructions to manually close and reopen
          alert(
            'Update complete! For best results, please:\n\n1. Close this app completely (swipe up and swipe away)\n2. Reopen the app from your home screen\n\nThe app will now restart...'
          )

          // Still try the technical reload as backup
          setTimeout(() => {
            const url = new URL(window.location.href)
            url.searchParams.set('v', Date.now().toString())
            url.searchParams.set('ios-update', '1')
            window.location.replace(url.toString())
          }, 1000)
        } else {
          window.location.reload()
        }
      })
    } catch (error) {
      logger.error(`Service worker registration failed`, error)
    }
  }
}

interface ClickOutsideHTMLElement extends HTMLElement {
  clickOutsideEvent?: (event: MouseEvent) => void
}

const clickOutside = {
  beforeMount: (el: ClickOutsideHTMLElement, binding: DirectiveBinding<() => void>) => {
    el.clickOutsideEvent = (event: MouseEvent) => {
      const target = event.target as Node
      if (!(el === target || el.contains(target))) {
        binding.value()
      }
    }
    document.addEventListener('click', el.clickOutsideEvent)
  },
  unmounted: (el: ClickOutsideHTMLElement) => {
    if (el.clickOutsideEvent) {
      document.removeEventListener('click', el.clickOutsideEvent)
    }
  }
}

const focus = {
  mounted: (el: HTMLElement) => {
    el.focus()
  }
}
const router = createRouter({
  history: createWebHistory(),
  routes
})

const app = createApp(App)
const pinia = createPinia()
app.use(pinia)
app.directive('click-outside', clickOutside)
app.directive('focus', focus)
app.component('font-awesome-icon', FontAwesomeIcon)
// Register only the most frequently used icons globally (6 icons)
// All other icons should be imported directly in components for better tree-shaking
app.component('PhPlus', PhPlus)
app.component('PhX', PhX)
app.component('PhPencil', PhPencil)
app.component('PhTrash', PhTrash)
app.component('PhSpinnerGap', PhSpinnerGap)
app.component('PhArrowsClockwise', PhArrowsClockwise)
app.use(Slicksort)
app.use(router)
app.mount('#app')
registerServiceWorker()
