import { createApp } from 'vue'
import { createPinia } from 'pinia'
import router from '@/router'
import { setupVueQuery } from '@/shared/plugins/queryClient'
import { i18n } from '@/i18n'
import '@/assets/styles/main.css'
import App from '@/App.vue'

import { createBroadcastPlugin, initMultiWindow } from '@/shared/plugins/broadcastSync'
import { installMockApi } from '@/mocks'

// Dev-only: when VITE_MOCK_DATA=true, patch fetch to serve curated fixtures
// for OTC / Semantic / CeDeFi before any service fires. No-op in production.
installMockApi()

// Hard-fail if a dev-only auth bypass leaked into a production build.
// VITE_* env values are inlined at `vite build` time, so the only way to
// catch this is a runtime assert before mount. import.meta.env.PROD is
// true for default production builds and false for dev/sandbox modes.
if (import.meta.env.PROD && import.meta.env.VITE_DEV_AUTH_DISABLED === 'true') {
  const msg =
    'FATAL: VITE_DEV_AUTH_DISABLED=true in a production build. ' +
    'Dev auth bypass must never ship to end users. Aborting boot.'
  const pre = document.createElement('pre')
  pre.style.fontFamily = 'ui-monospace, monospace'
  pre.style.padding = '24px'
  pre.style.color = '#8A2B1E'
  pre.textContent = msg
  document.body.replaceChildren(pre)
  throw new Error(msg)
}

const app = createApp(App)
const pinia = createPinia()

// Sync sharedSymbol store across browser windows via BroadcastChannel
pinia.use(createBroadcastPlugin(['sharedSymbol', 'panelLink']))

app.use(pinia)
app.use(router)
app.use(i18n)
setupVueQuery(app)

// Register this window in multi-window registry
initMultiWindow()

// One-time cleanup of legacy auth storage keys
localStorage.removeItem('nyquist_api_key')
localStorage.removeItem('rudata_credentials')
// Remove legacy cbondsPassword if stored
try {
  const s = localStorage.getItem('app_settings')
  if (s) {
    const p = JSON.parse(s)
    if (p?.api?.cbondsPassword) {
      delete p.api.cbondsPassword
      localStorage.setItem('app_settings', JSON.stringify(p))
    }
  }
} catch { /* ignore */ }

// Initialize theme
import { useThemeStore, useAppearanceStore } from '@/stores'
const themeStore = useThemeStore()
themeStore.initTheme()

// Apply saved workspace appearance (accent / density / font scale) before mount.
// The store applies its persisted values to <html> on creation, so instantiating
// it here restores the user's look without a visible re-style flash.
useAppearanceStore()

// Enhanced smooth scrolling for better performance
if ('scrollBehavior' in document.documentElement.style) {
  // Native smooth scrolling is supported
  document.documentElement.style.scrollBehavior = 'smooth'
} else {
  // Polyfill for browsers that don't support smooth scrolling
  const smoothScrollPolyfill = () => {
    const elements = document.querySelectorAll('[data-smooth-scroll]')
    elements.forEach((el) => {
      el.addEventListener('click', (e) => {
        const target = (e.target as HTMLElement).getAttribute('href')
        if (target && target.startsWith('#')) {
          e.preventDefault()
          const targetElement = document.querySelector(target)
          if (targetElement) {
            targetElement.scrollIntoView({
              behavior: 'smooth',
              block: 'start'
            })
          }
        }
      })
    })
  }
  smoothScrollPolyfill()
}

// Возврат из bfcache: браузер воскрешает страницу целиком из снимка, минуя
// навигацию. Сторож router.beforeEach при этом НЕ срабатывает, потому что
// маршрут не менялся — и после выхода из аккаунта кнопка «вперёд» возвращает
// отрисованный рабочий стол со всеми уже загруженными цифрами. Новые запросы
// к API уходят без токена и получают 401 (getApiKey читает localStorage в
// момент вызова, а он очищен), то есть сессию не угнать — но то, что было на
// экране, показывается любому, кто взял устройство после выхода.
//
// event.persisted истинно ТОЛЬКО при восстановлении из bfcache, поэтому
// обычные загрузки страницы эта проверка не трогает.
// Выход в одной вкладке не выкидывал из остальных: сторож маршрутов
// срабатывает только при навигации, а открытая соседняя вкладка продолжала
// показывать рабочий стол с данными. Событие storage приходит во ВСЕ вкладки,
// кроме той, что внесла изменение, — ровно то, что нужно.
//
// Перезагрузка, а не переход по маршруту: нужно стереть и хранилища Pinia,
// в которых лежат уже загруженные цифры. Их при выходе никто не чистит —
// ни одного $reset в дереве нет.
window.addEventListener('storage', (event) => {
  if (event.key !== 'nyquist_access_token' || event.newValue !== null) return
  const isPublic = ['/', '/auth', '/marketing', '/demo', '/docs', '/pricing'].includes(
    window.location.pathname,
  )
  if (!isPublic) window.location.replace('/auth')
})

window.addEventListener('pageshow', (event) => {
  if (!event.persisted) return
  const hasToken = !!localStorage.getItem('nyquist_access_token')
  const isPublic = ['/', '/auth', '/marketing', '/demo', '/docs', '/pricing'].includes(
    window.location.pathname,
  )
  if (hasToken || isPublic) return
  // Именно перезагрузка, а не router.push: страница пришла из снимка вместе с
  // отрисованным состоянием и наполненными хранилищами, и переход по маршруту
  // оставил бы их в памяти. Нужен чистый документ.
  window.location.replace('/auth')
})

app.mount('#app')


