import { TestBed } from '@angular/core/testing';

import { authGuard } from './auth.guard';
import { CanActivateFn, Router, UrlTree } from '@angular/router';
import { AuthFacade } from '../../../adapters/authentification/auth.facade';

describe('authGuard', () => {
  // 1. Définition des variables pour les Mocks
  let mockRouter: { parseUrl: jest.Mock };
  let mockAuthFacade: {
    verifyEmail: jest.Mock;
    verifyAuthenticatedUser: jest.Mock;
    isAuthenticated: jest.Mock;
    isEmailVerified: jest.Mock;
  };

  // 2. Fonction helper pour exécuter le guard dans le contexte d'injection
  const executeGuard: CanActivateFn = (...guardParameters) =>
    TestBed.runInInjectionContext(() => authGuard(...guardParameters));

  beforeEach(() => {
    // 3. Initialisation des Mocks
    mockRouter = {
      parseUrl: jest.fn(),
    };

    mockAuthFacade = {
      verifyEmail: jest.fn(),
      verifyAuthenticatedUser: jest.fn(),
      isAuthenticated: jest.fn(), // On changera la valeur de retour selon le test
      isEmailVerified: jest.fn(), // On changera la valeur de retour selon le test
    };

    TestBed.configureTestingModule({
      providers: [
        { provide: Router, useValue: mockRouter },
        { provide: AuthFacade, useValue: mockAuthFacade }, // On fournit la Facade, pas le Repo
      ],
    });
  });

  it('should be created', () => {
    expect(executeGuard).toBeTruthy();
  });

  // --- SCÉNARIO 1 : L'utilisateur a tout bon ---
  it('should return true if user is authenticated AND email is verified', () => {
    // Setup : Tout est OK
    mockAuthFacade.isAuthenticated.mockReturnValue(true);
    mockAuthFacade.isEmailVerified.mockReturnValue(true);

    const result = executeGuard({} as any, {} as any); // On passe des fausses routes/state

    // Vérifications
    expect(result).toBe(true);
    // On vérifie aussi que le guard a bien lancé les vérifications
    expect(mockAuthFacade.verifyEmail).toHaveBeenCalled();
    expect(mockAuthFacade.verifyAuthenticatedUser).toHaveBeenCalled();
  });

  // --- SCÉNARIO 2 : L'utilisateur n'est pas connecté ---
  it('should redirect to /auth if user is NOT authenticated', () => {
    // Setup : Pas connecté
    mockAuthFacade.isAuthenticated.mockReturnValue(false);
    mockAuthFacade.isEmailVerified.mockReturnValue(true); // Peu importe ici

    // On prépare le router pour qu'il renvoie une fausse UrlTree
    const dummyUrlTree = {} as UrlTree;
    mockRouter.parseUrl.mockReturnValue(dummyUrlTree);

    const result = executeGuard({} as any, {} as any);

    // Le guard doit retourner la redirection (UrlTree)
    expect(result).toBe(dummyUrlTree);
    expect(mockRouter.parseUrl).toHaveBeenCalledWith('/auth');
  });

  // --- SCÉNARIO 3 : Connecté mais email non vérifié ---
  it('should redirect to /auth if user is authenticated but email is NOT verified', () => {
    // Setup : Connecté mais mail pas bon
    mockAuthFacade.isAuthenticated.mockReturnValue(true);
    mockAuthFacade.isEmailVerified.mockReturnValue(false);

    const dummyUrlTree = {} as UrlTree;
    mockRouter.parseUrl.mockReturnValue(dummyUrlTree);

    const result = executeGuard({} as any, {} as any);

    expect(result).toBe(dummyUrlTree);
    expect(mockRouter.parseUrl).toHaveBeenCalledWith('/auth');
  });
});
