<script setup lang="ts">
import { onMounted, watch } from 'vue'
import { invoke } from '@tauri-apps/api/core'
import TitleBar from './components/TitleBar.vue'
import NavRail from './components/NavRail.vue'
import ToastNotification from './components/ToastNotification.vue'
import { useSettingsStore } from './stores/settings'
import { useToastStore } from './stores/toast'
import { useTimerStore } from './stores/timer'
import { useRecurringStore } from './stores/recurring'
import { loadAndApplyTimerFont } from './utils/fonts'
import { loadAndApplyUIFont } from './utils/uiFonts'
import { useAnnouncer } from './composables/useAnnouncer'
import { audioEngine, DEFAULT_EVENTS } from './utils/audio'
import type { SoundEvent } from './utils/audio'
import TourOverlay from './components/TourOverlay.vue'
import RecurringPromptDialog from './components/RecurringPromptDialog.vue'
import TimerSaveDialog from './components/TimerSaveDialog.vue'
import { useOnboardingStore } from './stores/onboarding'
import { useProjectsStore } from './stores/projects'
import { useInvoicesStore } from './stores/invoices'

const settingsStore = useSettingsStore()
const recurringStore = useRecurringStore()
const timerStore = useTimerStore()
const { announcement } = useAnnouncer()

function getProjectName(projectId?: number): string {
  if (!projectId) return ''
  const projectsStore = useProjectsStore()
  return projectsStore.projects.find(p => p.id === projectId)?.name || ''
}

function getProjectColor(projectId?: number): string {
  if (!projectId) return '#6B7280'
  const projectsStore = useProjectsStore()
  return projectsStore.projects.find(p => p.id === projectId)?.color || '#6B7280'
}

async function registerShortcuts() {
  try {
    const { unregisterAll, register } = await import('@tauri-apps/plugin-global-shortcut')
    await unregisterAll()
    const toggleKey = settingsStore.settings.shortcut_toggle_timer || 'CmdOrCtrl+Shift+T'
    const showKey = settingsStore.settings.shortcut_show_app || 'CmdOrCtrl+Shift+Z'

    await register(toggleKey, () => {
      const timerStore = useTimerStore()
      if (timerStore.isStopped) {
        if (timerStore.selectedProjectId) timerStore.start()
      } else {
        timerStore.stop()
      }
    })

    await register(showKey, async () => {
      const { getCurrentWindow } = await import('@tauri-apps/api/window')
      const win = getCurrentWindow()
      await win.show()
      await win.setFocus()
    })
  } catch (e) {
    console.error('Failed to register shortcuts:', e)
  }
}

function applyTheme() {
  const el = document.documentElement
  const mode = settingsStore.settings.theme_mode || 'dark'
  const accent = settingsStore.settings.accent_color || 'amber'

  if (mode === 'system') {
    const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
    el.setAttribute('data-theme', prefersDark ? 'dark' : 'light')
  } else {
    el.setAttribute('data-theme', mode)
  }
  el.setAttribute('data-accent', accent)
}

function applyMotion() {
  const setting = settingsStore.settings.reduce_motion || 'system'
  const el = document.documentElement
  if (setting === 'on') {
    el.classList.add('reduce-motion')
  } else if (setting === 'off') {
    el.classList.remove('reduce-motion')
  } else {
    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
      el.classList.add('reduce-motion')
    } else {
      el.classList.remove('reduce-motion')
    }
  }
}

onMounted(async () => {
  await settingsStore.fetchSettings()

  const onboardingStore = useOnboardingStore()
  await onboardingStore.load()

  await timerStore.restoreState()

  const zoom = parseInt(settingsStore.settings.ui_zoom) || 100
  const app = document.getElementById('app')
  if (app) {
    (app.style as any).zoom = `${zoom}%`
  }
  applyTheme()
  applyMotion()
  loadAndApplyTimerFont(settingsStore.settings.timer_font || 'JetBrains Mono')

  const dyslexiaMode = settingsStore.settings.dyslexia_mode === 'true'
  if (dyslexiaMode) {
    loadAndApplyUIFont('OpenDyslexic')
  } else {
    const uiFont = settingsStore.settings.ui_font
    if (uiFont && uiFont !== 'Inter') {
      loadAndApplyUIFont(uiFont)
    }
  }

  // Load audio settings
  const soundEnabled = settingsStore.settings.sound_enabled === 'true'
  const soundMode = (settingsStore.settings.sound_mode || 'synthesized') as 'synthesized' | 'system' | 'custom'
  const soundVolume = parseInt(settingsStore.settings.sound_volume) || 70
  let soundEvents: Record<string, boolean> = {}
  try {
    soundEvents = JSON.parse(settingsStore.settings.sound_events || '{}')
  } catch { /* use defaults */ }

  audioEngine.updateSettings({
    enabled: soundEnabled,
    mode: soundMode,
    volume: soundVolume,
    events: { ...DEFAULT_EVENTS, ...soundEvents } as Record<SoundEvent, boolean>,
  })

  // Initialize persistent notifications setting
  const toastStore = useToastStore()
  toastStore.setPersistentNotifications(settingsStore.settings.persistent_notifications === 'true')

  await recurringStore.fetchEntries()
  recurringStore.checkRecurrences()
  setInterval(() => recurringStore.checkRecurrences(), 60000)
  setInterval(() => onboardingStore.detectCompletions(), 5 * 60000)

  // Background calendar sync
  async function syncCalendars() {
    try {
      const sources = await invoke<any[]>('get_calendar_sources')
      for (const source of sources) {
        if (source.source_type === 'url' && source.enabled && source.url) {
          try {
            const resp = await fetch(source.url)
            if (resp.ok) {
              const content = await resp.text()
              await invoke('import_ics_file', { sourceId: source.id, content })
            }
          } catch (e) {
            console.error('Calendar sync failed for', source.name, e)
          }
        }
      }
    } catch (e) {
      console.error('Failed to sync calendars:', e)
    }
  }

  syncCalendars()
  setInterval(syncCalendars, 30 * 60000)

  const invoicesStore = useInvoicesStore()
  await invoicesStore.fetchInvoices()
  await invoicesStore.checkOverdue()

  registerShortcuts()

  window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
    if (settingsStore.settings.theme_mode === 'system') applyTheme()
  })

  window.matchMedia('(prefers-reduced-motion: reduce)').addEventListener('change', () => {
    if (settingsStore.settings.reduce_motion === 'system' || !settingsStore.settings.reduce_motion) {
      applyMotion()
    }
  })
})

