import { useEffect, useState } from 'react'
import { Provider as JotaiProvider } from 'jotai'
import { useTranslation } from 'react-i18next'
import './i18n'
import './styles/themes.css'
import './styles/globals.css'
import './styles/layout.css'
import { TopBar } from '@renderer/components/layout/TopBar'
import { HomePage } from '@renderer/components/home/HomePage'
import { EditorLayout } from '@renderer/components/layout/EditorLayout'
import { SettingsPage } from '@renderer/components/settings/SettingsPage'
import { OnboardingWizard } from '@renderer/components/onboarding/OnboardingWizard'
import { useAppStore } from '@renderer/stores/useAppStore'
import { useSettingsStore } from '@renderer/stores/useSettingsStore'
import { useTabStore } from '@renderer/stores/useTabStore'
import { useBookStore } from '@renderer/stores/useBookStore'
import { useEditStore } from '@renderer/stores/useEditStore'
import { SearchModal } from '@renderer/components/search/SearchModal'
import { InspirationModal } from '@renderer/components/inspiration/InspirationModal'
import { ImportBookModal } from '@renderer/components/import/ImportBookModal'
import { ExportAllModal } from '@renderer/components/export/ExportAllModal'
import { ReadModeOverlay } from '@renderer/components/read/ReadModeOverlay'
import { FocusModeOverlay } from '@renderer/components/focus/FocusModeOverlay'
import { NamingCheckModal } from '@renderer/components/ai/NamingCheckModal'
import { useSearchStore } from '@renderer/stores/useSearchStore'
import { useReferenceStore } from '@renderer/stores/useReferenceStore'
import { flushEditorSave } from '@renderer/components/editor/TipTapEditor'
import { getEditorTextForTts } from '@renderer/lib/editor-commands'
import { insertLandmarkInEditor } from '@renderer/lib/editor-commands'
import { isSpeaking, speakText, stopSpeaking } from '@renderer/lib/tts-controller'
import { useAiStore } from '@renderer/stores/useAiStore'
import { useExportStore } from '@renderer/stores/useExportStore'
import { ipcCall } from '@renderer/lib/ipc-client'

