import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'

const getSessionMock = vi.fn()
const isPairedSessionExpiredMock = vi.fn()
const redirectMock = vi.fn(() => { throw new Error('REDIRECT_CALLED') })
const prismaUserRoleFindFirstMock = vi.fn()

vi.mock('@/lib/auth', () => ({ getSession: getSessionMock }))
vi.mock('@/lib/auth/pairing', () => ({ isPairedSessionExpired: isPairedSessionExpiredMock }))
vi.mock('next/navigation', () => ({ redirect: redirectMock }))
vi.mock('@/lib/prisma', () => ({
  prisma: { userRole: { findFirst: prismaUserRoleFindFirstMock } },
}))

describe('requireSession', () => {
  beforeEach(() => {
    getSessionMock.mockReset()
    isPairedSessionExpiredMock.mockReset()
    redirectMock.mockClear()
  })

  afterEach(() => {
    vi.resetModules()
  })

  it('redirect /login als userId ontbreekt', async () => {
    getSessionMock.mockResolvedValue({ userId: undefined, destroy: vi.fn() })
    isPairedSessionExpiredMock.mockReturnValue(false)
    const { requireSession } = await import('@/lib/auth-guard')
    await expect(requireSession()).rejects.toThrow('REDIRECT_CALLED')
    expect(redirectMock).toHaveBeenCalledWith('/login')
  })

  it('vernietigt + redirect /login als paired-sessie verlopen is', async () => {
    const destroy = vi.fn().mockResolvedValue(undefined)
    getSessionMock.mockResolvedValue({ userId: 'u1', destroy })
    isPairedSessionExpiredMock.mockReturnValue(true)
    const { requireSession } = await import('@/lib/auth-guard')
    await expect(requireSession()).rejects.toThrow('REDIRECT_CALLED')
    expect(destroy).toHaveBeenCalled()
    expect(redirectMock).toHaveBeenCalledWith('/login')
  })

  it('geeft sessie terug als alles ok', async () => {
    const sess = { userId: 'u1', destroy: vi.fn() }
    getSessionMock.mockResolvedValue(sess)
    isPairedSessionExpiredMock.mockReturnValue(false)
    const { requireSession } = await import('@/lib/auth-guard')
    const result = await requireSession()
    expect(result).toBe(sess)
    expect(redirectMock).not.toHaveBeenCalled()
  })
})
