import { computed, type Ref } from 'vue'
import { useRoute } from 'vue-router'

import { Visibility, routes, type LayoutRoute } from '@/plugins/routesLayout'
import { ROLE_ADMIN, hasRole, type CurrentUser } from '@/services/authSession'

function normalizeRoutePath(path: string) {
  if (!path || path === '/') {
    return '/'
  }

  return path.endsWith('/') ? path.slice(0, -1) : path
}

function isWithinRoutePath(currentPath: string, targetPath: string) {
  const normalizedCurrent = normalizeRoutePath(currentPath)
  const normalizedTarget = normalizeRoutePath(targetPath)

  if (normalizedTarget === '/') {
    return normalizedCurrent === '/'
  }

  return (
    normalizedCurrent === normalizedTarget ||
    normalizedCurrent.startsWith(`${normalizedTarget}/`)
  )
}

function resolveVisibilityRoutes(path: string, visibilityRoute?: string | string[]) {
  if (Array.isArray(visibilityRoute)) {
    return visibilityRoute.map((entry) => entry.trim()).filter((entry) => entry.length > 0)
  }

  const normalized = visibilityRoute?.trim()
  if (normalized && normalized.length > 0) {
    return [normalized]
  }

  return [path]
}

function isVisible(item: LayoutRoute, currentPath: string, user: CurrentUser | null) {
  switch (item.visible) {
    case Visibility.Public:
      return true
    case Visibility.Authenticated:
      return user !== null
    case Visibility.Unauthenticated:
      return user === null
    case Visibility.Authorized:
      if (!user) {
        return false
      }
      if (!item.requiredRoles || item.requiredRoles.length === 0) {
        return true
      }
      return item.requiredRoles.every((role) => hasRole(user, role))
    case Visibility.Route:
      return resolveVisibilityRoutes(item.path, item.visibilityRoute).some((target) =>
        isWithinRoutePath(currentPath, target),
      )
    default:
      return false
  }
}

function isAdminRoute(item: LayoutRoute) {
  return (
    item.visible === Visibility.Authorized &&
    Array.isArray(item.requiredRoles) &&
    item.requiredRoles.some((role) => role.trim().toLowerCase() === ROLE_ADMIN)
  )
}

export function useSidebarRoutes(currentUser: Ref<CurrentUser | null>) {
  const route = useRoute()

  const sidebarRoutes = computed(() =>
    routes.filter((item) => isVisible(item, route.path, currentUser.value)),
  )

  const adminSidebarRoutes = computed(() => sidebarRoutes.value.filter(isAdminRoute))

  const primarySidebarRoutes = computed(() =>
    sidebarRoutes.value.filter((item) => !isAdminRoute(item)),
  )

  const footerRoutes = computed(() =>
    routes.filter((item) => item.visible === Visibility.Footer),
  )

  return {
    sidebarRoutes,
    adminSidebarRoutes,
    primarySidebarRoutes,
    footerRoutes,
  }
}
