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

import { useAuthStore } from '@/stores/authStore'
import type { AuthPermissionCode } from '@/types/auth'
import { resolveAuthenticatedEntryPath, resolveLoginRedirectPath } from '@/utils/authNavigation'

type AuthStore = ReturnType<typeof useAuthStore>
type AppRouteMeta = {
  public?: boolean
  layout?: 'plain' | 'app'
  permission?: AuthPermissionCode
}

export const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/',
      name: 'home',
      component: {
        name: 'HomeRedirectView',
        render: () => null,
      },
    },
    {
      path: '/login',
      name: 'login',
      component: () => import('@/views/auth/LoginView.vue'),
      meta: {
        public: true,
        layout: 'plain',
        titleKey: 'auth.loginTitle',
      },
    },
    {
      path: '/unauthorized',
      name: 'unauthorized',
      component: () => import('@/views/auth/UnauthorizedView.vue'),
      meta: {
        titleKey: 'auth.unauthorizedTitle',
      },
    },
    {
      path: '/reservation/workbench',
      redirect: '/reservation/orders',
    },
    {
      path: '/reservation/orders',
      name: 'reservation-order-list',
      component: () => import('@/views/reservation/ReservationOrderListView.vue'),
      meta: {
        titleKey: 'nav.orders',
        permission: 'RESERVATION_ORDER_READ',
      },
    },
    {
      path: '/reservation/tasks',
      name: 'reservation-task-list',
      component: () => import('@/views/reservation/ReservationTaskListView.vue'),
      meta: {
        titleKey: 'nav.taskQueue',
        permission: 'RESERVATION_TASK_READ',
      },
    },
    {
      path: '/reservation/orders/:orderId',
      name: 'reservation-order-detail',
      component: () => import('@/views/reservation/ReservationOrderDetailView.vue'),
      meta: {
        titleKey: 'nav.orderDetail',
        permission: 'RESERVATION_ORDER_READ',
      },
    },
    {
      path: '/reservation/tasks/:taskId',
      name: 'reservation-task-detail',
      component: () => import('@/views/reservation/ReservationTaskDetailView.vue'),
      meta: {
        titleKey: 'nav.taskDetail',
        permission: 'RESERVATION_TASK_READ',
      },
    },
    {
      path: '/reservation/source-messages/:sourceMessageId/conversation',
      name: 'reservation-source-message-conversation',
      component: () => import('@/views/reservation/ReservationSourceMessageConversationView.vue'),
      meta: {
        titleKey: 'nav.sourceMessageConversation',
        permission: 'SOURCE_MESSAGE_ORIGINAL_READ',
      },
    },
    {
      path: '/debug/eml-superagent',
      name: 'debug-eml-superagent',
      component: () => import('@/views/debug/DebugEmlSuperAgentRunView.vue'),
      meta: {
        titleKey: 'debugEml.title',
        permission: 'SYSTEM_DEBUG_EML_RUN',
      },
    },
  ],
})

router.beforeEach(createAuthGuard())

export function createAuthGuard(resolveAuthStore: () => AuthStore = () => useAuthStore()) {
  return async (to: RouteLocationNormalized) => {
    const authStore = resolveAuthStore()
    const meta = to.meta as AppRouteMeta

    if (!authStore.restoreAttempted && authStore.hasStoredToken()) {
      await authStore.restoreFromSession()
    }

    if (meta.public) {
      if (to.name === 'login' && authStore.isAuthenticated) {
        return resolveLoginRedirectPath(to.query.redirect, authStore.firstMenuPath)
      }
      return true
    }

    if (!authStore.isAuthenticated) {
      return {
        path: '/login',
        query: {
          redirect: to.fullPath,
        },
      }
    }

    if (to.path === '/') {
      return resolveAuthenticatedEntryPath(authStore.firstMenuPath)
    }

    if (meta.permission && !authStore.hasPermission(meta.permission)) {
      return {
        name: 'unauthorized',
      }
    }

    return true
  }
}
