import { PbProfileRepository } from '@app/infrastructure/profiles/pb-profile.repository';
import { Profile } from '@app/domain/profiles/profile.model';
import { ProfileDTO } from '@app/domain/profiles/dto/create-profile.dto';
import PocketBase from 'pocketbase';
import { mockProfiles } from '@app/testing/profile.mock';

jest.mock('pocketbase'); // on mock le module PocketBase

describe('PbProfileRepository', () => {
  let repo: PbProfileRepository;
  let mockPocketBase: any;
  let mockCollection: any;

  beforeEach(() => {
    // Création d’un faux client PocketBase avec les méthodes dont on a besoin
    mockCollection = {
      getFullList: jest.fn(),
      getFirstListItem: jest.fn(),
      create: jest.fn(),
      update: jest.fn(),
    };

    mockPocketBase = {
      collection: jest.fn().mockReturnValue(mockCollection),
    };

    // @ts-ignore : on remplace l’instance réelle de PocketBase par notre mock
    (PocketBase as jest.Mock).mockImplementation(() => mockPocketBase);

    // on récupère une "collection" simulée
    mockCollection = mockPocketBase.collection('profiles');

    repo = new PbProfileRepository();
  });

  // ------------------------------------------
  // 🔹 TEST : list()
  // ------------------------------------------
  it('devrait appeler pb.collection("profiles").getFullList() avec un tri par profession', (done) => {
    mockCollection.getFullList.mockResolvedValue(mockProfiles);

    repo.list().subscribe((result) => {
      expect(mockPocketBase.collection).toHaveBeenCalledWith('profiles');
      expect(mockCollection.getFullList).toHaveBeenCalledWith({ sort: 'profession' });
      expect(result).toEqual(mockProfiles);
      done();
    });
  });

  // ------------------------------------------
  // 🔹 TEST : getByUserId()
  // ------------------------------------------
  it('devrait appeler pb.collection("profiles").getFirstListItem() avec le bon filtre utilisateur', () => {
    const userId = '1';

    mockCollection.getFirstListItem.mockResolvedValue(mockProfiles);

    repo.getByUserId(userId).subscribe((result) => {
      expect(mockCollection.getFirstListItem).toHaveBeenCalledWith(`utilisateur="${userId}"`);
      expect(result).toEqual(mockProfiles[0]);
    });
  });

  // ------------------------------------------
  // 🔹 TEST : create()
  // ------------------------------------------
  it('devrait appeler pb.collection("profiles").create() avec le DTO du profil', (done) => {
    const dto: ProfileDTO = {
      utilisateur: 'user',
      profession: 'DevOps',
      reseaux: {} as JSON,
    };

    const fakeResponse: Profile = {
      id: '123',
      created: '2025-01-01T00:00:00Z',
      updated: '2025-01-01T00:00:00Z',
      estVerifier: true,
      secteur: 'Création',
      bio: 'Bio',
      cv: '',
      projets: [],
      apropos: 'À propos...',
      ...dto,
    };

    mockCollection.create.mockResolvedValue(fakeResponse);

    repo.create(dto).subscribe((result) => {
      expect(mockCollection.create).toHaveBeenCalledWith(dto);
      expect(result).toEqual(fakeResponse);
      done();
    });
  });

  // ------------------------------------------
  // 🔹 TEST : update()
  // ------------------------------------------
  it('devrait appeler pb.collection("profiles").update() avec ID et données partielle', (done) => {
    const id = '1';
    const data = { bio: 'Bio mise à jour' };
    const updatedProfile: Profile = {
      id,
      created: '',
      updated: '',
      profession: 'Dev',
      utilisateur: 'user_001',
      estVerifier: false,
      secteur: 'Tech',
      reseaux: {} as JSON,
      bio: data.bio!,
      cv: '',
      projets: [],
      apropos: '',
    };

    mockCollection.update.mockResolvedValue(updatedProfile);

    repo.update(id, data).subscribe((result) => {
      expect(mockCollection.update).toHaveBeenCalledWith(id, data);
      expect(result.bio).toBe('Bio mise à jour');
      done();
    });
  });
});
