import { PbProjectRepository } from '@app/infrastructure/projects/pb-project.repository';
import { CreateProjectDto } from '@app/domain/projects/dto/create-project.dto';
import { Project } from '@app/domain/projects/project.model';
import PocketBase from 'pocketbase';
import { mockProjects } from '@app/testing/project.mock';

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

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

  beforeEach(() => {
    // Création d’un faux client PocketBase avec des méthodes mockées
    mockPocketBase = {
      collection: jest.fn().mockReturnValue({
        create: jest.fn(),
        getFullList: jest.fn(),
        getOne: jest.fn(),
        update: jest.fn(),
      }),
    };

    // 👇 On remplace la classe importée par notre version mockée
    (PocketBase as jest.Mock).mockImplementation(() => mockPocketBase);

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

    // on instancie le repository à tester
    repo = new PbProjectRepository();
  });

  // ------------------------------------------
  // 🔹 TEST : create()
  // ------------------------------------------
  it('devrait appeler pb.collection("projets").create() avec le DTO', (done) => {
    const dto: CreateProjectDto = {
      nom: 'Projet test',
      lien: 'https://exemple.com',
      description: 'Test création',
      utilisateur: 'user_001',
    };

    const fakeResponse: Project = {
      id: '123',
      created: '2025-01-01T00:00:00Z',
      updated: '2025-01-01T00:00:00Z',
      fichier: '',
      ...dto,
    };

    mockCollection.create.mockResolvedValue(fakeResponse);

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

  // ------------------------------------------
  // 🔹 TEST : list()
  // ------------------------------------------
  it('devrait appeler pb.collection("projets").getFullList() avec le filtre utilisateur', (done) => {
    const userId = '1';

    mockCollection.getFullList.mockResolvedValue(mockProjects);

    repo.list(userId).subscribe((result) => {
      expect(mockCollection.getFullList).toHaveBeenCalledWith({
        filter: `utilisateur='${userId}'`,
      });
      expect(result).toEqual(mockProjects);
      done();
    });
  });

  // ------------------------------------------
  // 🔹 TEST : get()
  // ------------------------------------------
  it('devrait appeler pb.collection("projets").getOne() avec le bon ID', (done) => {
    const id = '1';
    const fakeProject: Project = {
      id,
      created: '',
      updated: '',
      nom: 'Test',
      lien: '',
      description: '',
      fichier: '',
      utilisateur: 'user_001',
    };

    mockCollection.getOne.mockResolvedValue(fakeProject);

    repo.get(id).subscribe((result) => {
      expect(mockCollection.getOne).toHaveBeenCalledWith(id);
      expect(result).toEqual(fakeProject);
      done();
    });
  });

  // ------------------------------------------
  // 🔹 TEST : update()
  // ------------------------------------------
  it('devrait appeler pb.collection("projets").update() avec ID et data', (done) => {
    const id = 'p001';
    const data = { nom: 'Projet modifié' };
    const updated: Project = {
      id,
      created: '',
      updated: '',
      nom: data.nom,
      lien: '',
      description: '',
      fichier: '',
      utilisateur: 'user_001',
    };

    mockCollection.update.mockResolvedValue(updated);

    repo.update(id, data).subscribe((result) => {
      expect(mockCollection.update).toHaveBeenCalledWith(id, data);
      expect(result.nom).toBe('Projet modifié');
      done();
    });
  });
});