function AppInner(): React.JSX.Element {
  const { t } = useTranslation()
  const view = useAppStore((s) => s.view)
  const toast = useAppStore((s) => s.toast)
  const focusMode = useAppStore((s) => s.focusMode)
  const namingCheckOpen = useAppStore((s) => s.namingCheckOpen)
  const setFocusMode = useAppStore((s) => s.setFocusMode)
  const setNamingCheckOpen = useAppStore((s) => s.setNamingCheckOpen)
  const showToast = useAppStore((s) => s.showToast)
  const setView = useAppStore((s) => s.setView)
  const { loaded, onboardingCompleted, load: loadSettings } = useSettingsStore()
  const loadBooks = useBookStore((s) => s.loadBooks)
  const { activeTabId, openTabs } = useTabStore()
  const openBook = useBookStore((s) => s.openBook)
  const [showOnboarding, setShowOnboarding] = useState(false)

  useEffect(() => {
    void (async () => {
      await loadSettings()
      await loadBooks()
    })()
  }, [loadSettings, loadBooks])

  useEffect(() => {
    if (loaded && !onboardingCompleted) setShowOnboarding(true)
  }, [loaded, onboardingCompleted])

  useEffect(() => {
    return window.electronAPI.onGoalNotification((payload) => {
      showToast(t(payload.messageKey, payload.messageParams))
    })
  }, [showToast, t])

  useEffect(() => {
    const openSearch = (): void => useSearchStore.getState().setOpen(true)
    const openLandmarks = (): void => useAppStore.getState().setLandmarksModalOpen(true)
    const openInspiration = (): void => {
      useAppStore.getState().setInspirationModalOpen(true)
    }
    const onInsertLandmark = (e: Event): void => {
      const label = (e as CustomEvent<{ label: string }>).detail?.label
      if (!label) return
      const { currentBookId } = useBookStore.getState()
      const target = useEditStore.getState().target
      if (!currentBookId || target?.kind !== 'chapter') return
      insertLandmarkInEditor({ label, landmarkType: 'todo' })
      void ipcCall(() =>
        window.electronAPI.bookmark.create(currentBookId, target.id, 0, label, 'todo')
      )
    }
    const onSetAiOnline = (e: Event): void => {
      const online = (e as CustomEvent<{ online: boolean }>).detail?.online
      if (typeof online === 'boolean') useAiStore.setState({ online })
    }
    const onFlushEditor = (): void => {
      void flushEditorSave()
    }
    window.addEventListener('bilin:e2e-open-search', openSearch)
    window.addEventListener('bilin:e2e-open-landmarks', openLandmarks)
    window.addEventListener('bilin:e2e-capture-inspiration', openInspiration)
    window.addEventListener('bilin:e2e-insert-landmark', onInsertLandmark)
    window.addEventListener('bilin:e2e-set-ai-online', onSetAiOnline)
    window.addEventListener('bilin:e2e-flush-editor', onFlushEditor)
    return () => {
      window.removeEventListener('bilin:e2e-open-search', openSearch)
      window.removeEventListener('bilin:e2e-open-landmarks', openLandmarks)
      window.removeEventListener('bilin:e2e-capture-inspiration', openInspiration)
      window.removeEventListener('bilin:e2e-insert-landmark', onInsertLandmark)
      window.removeEventListener('bilin:e2e-set-ai-online', onSetAiOnline)
      window.removeEventListener('bilin:e2e-flush-editor', onFlushEditor)
    }
  }, [])

  useEffect(() => {
    const unsub = window.electronAPI.onShortcutTriggered(async (action) => {
      if (action === 'saveChapter') {
        try {
          await flushEditorSave(true)
        } catch {
          showToast(t('toast.saveFailed'))
        }
        return
      }
      if (action === 'newChapter') {
        if (view !== 'editor') return
        const { currentBookId, activeVolumeId, refreshChapters, setSelectedChapter } = useBookStore.getState()
        if (!currentBookId || !activeVolumeId) return
        await flushEditorSave()
        const ch = await ipcCall(() =>
          window.electronAPI.chapter.create(currentBookId, activeVolumeId, t('editor.newChapter'))
        )
        await refreshChapters()
        setSelectedChapter(ch.id)
        return
      }
      if (action === 'closeTab') {
        const tab = openTabs.find((x) => x.id === activeTabId)
        if (!tab) return
        const next = useTabStore.getState().closeTab(tab.id)
        if (next) {
          const nt = useTabStore.getState().openTabs.find((x) => x.id === next)
          if (nt?.type === 'book' && nt.bookId) {
            await openBook(nt.bookId)
            setView('editor')
          } else setView('settings')
        } else setView('home')
        return
      }
      if (action === 'globalSearch') {
        useSearchStore.getState().setOpen(true)
        return
      }
      if (action === 'openReference') {
        useReferenceStore.getState().setOpen(true)
        return
      }
      if (action === 'openLandmarks') {
        useAppStore.getState().setLandmarksModalOpen(true)
        return
      }
      if (action === 'insertLandmark') {
        if (view !== 'editor') return
        document.querySelector<HTMLButtonElement>('[data-testid="insert-landmark"]')?.click()
        return
      }
      if (action === 'captureInspiration') {
        useAppStore.getState().setInspirationModalOpen(true)
        return
      }
      if (action === 'exportBook') {
        if (view !== 'editor') return
        const target = useEditStore.getState().target
        if (target?.kind !== 'chapter') return
        useExportStore.getState().openModal()
        return
      }
      if (action === 'focusMode') {
        if (view !== 'editor') return
        setFocusMode(!useAppStore.getState().focusMode)
        return
      }
      if (action === 'toggleTTS') {
        if (view !== 'editor') return
        if (isSpeaking()) {
          stopSpeaking()
          showToast(t('tts.stopped'))
          return
        }
        const text = getEditorTextForTts()
        if (!text.trim()) {
          showToast(t('tts.noText'))
          return
        }
        speakText(text)
        showToast(t('tts.started'))
        return
      }
      showToast(t('feature.comingSoon'))
    })
    return unsub
  }, [view, activeTabId, openTabs, openBook, setView, setFocusMode, showToast, t])

  const handleOnboardingComplete = (): void => {
    setShowOnboarding(false)
  }

  return (
    <div id="app" className={focusMode ? 'focus-mode' : undefined} data-testid="app-root">
      <TopBar />
      <div id="main-area">
        {view === 'home' && <HomePage />}
        {view === 'editor' && <EditorLayout />}
        {view === 'settings' && <SettingsPage />}
      </div>
      <FocusModeOverlay />
      <ReadModeOverlay />
      {showOnboarding && <OnboardingWizard onComplete={handleOnboardingComplete} />}
      <SearchModal />
      <InspirationModal />
      <ImportBookModal />
      <ExportAllModal />
      <NamingCheckModal open={namingCheckOpen} onClose={() => setNamingCheckOpen(false)} />
      {toast && <div className="toast">{toast}</div>}
    </div>
  )
}

export default function App(): React.JSX.Element {
  return (
    <JotaiProvider>
      <AppInner />
    </JotaiProvider>
  )
}
