import { describe, it, expect, beforeEach } from 'vitest'
import { createRouter, createWebHistory } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router'

const mockLocalStorage = {
  store: {} as Record<string, string>,
  getItem(key: string) {
    return this.store[key] || null
  },
  setItem(key: string, value: string) {
    this.store[key] = value
  },
  removeItem(key: string) {
    delete this.store[key]
  },
  clear() {
    this.store = {}
  }
}

Object.defineProperty(window, 'localStorage', {
  value: mockLocalStorage
})

const createTestRouter = (routes: RouteRecordRaw[]) => {
  return createRouter({
    history: createWebHistory(),
    routes
  })
}

describe('路由守卫权限检查', () => {
  beforeEach(() => {
    mockLocalStorage.clear()
  })

  describe('基础认证检查', () => {
    it('未登录用户访问受保护路由应重定向到登录页', async () => {
      const routes: RouteRecordRaw[] = [
        {
          path: '/login',
          name: 'Login',
          component: { template: '<div>Login</div>' }
        },
        {
          path: '/',
          component: { template: '<div>Layout</div>' },
          meta: { requiresAuth: true },
          children: [
            {
              path: 'dashboard',
              name: 'Dashboard',
              component: { template: '<div>Dashboard</div>' }
            }
          ]
        }
      ]

      const router = createTestRouter(routes)
      
      router.beforeEach((to, _from, next) => {
        const token = localStorage.getItem('token')
        
        if (to.meta.requiresAuth && !token) {
          next('/login')
        } else {
          next()
        }
      })

      await router.push('/dashboard')
      expect(router.currentRoute.value.path).toBe('/login')
    })

    it('已登录用户访问受保护路由应允许通过', async () => {
      mockLocalStorage.setItem('token', 'valid-token')
      
      const routes: RouteRecordRaw[] = [
        {
          path: '/login',
          name: 'Login',
          component: { template: '<div>Login</div>' }
        },
        {
          path: '/',
          component: { template: '<div>Layout</div>' },
          meta: { requiresAuth: true },
          children: [
            {
              path: 'dashboard',
              name: 'Dashboard',
              component: { template: '<div>Dashboard</div>' }
            }
          ]
        }
      ]

      const router = createTestRouter(routes)
      
      router.beforeEach((to, _from, next) => {
        const token = localStorage.getItem('token')
        
        if (to.meta.requiresAuth && !token) {
          next('/login')
        } else {
          next()
        }
      })

      await router.push('/dashboard')
      expect(router.currentRoute.value.path).toBe('/dashboard')
    })
  })

  describe('角色权限检查', () => {
    it('普通用户访问管理员路由应重定向到403页面', async () => {
      mockLocalStorage.setItem('token', 'valid-token')
      mockLocalStorage.setItem('roles', JSON.stringify(['user']))
      
      const routes: RouteRecordRaw[] = [
        {
          path: '/login',
          name: 'Login',
          component: { template: '<div>Login</div>' }
        },
        {
          path: '/403',
          name: 'Forbidden',
          component: { template: '<div>403 Forbidden</div>' }
        },
        {
          path: '/',
          component: { template: '<div>Layout</div>' },
          meta: { requiresAuth: true },
          children: [
            {
              path: 'dashboard',
              name: 'Dashboard',
              component: { template: '<div>Dashboard</div>' }
            },
            {
              path: 'users',
              name: 'UserManagement',
              component: { template: '<div>UserManagement</div>' },
              meta: { roles: ['admin'] }
            }
          ]
        }
      ]

      const router = createTestRouter(routes)
      
      router.beforeEach((to, _from, next) => {
        const token = localStorage.getItem('token')
        const rolesStr = localStorage.getItem('roles')
        const userRoles = rolesStr ? JSON.parse(rolesStr) : []
        
        if (to.meta.requiresAuth && !token) {
          next('/login')
          return
        }
        
        if (to.meta.roles && Array.isArray(to.meta.roles)) {
          const hasRole = to.meta.roles.some((role: string) => userRoles.includes(role))
          if (!hasRole) {
            next('/403')
            return
          }
        }
        
        next()
      })

      await router.push('/users')
      expect(router.currentRoute.value.path).toBe('/403')
    })

    it('管理员用户访问管理员路由应允许通过', async () => {
      mockLocalStorage.setItem('token', 'valid-token')
      mockLocalStorage.setItem('roles', JSON.stringify(['admin']))
      
      const routes: RouteRecordRaw[] = [
        {
          path: '/login',
          name: 'Login',
          component: { template: '<div>Login</div>' }
        },
        {
          path: '/403',
          name: 'Forbidden',
          component: { template: '<div>403 Forbidden</div>' }
        },
        {
          path: '/',
          component: { template: '<div>Layout</div>' },
          meta: { requiresAuth: true },
          children: [
            {
              path: 'dashboard',
              name: 'Dashboard',
              component: { template: '<div>Dashboard</div>' }
            },
            {
              path: 'users',
              name: 'UserManagement',
              component: { template: '<div>UserManagement</div>' },
              meta: { roles: ['admin'] }
            }
          ]
        }
      ]

      const router = createTestRouter(routes)
      
      router.beforeEach((to, _from, next) => {
        const token = localStorage.getItem('token')
        const rolesStr = localStorage.getItem('roles')
        const userRoles = rolesStr ? JSON.parse(rolesStr) : []
        
        if (to.meta.requiresAuth && !token) {
          next('/login')
          return
        }
        
        if (to.meta.roles && Array.isArray(to.meta.roles)) {
          const hasRole = to.meta.roles.some((role: string) => userRoles.includes(role))
          if (!hasRole) {
            next('/403')
            return
          }
        }
        
        next()
      })

      await router.push('/users')
      expect(router.currentRoute.value.path).toBe('/users')
    })

    it('无角色要求的路由所有登录用户都可访问', async () => {
      mockLocalStorage.setItem('token', 'valid-token')
      mockLocalStorage.setItem('roles', JSON.stringify(['user']))
      
      const routes: RouteRecordRaw[] = [
        {
          path: '/login',
          name: 'Login',
          component: { template: '<div>Login</div>' }
        },
        {
          path: '/',
          component: { template: '<div>Layout</div>' },
          meta: { requiresAuth: true },
          children: [
            {
              path: 'dashboard',
              name: 'Dashboard',
              component: { template: '<div>Dashboard</div>' }
            }
          ]
        }
      ]

      const router = createTestRouter(routes)
      
      router.beforeEach((to, _from, next) => {
        const token = localStorage.getItem('token')
        const rolesStr = localStorage.getItem('roles')
        const userRoles = rolesStr ? JSON.parse(rolesStr) : []
        
        if (to.meta.requiresAuth && !token) {
          next('/login')
          return
        }
        
        if (to.meta.roles && Array.isArray(to.meta.roles)) {
          const hasRole = to.meta.roles.some((role: string) => userRoles.includes(role))
          if (!hasRole) {
            next('/403')
            return
          }
        }
        
        next()
      })

      await router.push('/dashboard')
      expect(router.currentRoute.value.path).toBe('/dashboard')
    })
  })
})
