<template>
  <div id="app">
    <!-- Splash Screen (only on first visit) -->
    <SplashScreen v-if="showSplash" @complete="handleSplashComplete" />

    <!-- Main App Content - only show after splash and routing is complete -->
    <RouterView v-if="!showSplash && isReady" />
    
    <!-- Spotlight command palette (Cmd+K / Ctrl+K) -->
    <SpotlightSearch />

    <!-- CLI popup (F key) -->
    <CLIPopup />

    <!-- App launcher overlay (iframe popup) -->
    <AppLauncherOverlay />

    <!-- Global toast notifications -->
    <ToastStack />

    <!-- Screensaver -->
    <Screensaver />

    <!-- Help guide modal (from spotlight) -->
    <HelpGuideModal
      :show="spotlightStore.helpModal.show"
      :title="spotlightStore.helpModal.title"
      :content="spotlightStore.helpModal.content"
      :related-path="spotlightStore.helpModal.relatedPath"
      @close="spotlightStore.closeHelpModal()"
    />
    
    <!-- PWA Update Prompt -->
    <PWAUpdatePrompt />

    <!-- PWA Install Prompt (Install app, not just Add to Home Screen) -->
    <PWAInstallPrompt />

    <!-- Toast notifications - top right, glass style, any page -->
    <Teleport to="body">
      <Transition name="toast">
        <div
          v-if="toastMessage.show"
          @click="messageToast.dismissToastAndOpenMessages"
          class="fixed top-20 right-4 left-4 z-[100] w-auto max-w-md cursor-pointer rounded-xl p-4 transition-all hover:border-white/30 hover:shadow-2xl md:top-6 md:right-6 md:left-auto md:max-w-md toast-glass"
        >
          <div class="flex items-start gap-3">
            <div class="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-orange-500/20">
              <svg class="h-5 w-5 text-orange-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
              </svg>
            </div>
            <div class="min-w-0 flex-1">
              <p class="text-sm font-medium text-white">New message</p>
              <p class="mt-0.5 text-sm text-white/70 line-clamp-2">{{ toastMessage.text }}</p>
              <p class="mt-1 text-xs text-orange-400">Click to view</p>
            </div>
          </div>
        </div>
      </Transition>
    </Teleport>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import SplashScreen from './components/SplashScreen.vue'
import PWAUpdatePrompt from './components/PWAUpdatePrompt.vue'
import PWAInstallPrompt from './components/PWAInstallPrompt.vue'
import SpotlightSearch from './components/SpotlightSearch.vue'
import CLIPopup from './components/CLIPopup.vue'
import AppLauncherOverlay from './components/AppLauncherOverlay.vue'
import ToastStack from './components/ToastStack.vue'
import Screensaver from './components/Screensaver.vue'
import HelpGuideModal from './components/HelpGuideModal.vue'
import { useControllerNav } from '@/composables/useControllerNav'
import { playKeyboardTypingSound } from '@/composables/useLoginSounds'
import { useSpotlightStore } from '@/stores/spotlight'
import { useCLIStore } from '@/stores/cli'
import { useMessageToast } from '@/composables/useMessageToast'
import { useAppStore } from '@/stores/app'
import { useScreensaverStore } from '@/stores/screensaver'
import { useUIModeStore } from '@/stores/uiMode'

const router = useRouter()
const screensaverStore = useScreensaverStore()
const spotlightStore = useSpotlightStore()
const cliStore = useCLIStore()
const appStore = useAppStore()
const uiModeStore = useUIModeStore()
const messageToast = useMessageToast()
const toastMessage = messageToast.toastMessage

useControllerNav()

// Start/stop message polling when auth state changes
watch(() => appStore.isAuthenticated, (authenticated) => {
  if (authenticated) {
    messageToast.startPolling()
    screensaverStore.resetInactivityTimer()
  } else {
    messageToast.stopPolling()
    toastMessage.value = { show: false, text: '' }
    screensaverStore.clearInactivityTimer()
    screensaverStore.deactivate()
  }
}, { immediate: true })

// Reset screensaver inactivity on user activity (when authenticated)
function onUserActivity() {
  if (appStore.isAuthenticated && !screensaverStore.isActive) {
    screensaverStore.resetInactivityTimer()
  }
}

