import { ForbiddenException, UnauthorizedException } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { RolesGuard } from '../auth/roles.guard';
import { PantryController } from './pantry.controller';
import { getRolesMetadata, mockHttpContext } from '../test-utils/security-test-helpers';

describe('Pantry admin security', () => {
  const adminHandlers: Array<[string, Function]> = [
    ['findAllAdmin', PantryController.prototype.findAllAdmin],
    ['createAdmin', PantryController.prototype.createAdmin],
    ['updateAdmin', PantryController.prototype.updateAdmin],
    ['removeAdmin', PantryController.prototype.removeAdmin],
    ['moveToInventoryAdmin', PantryController.prototype.moveToInventoryAdmin],
  ];

  it('alla admin-endpoints har @Roles("admin") metadata', () => {
    for (const [, handler] of adminHandlers) {
      expect(getRolesMetadata(handler)).toEqual(['admin']);
    }
  });

  it.each(adminHandlers)('RolesGuard nekar icke-admin (403) på %s', (_name, handler) => {
    const reflector = new Reflector();
    const guard = new RolesGuard(reflector);
    const context = mockHttpContext({
      handler,
      clazz: PantryController,
      user: { role: 'user' },
    });

    expect(() => guard.canActivate(context)).toThrow(ForbiddenException);
  });

  it.each(adminHandlers)('RolesGuard tillåter admin (200/allow) på %s', (_name, handler) => {
    const reflector = new Reflector();
    const guard = new RolesGuard(reflector);
    const context = mockHttpContext({
      handler,
      clazz: PantryController,
      user: { role: 'admin' },
    });

    expect(guard.canActivate(context)).toBe(true);
  });

  it('JwtAuthGuard mappar saknad användare till 401', () => {
    const guard = new JwtAuthGuard(new Reflector());

    expect(() => guard.handleRequest(null, null, null)).toThrow(UnauthorizedException);
  });

  it('JwtAuthGuard släpper igenom autentiserad användare (200/allow)', () => {
    const guard = new JwtAuthGuard(new Reflector());
    const user = { userId: 42, role: 'user' };

    expect(guard.handleRequest(null, user, null)).toBe(user);
  });
});
