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

import { MyProfileUpdateCvFormComponent } from './my-profile-update-cv-form.component';
import { mockFileManagerSvc } from '@app/testing/file-manager.service.mock';
import { ActionType } from '@app/domain/action-type.util';
import { ProfileFacade } from '../../../adapters/profiles/profile.facade';
import { FileManagerService } from '../../../adapters/shared/services/file-manager.service';
import { mockProfileFac } from '@app/testing/adapters/profiles/profile.facade.mock';
import { mockProfiles } from '@app/testing/profile.mock';

describe('MyProfileUpdateCvFormComponent', () => {
  let component: MyProfileUpdateCvFormComponent;
  let fixture: ComponentFixture<MyProfileUpdateCvFormComponent>;

  // 1. Mock FileManagerService
  // On reprend la logique des tests précédents pour ce service
  let mockFileManagerService = mockFileManagerSvc;

  // 2. Mock ProfileFacade
  const mockProfileFacade = mockProfileFac;

  // Donnée de test
  const mockProfile = mockProfiles[0];

  beforeEach(async () => {
    // Reset des mocks
    mockFileManagerService.file.set(null);
    mockFileManagerService.fileError.set(null);
    mockFileManagerService.resetFile.mockClear();

    mockProfileFacade.update.mockClear();
    mockProfileFacade.loading.set({ isLoading: false, action: ActionType.NONE });
    mockProfileFacade.error.set({ hasError: false });

    await TestBed.configureTestingModule({
      imports: [MyProfileUpdateCvFormComponent],
      providers: [
        // On injecte nos mocks à la place des vrais services
        { provide: FileManagerService, useValue: mockFileManagerService },
        { provide: ProfileFacade, useValue: mockProfileFacade },
      ],
    }).compileComponents();

    fixture = TestBed.createComponent(MyProfileUpdateCvFormComponent);
    component = fixture.componentInstance;

    // Initialisation de l'input requis
    fixture.componentRef.setInput('profile', mockProfile);

    fixture.detectChanges();
  });

  it('devrait créer le composant', () => {
    expect(component).toBeTruthy();
  });

  describe('Validation (canSubmit)', () => {
    it('devrait être false par défaut (pas de fichier)', () => {
      expect(component.canSubmit).toBe(false);
    });

    it('devrait être true si un fichier est valide', () => {
      mockFileManagerService.file.set(new File([''], 'cv.pdf'));
      expect(component.canSubmit).toBe(true);
    });

    it('devrait être false si une erreur de fichier existe', () => {
      mockFileManagerService.file.set(new File([''], 'cv.exe')); // Fichier présent...
      mockFileManagerService.fileError.set('Type invalide'); // ...mais erreur

      expect(component.canSubmit).toBe(false);
    });

    it('devrait être false si un chargement est en cours', () => {
      mockFileManagerService.file.set(new File([''], 'cv.pdf'));
      mockProfileFacade.loading.set({ isLoading: true, action: ActionType.UPDATE });

      expect(component.canSubmit).toBe(false);
    });
  });

  describe('Soumission (onSubmit)', () => {
    it('devrait appeler facade.update avec FormData', () => {
      const validFile = new File(['dummy content'], 'cv.pdf', { type: 'application/pdf' });
      mockFileManagerService.file.set(validFile);

      component.onSubmit();

      expect(mockProfileFacade.update).toHaveBeenCalledTimes(1);

      const args = mockProfileFacade.update.mock.calls[0];
      expect(args[0]).toBe('1'); // ID du profil
      expect(args[1]).toBeInstanceOf(FormData);
      expect(args[1].get('cv')).toBe(validFile);
    });

    it('ne devrait rien faire si pas de fichier', () => {
      mockFileManagerService.file.set(null);
      component.onSubmit();
      expect(mockProfileFacade.update).not.toHaveBeenCalled();
    });
  });

  describe('Effets (Reset après succès)', () => {
    it('devrait réinitialiser le fichier quand le chargement se termine sans erreur', () => {
      // 1. État initial : chargement en cours
      mockProfileFacade.loading.set({ isLoading: true, action: ActionType.UPDATE });
      fixture.detectChanges();

      // 2. État final : chargement terminé (isLoading: false)
      mockProfileFacade.loading.set({ isLoading: false, action: ActionType.UPDATE });
      mockProfileFacade.error.set({ hasError: false }); // Pas d'erreur

      fixture.detectChanges(); // Déclenche l'effect

      expect(mockFileManagerService.resetFile).toHaveBeenCalled();
    });

    it('ne devrait PAS réinitialiser si il y a une erreur', () => {
      mockProfileFacade.loading.set({ isLoading: false, action: ActionType.UPDATE });
      mockProfileFacade.error.set({ hasError: true }); // Erreur présente

      fixture.detectChanges();

      expect(mockFileManagerService.resetFile).not.toHaveBeenCalled();
    });
  });
});