function onKeyDown(e: KeyboardEvent) {
  const isMac = navigator.platform.toUpperCase().includes('MAC')
  const mod = isMac ? e.metaKey : e.ctrlKey
  // Cmd+K / Ctrl+K only (modifier required - avoids accidental trigger when typing)
  const target = e.target as HTMLElement
  const isInput = target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable
  if (mod && e.key === 'k') {
    e.preventDefault()
    spotlightStore.toggle()
    return
  }
  // F key - CLI popup (skip when in input or modifier held)
  if ((e.key === 'f' || e.key === 'F') && !isInput && !mod && !e.altKey) {
    e.preventDefault()
    cliStore.toggle()
    return
  }
  // Cmd+1/2/3 - switch UI mode (skip when in input)
  if (mod && !isInput && appStore.isAuthenticated) {
    if (e.key === '1') { e.preventDefault(); uiModeStore.setMode('easy'); router.push('/dashboard'); return }
    if (e.key === '2') { e.preventDefault(); uiModeStore.setMode('gamer'); router.push('/dashboard'); return }
    if (e.key === '3') { e.preventDefault(); router.push('/dashboard/chat'); return }
  }
  // Cmd+M / Ctrl+M - cycle UI mode (skip when in input)
  if (mod && (e.key === 'm' || e.key === 'M') && !isInput && appStore.isAuthenticated) {
    e.preventDefault()
    uiModeStore.cycleMode()
    router.push('/dashboard')
    return
  }
  // 's' key activates screensaver when authenticated (skip if typing in input)
  if (e.key === 's' || e.key === 'S') {
    if (!isInput && appStore.isAuthenticated && !screensaverStore.isActive) {
      e.preventDefault()
      screensaverStore.activate()
    }
  }
  // Keyboard typing sound - plays on any character typed in inputs (global)
  if (isInput && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
    playKeyboardTypingSound()
  }
}

const route = useRoute()
// Start with splash hidden — onMounted decides whether to show it
const showSplash = ref(false)
const isReady = ref(false)

/**
 * Determine if splash screen should be shown
 * Splash is skipped if:
 * - User has already seen the intro
 * - User is on a direct route (refresh/bookmark)
 */
// Fix Chromium backdrop-filter rendering bug: when tab loses/regains focus,
// the compositor fails to repaint backdrop-filter layers over animated
// fixed-position overlays (body::before/after with mix-blend-mode).
// On return: strip backdrop-filter via class, wait a frame, then restore.
function onVisibilityChange() {
  if (document.hidden) {
    document.documentElement.classList.add('tab-hidden')
  } else {
    // Step 1: strip backdrop-filter while animations stay paused (tab-hidden)
    document.documentElement.classList.add('no-backdrop')
    // Step 2: restore backdrop-filter over static content (clean compositor rebuild)
    // Use setTimeout — Chromium batches rAFs on tab return
    setTimeout(() => {
      document.documentElement.classList.remove('no-backdrop')
      // Step 3: resume animations after backdrop-filter layers are established
      requestAnimationFrame(() => {
        document.documentElement.classList.remove('tab-hidden')
      })
    }, 50)
  }
}

onMounted(async () => {
  document.addEventListener('visibilitychange', onVisibilityChange)
  window.addEventListener('keydown', onKeyDown, true)
  window.addEventListener('mousemove', onUserActivity)
  window.addEventListener('mousedown', onUserActivity)
  window.addEventListener('keydown', onUserActivity)
  window.addEventListener('touchstart', onUserActivity)
  const seenIntro = localStorage.getItem('neode_intro_seen') === '1'
  const isDirectRoute = route.path !== '/'
  const fromBoot = sessionStorage.getItem('archipelago_from_boot') === '1'
  if (fromBoot) sessionStorage.removeItem('archipelago_from_boot')
  if (import.meta.env.DEV) console.log('[App] onMounted — seenIntro:', seenIntro, 'fromBoot:', fromBoot)

  if (fromBoot && !seenIntro) {
    // Coming from boot screen — show the full splash intro (Enter to Exit → typing → logo)
    showSplash.value = true
  } else if (!seenIntro && !isDirectRoute && import.meta.env.VITE_DEV_MODE !== 'boot') {
    // Normal first visit (not boot mode) — show splash intro
    showSplash.value = true
  } else {
    // Already seen intro, direct route, or boot mode (boot screen handles intro)
    showSplash.value = false
    document.body.classList.add('splash-complete')
    await router.isReady()
    isReady.value = true
  }
})

onBeforeUnmount(() => {
  document.removeEventListener('visibilitychange', onVisibilityChange)
  window.removeEventListener('keydown', onKeyDown, true)
  window.removeEventListener('mousemove', onUserActivity)
  window.removeEventListener('mousedown', onUserActivity)
  window.removeEventListener('keydown', onUserActivity)
  window.removeEventListener('touchstart', onUserActivity)
})

/**
 * Handle splash screen completion
 * Routes user directly to appropriate screen based on onboarding status (from backend)
 */
async function handleSplashComplete() {
  showSplash.value = false
  document.body.classList.add('splash-complete')
  isReady.value = true
  sessionStorage.setItem('archipelago_from_splash', '1')

  const devMode = import.meta.env.VITE_DEV_MODE
  if (devMode === 'setup' || devMode === 'existing') {
    router.push('/login').catch(() => {})
    return
  }

  try {
    const { isOnboardingComplete } = await import('@/composables/useOnboarding')
    const seenOnboarding = await isOnboardingComplete()
    const destination = seenOnboarding ? '/login' : '/onboarding/intro'
    router.push(destination).catch(() => {})
  } catch {
    router.push('/onboarding/intro').catch(() => {})
  }
}
</script>

<style>
/* Global styles are in style.css */
</style>
