import { BadRequestException } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { UserService } from '../user/user.service';

describe('AuthController', () => {
  let controller: AuthController;
  const authServiceMock = {
    verifyCreatePasswordToken: jest.fn(),
    createPasswordWithToken: jest.fn(),
    requestPasswordReset: jest.fn(),
    resetPasswordWithResetToken: jest.fn(),
  };

  beforeEach(async () => {
    jest.clearAllMocks();
    const module: TestingModule = await Test.createTestingModule({
      controllers: [AuthController],
      providers: [
        { provide: AuthService, useValue: authServiceMock },
        { provide: UserService, useValue: {} },
      ],
    }).compile();

    controller = module.get<AuthController>(AuthController);
  });

  it('should be defined', () => {
    expect(controller).toBeDefined();
  });

  it('forwards token verification to auth service', async () => {
    authServiceMock.verifyCreatePasswordToken.mockResolvedValue({
      valid: true,
      message: 'Token valide',
    });

    await expect(controller.verifyCreatePasswordToken('tok-123')).resolves.toEqual({
      valid: true,
      message: 'Token valide',
    });
    expect(authServiceMock.verifyCreatePasswordToken).toHaveBeenCalledWith('tok-123');
  });

  it('rejects create-password when confirmation mismatches', async () => {
    await expect(
      controller.createPassword({
        token: 'tok-123',
        password: 'Password1',
        password_confirmation: 'Password2',
      }),
    ).rejects.toThrow(BadRequestException);
    expect(authServiceMock.createPasswordWithToken).not.toHaveBeenCalled();
  });

  it('calls auth service when create-password payload is valid', async () => {
    authServiceMock.createPasswordWithToken.mockResolvedValue({
      message: 'Mot de passe créé avec succès. Vous pouvez maintenant vous connecter.',
      userId: 'user-1',
    });

    await expect(
      controller.createPassword({
        token: 'tok-123',
        password: 'Password1',
        password_confirmation: 'Password1',
      }),
    ).resolves.toEqual({
      message: 'Mot de passe créé avec succès. Vous pouvez maintenant vous connecter.',
      userId: 'user-1',
    });
    expect(authServiceMock.createPasswordWithToken).toHaveBeenCalledWith('tok-123', 'Password1');
  });

  it('forgot-password délègue au service et renvoie le message générique', async () => {
    authServiceMock.requestPasswordReset.mockResolvedValue({
      message: 'Si cette adresse est associée…',
    });
    await expect(controller.forgotPassword({ email: 'user@test.fr' })).resolves.toEqual({
      message: 'Si cette adresse est associée…',
    });
    expect(authServiceMock.requestPasswordReset).toHaveBeenCalledWith('user@test.fr');
  });

  it('rejects reset-password when confirmation mismatches', async () => {
    await expect(
      controller.resetPassword({
        token: 'tok',
        password: 'Password1',
        password_confirmation: 'Password2',
      }),
    ).rejects.toThrow(BadRequestException);
    expect(authServiceMock.resetPasswordWithResetToken).not.toHaveBeenCalled();
  });

  it('calls reset-password when payload is valid', async () => {
    authServiceMock.resetPasswordWithResetToken.mockResolvedValue({
      message: 'Mot de passe mis à jour.',
    });
    await expect(
      controller.resetPassword({
        token: 'tok-123',
        password: 'Password1',
        password_confirmation: 'Password1',
      }),
    ).resolves.toEqual({ message: 'Mot de passe mis à jour.' });
    expect(authServiceMock.resetPasswordWithResetToken).toHaveBeenCalledWith('tok-123', 'Password1');
  });
});
