import { LoginUserCommand } from '../commands/login-user/login-user.command';
import { LoginUserHandler } from '../commands/login-user/login-user.handler';

describe('LoginUserHandler', () => {
  let handler: LoginUserHandler;
  let mockTokenService: { generateTokenPair: ReturnType<typeof vi.fn> };
  let mockChallengeRepo: { create: ReturnType<typeof vi.fn> };

  const tokenPair = {
    accessToken: 'access-jwt',
    refreshToken: 'family.refresh-hex',
    expiresIn: 900,
  };

  beforeEach(() => {
    mockTokenService = { generateTokenPair: vi.fn().mockResolvedValue(tokenPair) };
    mockChallengeRepo = { create: vi.fn().mockResolvedValue({}) };
    handler = new LoginUserHandler(mockTokenService as any, mockChallengeRepo as any);
  });

  it('generates token pair with correct payload when MFA not required', async () => {
    const command = new LoginUserCommand('user-1', '0912345678', 'BUYER', false);
    const result = await handler.execute(command);

    expect(result).toEqual({ requiresMfa: false, tokens: tokenPair });
    expect(mockTokenService.generateTokenPair).toHaveBeenCalledWith({
      sub: 'user-1',
      phone: '0912345678',
      role: 'BUYER',
    });
  });

  it('creates MFA challenge when MFA is required', async () => {
    const command = new LoginUserCommand('user-1', '0912345678', 'BUYER', true);
    const result = await handler.execute(command);

    expect(result.requiresMfa).toBe(true);
    expect(result.challengeId).toBeDefined();
    expect(result.tokens).toBeUndefined();
    expect(mockTokenService.generateTokenPair).not.toHaveBeenCalled();
    expect(mockChallengeRepo.create).toHaveBeenCalledWith(
      expect.objectContaining({
        userId: 'user-1',
        type: 'totp',
        attemptCount: 0,
        maxAttempts: 5,
        isVerified: false,
      }),
    );
  });

  it('passes AGENT role correctly', async () => {
    const command = new LoginUserCommand('user-2', '0987654321', 'AGENT');
    await handler.execute(command);

    expect(mockTokenService.generateTokenPair).toHaveBeenCalledWith({
      sub: 'user-2',
      phone: '0987654321',
      role: 'AGENT',
    });
  });

  it('passes ADMIN role correctly', async () => {
    const command = new LoginUserCommand('admin-1', '0901234567', 'ADMIN');
    await handler.execute(command);

    expect(mockTokenService.generateTokenPair).toHaveBeenCalledWith({
      sub: 'admin-1',
      phone: '0901234567',
      role: 'ADMIN',
    });
  });
});
