import { defineAsyncComponent } from 'vue'

import AppModalLoadingState from '../../components/shared/AppModalLoadingState.vue'
import AppViewLoadingState from '../../components/shared/AppViewLoadingState.vue'

const appViewLoaders = {
  audit: () => import('../AuditView.vue'),
  budget: () => import('../BudgetCenterView.vue'),
  digitalEmployees: () => import('../DigitalEmployeesView.vue'),
  documents: () => import('../DocumentsCenterView.vue'),
  employees: () => import('../EmployeeManagementView.vue'),
  overview: () => import('../OverviewView.vue'),
  policies: () => import('../PoliciesView.vue'),
  receiptFolder: () => import('../ReceiptFolderView.vue'),
  settings: () => import('../SettingsView.vue'),
  travelCreate: () => import('../TravelReimbursementCreateView.vue'),
  travelDetail: () => import('../TravelRequestDetailView.vue'),
  workbench: () => import('../PersonalWorkbenchView.vue')
}

const appViewPreloadCache = new Map()

const relatedPreloadViews = {
  audit: ['documents', 'policies'],
  budget: ['documents', 'overview'],
  digitalEmployees: ['overview', 'settings'],
  documents: ['travelDetail', 'workbench'],
  employees: ['settings', 'overview'],
  overview: ['workbench', 'documents'],
  policies: ['audit', 'documents'],
  receiptFolder: ['documents', 'workbench'],
  settings: ['digitalEmployees', 'employees'],
  workbench: ['documents', 'receiptFolder']
}

export function preloadAppView(viewId) {
  const normalizedViewId = String(viewId || '').trim()
  const loader = appViewLoaders[normalizedViewId]
  if (!loader) {
    return Promise.resolve(null)
  }
  if (!appViewPreloadCache.has(normalizedViewId)) {
    appViewPreloadCache.set(
      normalizedViewId,
      loader().catch((error) => {
        appViewPreloadCache.delete(normalizedViewId)
        throw error
      })
    )
  }
  return appViewPreloadCache.get(normalizedViewId)
}

export function defineAsyncRouteView(viewId, options = {}) {
  return defineAsyncComponent({
    loader: () => preloadAppView(viewId),
    loadingComponent: options.loadingComponent || AppViewLoadingState,
    delay: options.delay ?? 160,
    timeout: options.timeout ?? 30000,
    suspensible: false
  })
}

export function defineAsyncModalView(viewId) {
  return defineAsyncRouteView(viewId, {
    loadingComponent: AppModalLoadingState,
    delay: 80
  })
}

export function scheduleRelatedAppViewPreload(viewId) {
  const views = relatedPreloadViews[String(viewId || '').trim()] || []
  if (!views.length || typeof window === 'undefined') {
    return
  }
  const runPreload = () => {
    for (const view of views.slice(0, 2)) {
      void preloadAppView(view).catch(() => {})
    }
  }
  if (typeof window.requestIdleCallback === 'function') {
    window.requestIdleCallback(runPreload, { timeout: 1600 })
    return
  }
  window.setTimeout(runPreload, 360)
}
