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 { mockProfilePaginated, 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 = {
      getList: jest.fn(),
      getOne: jest.fn(),
      create: jest.fn(),
      update: jest.fn(),
    };

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

    (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").getList() avec un tri par profession', (done) => {
    mockCollection.getList.mockResolvedValue(mockProfilePaginated);
    const options = {
      expand: 'utilisateur,secteur',
      filter:
        "utilisateur.verified = true && utilisateur.name != '' && profession != 'Profession non renseignée' && secteur != ''",
      sort: '-created',
    };
    repo.list().subscribe((result) => {
      expect(mockPocketBase.collection).toHaveBeenCalledWith('profiles');
      expect(mockCollection.getList).toHaveBeenCalledWith(undefined, undefined, options);
      expect(result).toEqual(mockProfilePaginated);
      done();
    });
  });

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

    mockCollection.getOne.mockResolvedValue(mockProfiles);

    repo.getById(profileId).subscribe((result) => {
      expect(mockCollection.getOne).toHaveBeenCalledWith(`${profileId}`, { expand: 'utilisateur' });
      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();
    });
  });
});
