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 !== 'requests')
  .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: { name: 'app-overview' }
    },
    {
      path: '/app/requests',
      name: 'app-requests',
      component: AppShellRouteView,
      meta: {
        requiresAuth: true,
        appView: 'requests'
      }
    },
    {
      path: '/app/requests/:requestId',
      name: 'app-request-detail',
      component: AppShellRouteView,
      meta: {
        requiresAuth: true,
        appView: 'requests'
      }
    },
    ...appChildRoutes.map((route) => ({
      ...route,
      path: `/app/${route.path}`
    })),
    {
      path: '/:pathMatch(.*)*',
      redirect: '/'
    }
  ]
})

router.beforeEach((to) => {
  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) {
    return checkBackendHealth().then((ok) => {
      if (!ok && to.name !== 'backend-unavailable') {
        return { name: 'backend-unavailable' }
      }

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

      if (ok && typeof to.meta.appView === 'string' && !canAccessAppView(currentUser.value, to.meta.appView)) {
        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
