import { describe, expect, it, vi } from 'vitest'
import type { NextFunction, Request, Response } from 'express'

import { requireRole } from './requireRole'

function responseStub() {
  const res = { status: vi.fn(), json: vi.fn() }
  res.status.mockReturnValue(res)
  res.json.mockReturnValue(res)
  return res as unknown as Response & typeof res
}

describe('requireRole middleware', () => {
  it('rejects requests when company auth did not attach an employee', () => {
    const req = {} as Request
    const res = responseStub()
    const next = vi.fn() as NextFunction

    requireRole('AGENT' as any)(req, res, next)

    expect(res.status).toHaveBeenCalledWith(401)
    expect(res.json).toHaveBeenCalledWith({ error: 'unauthenticated', message: 'Authentication required', statusCode: 401 })
    expect(next).not.toHaveBeenCalled()
  })

  it('rejects employees below the required role and includes role context', () => {
    const req = { employee: { role: 'AGENT' } } as Request
    const res = responseStub()
    const next = vi.fn() as NextFunction

    requireRole('MANAGER' as any)(req, res, next)

    expect(res.status).toHaveBeenCalledWith(403)
    expect(res.json).toHaveBeenCalledWith({
      error: 'forbidden',
      message: 'This action requires the MANAGER role or higher',
      statusCode: 403,
      requiredRole: 'MANAGER',
      yourRole: 'AGENT',
    })
    expect(next).not.toHaveBeenCalled()
  })

  it('allows employees at or above the required role', () => {
    const req = { employee: { role: 'OWNER' } } as Request
    const res = responseStub()
    const next = vi.fn() as NextFunction

    requireRole('MANAGER' as any)(req, res, next)

    expect(next).toHaveBeenCalledTimes(1)
    expect(res.status).not.toHaveBeenCalled()
  })
})
