import { UnauthorizedException } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { MealPlanController } from './meal-plan.controller';

describe('MealPlan controller security', () => {
  const makeUser = (overrides: Partial<{ userId: number; role: string }> = {}) => ({
    userId: 42,
    role: 'user',
    ...overrides,
  });

  const mealPlanServiceMock = {
    findByRange: jest.fn(),
    shoppingList: jest.fn(),
    inventoryCompare: jest.fn(),
    upsert: jest.fn(),
    removeByDate: jest.fn(),
  };

  const controller = new MealPlanController(mealPlanServiceMock as any);

  beforeEach(() => {
    jest.clearAllMocks();
  });

  it('JwtAuthGuard kräver autentisering på findByRange', () => {
    const guard = new JwtAuthGuard(new Reflector());

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

  it('JwtAuthGuard tillåter autentiserad användare på findByRange', () => {
    const guard = new JwtAuthGuard(new Reflector());
    const user = makeUser({ userId: 1 });

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

  it('findByRange vidarebefordrar @CurrentUser.userId till service', () => {
    mealPlanServiceMock.findByRange.mockResolvedValue([]);

    controller.findByRange(makeUser(), '2026-05-01', '2026-05-07');

    expect(mealPlanServiceMock.findByRange).toHaveBeenCalledWith(42, '2026-05-01', '2026-05-07');
  });

  it('shoppingList vidarebefordrar @CurrentUser.userId till service', () => {
    mealPlanServiceMock.shoppingList.mockResolvedValue([]);

    controller.shoppingList(makeUser(), '2026-05-01', '2026-05-07');

    expect(mealPlanServiceMock.shoppingList).toHaveBeenCalledWith(42, '2026-05-01', '2026-05-07');
  });

  it('inventoryCompare vidarebefordrar @CurrentUser.userId till service', () => {
    mealPlanServiceMock.inventoryCompare.mockResolvedValue([]);

    controller.inventoryCompare(makeUser(), '2026-05-01', '2026-05-07');

    expect(mealPlanServiceMock.inventoryCompare).toHaveBeenCalledWith(42, '2026-05-01', '2026-05-07');
  });

  it('upsert vidarebefordrar @CurrentUser.userId till service', () => {
    const dto = { date: '2026-05-11', recipeId: 1 };
    mealPlanServiceMock.upsert.mockResolvedValue({ id: 1 });

    controller.upsert(makeUser(), dto as any);

    expect(mealPlanServiceMock.upsert).toHaveBeenCalledWith(42, dto);
  });

  it('removeByDate vidarebefordrar @CurrentUser.userId till service', () => {
    mealPlanServiceMock.removeByDate.mockResolvedValue(undefined);

    controller.removeByDate(makeUser(), '2026-05-11');

    expect(mealPlanServiceMock.removeByDate).toHaveBeenCalledWith(42, '2026-05-11');
  });
});
