import { describe, expect, it } from 'vitest'
import { resolveDashboardRoutePolicy, roleCanAccessPolicy } from '@/lib/dashboardRoutePolicies'
import { buildSignInRedirect, flattenInternalRoutes, getBaselineInternalRoutes, isAllowedRoute, resolveAccessRedirect, resolveAllowedRoutes } from './DashboardAccessGuard'

describe('DashboardAccessGuard route helpers', () => {
  it('normalizes dashboard-prefixed menu routes before checking access', () => {
    const routes = flattenInternalRoutes([
      {
        id: 'dashboard',
        itemType: 'INTERNAL_PAGE',
        routeOrUrl: '/dashboard',
        children: [],
      },
      {
        id: 'fleet',
        itemType: 'INTERNAL_PAGE',
        routeOrUrl: '/dashboard/fleet',
        children: [],
      },
      {
        id: 'external',
        itemType: 'EXTERNAL_LINK',
        routeOrUrl: '/dashboard/dashboard',
        children: [],
      },
    ])

    expect(routes).toEqual(['/', '/fleet'])
    expect(isAllowedRoute('/', routes)).toBe(true)
    expect(isAllowedRoute('/fleet/123', routes)).toBe(true)
  })

  it('does not redirect forever when an authenticated employee has no visible menu routes', () => {
    expect(resolveAccessRedirect('/', [])).toBeNull()
    expect(resolveAccessRedirect('/fleet', [])).toBeNull()
  })

  it('uses the approved baseline routes when active subscription menu data is empty or root-only', () => {
    expect(resolveAllowedRoutes({ items: [], subscriptionAccessLevel: 'full' }, 'OWNER')).toEqual([
      '/',
      '/reservations',
      '/fleet',
      '/customers',
      '/reports',
      '/billing',
      '/settings',
    ])

    expect(resolveAllowedRoutes({
      subscriptionAccessLevel: 'full',
      items: [
        {
          id: 'dashboard',
          itemType: 'INTERNAL_PAGE',
          routeOrUrl: '/',
          children: [],
        },
      ],
    }, 'MANAGER')).toEqual([
      '/',
      '/reservations',
      '/fleet',
      '/customers',
      '/reports',
      '/billing',
    ])
  })

  it('uses baseline routes when the production menu only contains dashboard and billing recovery links', () => {
    expect(resolveAllowedRoutes({
      subscriptionAccessLevel: 'full',
      items: [
        {
          id: 'dashboard',
          itemType: 'INTERNAL_PAGE',
          routeOrUrl: '/',
          children: [],
        },
        {
          id: 'subscription',
          itemType: 'INTERNAL_PAGE',
          routeOrUrl: '/subscription',
          children: [],
        },
      ],
    }, 'OWNER')).toEqual([
      '/',
      '/reservations',
      '/fleet',
      '/customers',
      '/reports',
      '/billing',
      '/settings',
    ])
  })

  it('does not apply baseline fallback when subscription access is none', () => {
    expect(resolveAllowedRoutes({ items: [], subscriptionAccessLevel: 'none' }, 'OWNER')).toEqual([])
  })

  it('filters baseline routes by role', () => {
    expect(getBaselineInternalRoutes('AGENT')).toEqual(['/', '/reservations', '/fleet', '/customers'])
    expect(getBaselineInternalRoutes('MANAGER')).toEqual(['/', '/reservations', '/fleet', '/customers', '/reports', '/billing'])
  })

  it('redirects disallowed routes to the first visible internal route', () => {
    expect(resolveAccessRedirect('/settings', ['/', '/fleet'])).toBe('/')
    expect(resolveAccessRedirect('/fleet/123', ['/', '/fleet'])).toBeNull()
  })

  it('builds sign-in redirects with public dashboard return paths', () => {
    expect(buildSignInRedirect('/reservations')).toBe('/sign-in?redirect=%2Fdashboard%2Freservations')
    expect(buildSignInRedirect('/dashboard/fleet')).toBe('/sign-in?redirect=%2Fdashboard%2Ffleet')
  })

  it('treats subscription as an owner-only recovery route independent of menu registration', () => {
    const policy = resolveDashboardRoutePolicy('/subscription')

    expect(policy).toMatchObject({
      authenticationRequired: true,
      allowedRoles: ['OWNER'],
      subscriptionRequired: false,
      menuRegistrationRequired: false,
      billingRecoveryRoute: true,
    })
    expect(roleCanAccessPolicy('OWNER', policy)).toBe(true)
    expect(roleCanAccessPolicy('MANAGER', policy)).toBe(false)
    expect(roleCanAccessPolicy('AGENT', policy)).toBe(false)
  })
})