watch(() => [settingsStore.settings.theme_mode, settingsStore.settings.accent_color], () => {
  applyTheme()
})

watch(() => settingsStore.settings.reduce_motion, () => {
  applyMotion()
})

watch(() => settingsStore.settings.timer_font, (newFont) => {
  if (newFont) loadAndApplyTimerFont(newFont)
})

watch(() => settingsStore.settings.dyslexia_mode, (val) => {
  if (val === 'true') {
    loadAndApplyUIFont('OpenDyslexic')
  } else {
    const uiFont = settingsStore.settings.ui_font || 'Inter'
    loadAndApplyUIFont(uiFont)
  }
})

watch(() => settingsStore.settings.ui_font, (newFont) => {
  if (settingsStore.settings.dyslexia_mode !== 'true' && newFont) {
    loadAndApplyUIFont(newFont)
  }
})

watch(() => [settingsStore.settings.shortcut_toggle_timer, settingsStore.settings.shortcut_show_app], () => {
  registerShortcuts()
})

watch(() => settingsStore.settings.sound_enabled, (val) => {
  audioEngine.updateSettings({ enabled: val === 'true' })
})

watch(() => settingsStore.settings.sound_mode, (val) => {
  if (val) audioEngine.updateSettings({ mode: val as 'synthesized' | 'system' | 'custom' })
})

watch(() => settingsStore.settings.sound_volume, (val) => {
  audioEngine.updateSettings({ volume: parseInt(val) || 70 })
})

watch(() => settingsStore.settings.sound_events, (val) => {
  if (val) {
    try {
      const parsed = JSON.parse(val)
      audioEngine.updateSettings({ events: { ...DEFAULT_EVENTS, ...parsed } as Record<SoundEvent, boolean> })
    } catch { /* ignore parse errors */ }
  }
})

watch(() => settingsStore.settings.persistent_notifications, (val) => {
  const toastStore = useToastStore()
  toastStore.setPersistentNotifications(val === 'true')
})
</script>

<template>
  <a href="#main-content" class="sr-only sr-only-focusable fixed top-0 left-0 z-[200] bg-accent text-white px-4 py-2 rounded-br-lg">
    Skip to main content
  </a>
  <div class="h-full w-full flex flex-col bg-bg-base">
    <TitleBar />
    <div class="flex-1 flex overflow-hidden">
      <NavRail />
      <main id="main-content" class="flex-1 overflow-auto" tabindex="-1">
        <router-view v-slot="{ Component }">
          <Transition name="page" mode="out-in" :duration="{ enter: 250, leave: 150 }">
            <component :is="Component" :key="$route.path" />
          </Transition>
        </router-view>
      </main>
    </div>
  </div>
  <ToastNotification />
  <RecurringPromptDialog
    :show="recurringStore.pendingPrompt !== null"
    :project-name="getProjectName(recurringStore.pendingPrompt?.project_id)"
    :project-color="getProjectColor(recurringStore.pendingPrompt?.project_id)"
    :task-name="''"
    :description="recurringStore.pendingPrompt?.description || ''"
    :duration="recurringStore.pendingPrompt?.duration || 0"
    :time-of-day="recurringStore.pendingPrompt?.time_of_day || ''"
    @confirm="recurringStore.confirmPrompt()"
    @snooze="recurringStore.snoozePrompt()"
    @skip="recurringStore.skipPrompt()"
  />
  <TimerSaveDialog
    :show="timerStore.showSaveDialog"
    :elapsed-seconds="timerStore.pendingStopDuration"
    :mode="timerStore.saveDialogMode"
    @save="timerStore.handleSaveDialogSave"
    @discard="timerStore.handleSaveDialogDiscard"
    @cancel="timerStore.handleSaveDialogCancel"
  />
  <div id="route-announcer" class="sr-only" aria-live="polite" aria-atomic="true"></div>
  <div id="announcer" class="sr-only" aria-live="assertive" aria-atomic="true">{{ announcement }}</div>
  <TourOverlay />
</template>
