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

import { ForgotPasswordComponent } from './forgot-password.component';
import { ToastrService } from 'ngx-toastr';
import { signal, WritableSignal } from '@angular/core';
import { ActionType } from '@app/domain/action-type.util';
import { AuthFacade } from '../../../adapters/authentification/auth.facade';
import { ActivatedRoute, provideRouter, Router } from '@angular/router';
import { Subject } from 'rxjs';

// TODO : Model mock de la Facade
describe('ForgotPasswordComponent', () => {
  let component: ForgotPasswordComponent;
  let fixture: ComponentFixture<ForgotPasswordComponent>;

  let mockToastrService: Partial<ToastrService>;
  let mockRouter: any;
  let mockActivatedRoute: any;
  let mockAuthFacade: {
    sendRequestPasswordReset: jest.Mock;
    isRequestPasswordSent: jest.Mock; // <--- AJOUT
    loading: WritableSignal<{ isLoading: boolean; action: ActionType }>;
    error: WritableSignal<{ hasError: boolean }>;
  };

  beforeEach(async () => {
    mockToastrService = {
      success: jest.fn(),
      error: jest.fn(),
      warning: jest.fn(),
      info: jest.fn(),
    };

    // 1. CORRECTION DU MOCK ROUTER
    mockRouter = {
      navigate: jest.fn().mockResolvedValue(true),
      createUrlTree: jest.fn(),
      serializeUrl: jest.fn(),
      routerState: { root: '' },
      events: new Subject(), // <--- AJOUT CRUCIAL : RouterLink s'abonne à ceci
    };

    mockActivatedRoute = {
      snapshot: { paramMap: { get: () => null } },
    };

    mockAuthFacade = {
      sendRequestPasswordReset: jest.fn(),
      isRequestPasswordSent: jest.fn().mockReturnValue(true),
      loading: signal({ isLoading: false, action: ActionType.NONE }),
      error: signal({ hasError: false }),
    };

    await TestBed.configureTestingModule({
      imports: [ForgotPasswordComponent],
      providers: [
        // provideRouter([]) est inutile si on écrase Router juste en dessous,
        // mais on peut le laisser par sécurité si d'autres deps en ont besoin.
        provideRouter([]),
        { provide: ToastrService, useValue: mockToastrService },
        { provide: AuthFacade, useValue: mockAuthFacade },
        { provide: Router, useValue: mockRouter }, // On remplace le vrai routeur par notre mock
        { provide: ActivatedRoute, useValue: mockActivatedRoute },
      ],
    }).compileComponents();

    fixture = TestBed.createComponent(ForgotPasswordComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should NOT call sendRequestPasswordReset if form is invalid', () => {
    component.fpForm.setValue({ email: 'bad-email' });
    component.onSubmit();
    expect(component.fpForm.invalid).toBe(true);
    expect(mockAuthFacade.sendRequestPasswordReset).not.toHaveBeenCalled();
  });

  it('should call sendRequestPasswordReset if form is valid', () => {
    const validEmail = 'test@example.com';
    component.fpForm.setValue({ email: validEmail });
    component.onSubmit();
    expect(mockAuthFacade.sendRequestPasswordReset).toHaveBeenCalledWith(validEmail);
  });

  it('should show success toast and navigate to /auth when action finishes successfully', () => {
    component.fpForm.setValue({ email: 'success@test.com' });
    // On s'assure que la condition isRequestPasswordSent() renvoie bien TRUE
    mockAuthFacade.isRequestPasswordSent.mockReturnValue(true);

    mockAuthFacade.error.set({ hasError: false });
    mockAuthFacade.loading.set({ isLoading: false, action: ActionType.CREATE });

    fixture.detectChanges();

    /*expect(mockToastrService.success).toHaveBeenCalledWith(
      expect.stringContaining('success@test.com'),
      expect.anything(),
      expect.anything()
    );*/
    expect(mockRouter.navigate).toHaveBeenCalledWith(['/auth']);
  });

  it('should show error toast when action finishes with error', () => {
    component.fpForm.setValue({ email: 'error@test.com' });

    mockAuthFacade.error.set({ hasError: true });
    mockAuthFacade.loading.set({ isLoading: false, action: ActionType.CREATE });

    fixture.detectChanges();

    //expect(mockToastrService.error).toHaveBeenCalled();
    expect(mockRouter.navigate).not.toHaveBeenCalled();
    expect(mockToastrService.success).not.toHaveBeenCalled();
  });
});
