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',
      },
    },
    {
      path: '/system',
      component: () => import('@/views/system/SystemAdminLayoutView.vue'),
      meta: {
        titleKey: 'nav.systemSettings',
        permission: 'SYSTEM_ADMIN_CONSOLE_ACCESS',
      },
      children: [
        {
          path: 'users',
          name: 'system-users',
          component: () => import('@/views/system/SystemUsersView.vue'),
          meta: {
            titleKey: 'nav.systemUsers',
            permission: 'SYSTEM_USER_MANAGE',
          },
        },
        {
          path: 'roles',
          name: 'system-roles',
          component: () => import('@/views/system/SystemRolesView.vue'),
          meta: {
            titleKey: 'nav.systemRoles',
            permission: 'SYSTEM_ROLE_MANAGE',
          },
        },
        {
          path: 'menus',
          name: 'system-menus',
          component: () => import('@/views/system/SystemMenusView.vue'),
          meta: {
            titleKey: 'nav.systemMenus',
            permission: 'SYSTEM_MENU_MANAGE',
          },
        },
        {
          path: 'hotels',
          name: 'system-hotels',
          component: () => import('@/views/system/SystemHotelsView.vue'),
          meta: {
            titleKey: 'nav.systemHotels',
            permission: 'HOTEL_MANAGE',
          },
        },
        {
          path: 'audits',
          name: 'system-audits',
          component: () => import('@/views/system/SystemAuditsView.vue'),
          meta: {
            titleKey: 'nav.systemAudits',
            permission: 'SYSTEM_ADMIN_CONSOLE_ACCESS',
          },
        },
      ],
    },
    {
      path: '/:pathMatch(.*)*',
      name: 'not-found',
      component: () => import('@/views/system/RouteNotFoundView.vue'),
      meta: {
        titleKey: 'notFound.title',
      },
    },
  ],
})

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',
      }
    }

    if (to.path === '/system') {
      return resolveSystemAdminEntryPath(authStore)
    }

    return true
  }
}

function resolveSystemAdminEntryPath(authStore: AuthStore): string {
  if (authStore.hasPermission('SYSTEM_USER_MANAGE')) {
    return '/system/users'
  }
  if (authStore.hasPermission('SYSTEM_ROLE_MANAGE')) {
    return '/system/roles'
  }
  if (authStore.hasPermission('SYSTEM_MENU_MANAGE')) {
    return '/system/menus'
  }
  if (authStore.hasPermission('HOTEL_MANAGE')) {
    return '/system/hotels'
  }
  return '/system/audits'
}
