import { describe, it, expect, vi, beforeEach } from 'vitest'
import { createPinia, setActivePinia } from 'pinia'

// Must mock before importing router (which imports useAuthStore)
vi.mock('../../stores/auth.js', () => ({
  useAuthStore: vi.fn(),
}))

// Mock all lazily-imported view components so the router can be instantiated
vi.mock('../../views/auth/LoginView.vue', () => ({ default: { template: '<div />' } }))
vi.mock('../../views/auth/RegisterView.vue', () => ({ default: { template: '<div />' } }))
vi.mock('../../views/auth/PasswordResetView.vue', () => ({ default: { template: '<div />' } }))
vi.mock('../../views/auth/NewPasswordView.vue', () => ({ default: { template: '<div />' } }))
vi.mock('../../views/AdminView.vue', () => ({ default: { template: '<div />' } }))
vi.mock('../../views/SharedView.vue', () => ({ default: { template: '<div />' } }))

// Heavy view components imported statically — stub them too
vi.mock('../../views/FileManagerView.vue', () => ({ default: { template: '<div />' } }))
vi.mock('../../views/TopicsView.vue', () => ({ default: { template: '<div />' } }))
vi.mock('../../views/DocumentView.vue', () => ({ default: { template: '<div />' } }))
vi.mock('../../views/SettingsView.vue', () => ({ default: { template: '<div />' } }))
vi.mock('../../views/CloudFolderView.vue', () => ({ default: { template: '<div />' } }))
vi.mock('../../views/CloudStorageView.vue', () => ({ default: { template: '<div />' } }))

import { useAuthStore } from '../../stores/auth.js'
import router from '../index.js'

beforeEach(() => {
  setActivePinia(createPinia())
  vi.clearAllMocks()
})

describe('router — auth route meta (SEC-07, AUTH-01)', () => {
  const authPaths = ['/login', '/register', '/password-reset', '/password-reset/confirm']

  it.each(authPaths)(
    'route %s has meta.public = true so guard skips auth check',
    (path) => {
      const route = router.getRoutes().find(r => r.path === path)
      expect(route, `route "${path}" should exist`).toBeDefined()
      expect(route.meta.public).toBe(true)
    }
  )

  it.each(authPaths)(
    'route %s has meta.layout = "auth" so sidebar is never rendered',
    (path) => {
      const route = router.getRoutes().find(r => r.path === path)
      expect(route, `route "${path}" should exist`).toBeDefined()
      expect(route.meta.layout).toBe('auth')
    }
  )
})

describe('router — admin guard (SEC-07)', () => {
  it('redirects a non-admin user away from /admin to /', async () => {
    // Arrange: authenticated but role = 'viewer'
    useAuthStore.mockReturnValue({
      accessToken: 'fake-token',
      user: { id: '1', role: 'viewer' },
      refresh: vi.fn().mockResolvedValue(undefined),
    })

    // Act: attempt to navigate to /admin
    const result = await router.push('/admin')
    // The guard returns { path: '/' }, so the router resolves to '/'
    expect(router.currentRoute.value.path).toBe('/')
  })

  it('allows an admin user to reach /admin', async () => {
    // Arrange: authenticated as admin
    useAuthStore.mockReturnValue({
      accessToken: 'fake-token',
      user: { id: '1', role: 'admin' },
      refresh: vi.fn().mockResolvedValue(undefined),
    })

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