import { describe, it, expect, vi, beforeEach } from 'vitest';

vi.mock('@/lib/prisma', () => ({
  prisma: {
    diplomes: {
      create: vi.fn(),
      findMany: vi.fn(),
      findUnique: vi.fn(),
      update: vi.fn(),
      delete: vi.fn()
    },
  },
}));

import * as diplomeService from '@/services/diplomes.service';
import { prisma } from '@/lib/prisma';
type CreateDiplomePayload = Parameters<typeof diplomeService.createDiplome>[0];

describe('Unit — services/diplomes', () => {
  beforeEach(() => {
    vi.resetAllMocks();
  });
  it('listDiplomes: should return the contracts list with pagination', async () => {
    const limit = 25;
    const offset = 50;
    const expectedDiplomes = [
      { id: 1, id_salarie: 5524, diplome: "bac"},
      { id: 2, id_salarie: 5524, diplome: "but" },
    ];

    vi.mocked(prisma.diplomes.findMany).mockResolvedValue(expectedDiplomes as never);

    const res = await diplomeService.listDiplomes(limit, offset);

    expect(prisma.diplomes.findMany).toHaveBeenCalledWith({
      orderBy: [{ id: 'asc' }],
      take: limit,
      skip: offset,
    });
    expect(res).toEqual(expectedDiplomes);
  });

  it('listDiplomes: should return an empty array when no contract exists', async () => {
    const limit = 10;
    const offset = 0;

    vi.mocked(prisma.diplomes.findMany).mockResolvedValue([] as never);

    const res = await diplomeService.listDiplomes(limit, offset);

    expect(prisma.diplomes.findMany).toHaveBeenCalledWith({
      orderBy: [{ id: 'asc' }],
      take: limit,
      skip: offset,
    });
    expect(res).toEqual([]);
  });
  it('getDiplomeById: Should return the diplome for the given ID ', async () => {
    const id = 1;
    const expectedDiplome = { id: 1, id_salarie: 5524, diplome: "bac"};

    vi.mocked(prisma.diplomes.findUnique).mockResolvedValue(expectedDiplome as never);

    const res = await diplomeService.getDiplomeById(id);

    expect(prisma.diplomes.findUnique).toHaveBeenCalledWith({
      where: { id: id },
    });
    expect(res).toEqual(expectedDiplome);
  });
  it('getDiplomeById: should return null when diplome does not exist', async () => {
    const id = 404;

    vi.mocked(prisma.diplomes.findUnique).mockResolvedValue(null as never);

    const res = await diplomeService.getDiplomeById(id);

    expect(prisma.diplomes.findUnique).toHaveBeenCalledWith({
      where: { id: id },
    });
    expect(res).toBeNull();
  });
  it('createDiplome: should call prisma.create and return created diplome', async () => {
    const payload: CreateDiplomePayload = { id_salarie: 5524, diplome: "bac" };
    const created = { id: 1, ...payload };

    vi.mocked(prisma.diplomes.create).mockResolvedValue(created as never);

    const res = await diplomeService.createDiplome(payload);

    expect(prisma.diplomes.create).toHaveBeenCalledWith({ data: payload });
    expect(res).toEqual(created);
  });

  it('updateDiplomeById: should update diplome when ID exists', async () => {
    const id = 1;
    const payload = { diplome: 'Updated' } as Partial<CreateDiplomePayload>;
    const updatedDiplome = { id: id, ...payload };

    vi.mocked(prisma.diplomes.findUnique).mockResolvedValue({ id: id } as never);
    vi.mocked(prisma.diplomes.update).mockResolvedValue(updatedDiplome as never);

    const res = await diplomeService.updateDiplomeById(id, payload);

    expect(prisma.diplomes.findUnique).toHaveBeenCalledWith({
      where: { id: id },
    });
    expect(prisma.diplomes.update).toHaveBeenCalledWith({
      where: { id: id },
      data: payload,
    });
    expect(res).toEqual(updatedDiplome);
  });
  it('updateDiplomeById: should return null when ID does not exist', async () => {
    const id = 99999;

    const payload = { TCS: 'Nope' } as Partial<CreateDiplomePayload>;

    vi.mocked(prisma.diplomes.findUnique).mockResolvedValue(null as never);

    const res = await diplomeService.updateDiplomeById(id, payload);

    expect(prisma.diplomes.findUnique).toHaveBeenCalledWith({
      where: { id: id },
    });
    expect(prisma.diplomes.update).not.toHaveBeenCalled();
    expect(res).toBeNull();
  });
  it('deleteDiplomeById: should delete and return diplome ', async () => {
    const id = 1;
    const deletedDiplome = { id: id, diplome: 'Delete' };

    vi.mocked(prisma.diplomes.findUnique).mockResolvedValue({ id: id } as never);
    vi.mocked(prisma.diplomes.delete).mockResolvedValue(deletedDiplome as never);

    const res = await diplomeService.deleteDiplomeById(id);

    expect(prisma.diplomes.findUnique).toHaveBeenCalledWith({
      where: { id: id },
    });
    expect(prisma.diplomes.delete).toHaveBeenCalledWith({
      where: { id: id },
    });
    expect(res).toEqual(deletedDiplome);
  });
  it('deleteDiplomeById: should return null when ID does not exist', async () => {
    const id = 55555;

    vi.mocked(prisma.diplomes.findUnique).mockResolvedValue(null as never);

    const res = await diplomeService.deleteDiplomeById(id);

    expect(prisma.diplomes.findUnique).toHaveBeenCalledWith({
      where: { id: id },
    });
    expect(prisma.diplomes.delete).not.toHaveBeenCalled();
    expect(res).toBeNull();
  });
});
