import { createRouter, createWebHistory } from 'vue-router'

import { checkBackendHealth } from '../composables/useBackendHealth.js'
import { appViews } from '../composables/useNavigation.js'
import { useSystemState } from '../composables/useSystemState.js'
import { canAccessAppView } from '../utils/accessControl.js'
import AppShellRouteView from '../views/AppShellRouteView.vue'
import BackendUnavailableRouteView from '../views/BackendUnavailableRouteView.vue'
import LoginRouteView from '../views/LoginRouteView.vue'
import SetupRouteView from '../views/SetupRouteView.vue'

const appChildRoutes = appViews
  .filter((view) => view !== 'documents')
  .map((view) => ({
    path: view,
    name: `app-${view}`,
    component: AppShellRouteView,
    meta: {
      requiresAuth: true,
      appView: view
    }
  }))

const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/',
      name: 'root',
      redirect: () => {
        const { resolveEntryRoute } = useSystemState()
        return resolveEntryRoute()
      }
    },
    {
      path: '/setup',
      name: 'setup',
      component: SetupRouteView
    },
    {
      path: '/login',
      name: 'login',
      component: LoginRouteView
    },
    {
      path: '/backend-unavailable',
      name: 'backend-unavailable',
      component: BackendUnavailableRouteView
    },
    {
      path: '/app',
      redirect: () => {
        const { resolveEntryRoute } = useSystemState()
        return resolveEntryRoute()
      }
    },
    {
      path: '/app/documents',
      name: 'app-documents',
      component: AppShellRouteView,
      meta: {
        requiresAuth: true,
        appView: 'documents'
      }
    },
    {
      path: '/app/documents/:requestId',
      name: 'app-document-detail',
      component: AppShellRouteView,
      meta: {
        requiresAuth: true,
        appView: 'documents'
      }
    },
    {
      path: '/app/requests',
      redirect: { name: 'app-documents' }
    },
    {
      path: '/app/requests/:requestId',
      redirect: (to) => ({
        name: 'app-document-detail',
        params: { requestId: to.params.requestId },
        query: to.query,
        hash: to.hash
      })
    },
    {
      path: '/app/approval',
      redirect: { name: 'app-documents' }
    },
    {
      path: '/app/archive',
      redirect: { name: 'app-documents' }
    },
    {
      path: '/app/logs/:logKind/:logId',
      redirect: (to) => ({
        name: 'app-log-detail',
        params: { logKind: to.params.logKind, logId: to.params.logId },
        query: to.query,
        hash: to.hash
      })
    },
    {
      path: '/app/logs',
      redirect: { name: 'app-settings', query: { section: 'systemLogs' } }
    },
    {
      path: '/app/settings/logs/:logKind/:logId',
      name: 'app-log-detail',
      component: AppShellRouteView,
      meta: {
        requiresAuth: true,
        appView: 'settings'
      }
    },
    ...appChildRoutes.map((route) => ({
      ...route,
      path: `/app/${route.path}`
    })),
    {
      path: '/:pathMatch(.*)*',
      redirect: '/'
    }
  ]
})

function isAuthenticatedAppNavigation(to, from) {
  return Boolean(to.meta.requiresAuth && from.meta.requiresAuth && from.name !== 'backend-unavailable')
}

function scheduleBackgroundBackendHealthCheck() {
  void checkBackendHealth({ allowStaleOnTimeout: true }).then((ok) => {
    const currentRoute = router.currentRoute.value
    if (!ok && currentRoute.meta.requiresAuth && currentRoute.name !== 'backend-unavailable') {
      void router.replace({ name: 'backend-unavailable' })
    }
  })
}

router.beforeEach((to, from) => {
  if (to.name === 'app-documents' && from.name !== 'app-document-detail') {
    if (typeof window !== 'undefined' && window.localStorage) {
      window.localStorage.removeItem('x-financial.documents.scope')
    }
  }

  const { currentUser, isInitialized, loggedIn, resolveEntryRoute, syncAuthSession } = useSystemState()
  const authActive = syncAuthSession({ notify: Boolean(to.meta.requiresAuth) })

  if (!isInitialized.value) {
    if (to.name !== 'setup') {
      return { name: 'setup' }
    }

    return true
  }

  if (to.name === 'setup') {
    return resolveEntryRoute()
  }

  if (authActive && to.meta.requiresAuth) {
    if (typeof to.meta.appView === 'string' && !canAccessAppView(currentUser.value, to.meta.appView)) {
      return resolveEntryRoute()
    }

    if (isAuthenticatedAppNavigation(to, from)) {
      scheduleBackgroundBackendHealthCheck()
      return true
    }

    return checkBackendHealth({ allowStaleOnTimeout: true }).then((ok) => {
      if (!ok && to.name !== 'backend-unavailable') {
        return { name: 'backend-unavailable' }
      }

      if (ok && to.name === 'backend-unavailable') {
        return resolveEntryRoute()
      }

      return true
    })
  }

  if (!authActive && to.meta.requiresAuth) {
    return {
      name: 'login',
      query: {
        redirect: to.fullPath
      }
    }
  }

  if (authActive && to.name === 'login') {
    return resolveEntryRoute()
  }

  if (to.name === 'root') {
    return resolveEntryRoute()
  }

  return true
})

export default router
