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

vi.mock('@/services/absences.service', () => ({
  listAbsences: vi.fn(),
  getAbsenceById: vi.fn(),
  createAbsence: vi.fn(),
  updateAbsenceById: vi.fn(),
  deleteAbsenceById: vi.fn(),
}));

vi.mock('@/server/public-entity', () => ({
  toPublicAbsence: vi.fn((absence) => absence ? { ...absence, public: true } : absence),
  toPublicAbsenceList: vi.fn((absences) =>
    absences.map((absence: any) => ({ ...absence, public: true }))
  ),
}));

import {
  listAbsences,
  getAbsenceById,
  createAbsence,
  updateAbsenceById,
  deleteAbsenceById,
} from '@/services/absences.service';

import {
  toPublicAbsence,
  toPublicAbsenceList,
} from '@/server/public-entity';

import {
  getAbsencesFeed,
  getAbsenceDetails,
  createAbsenceFeed,
  updateAbsenceFeed,
  deleteAbsenceFeed,
} from '../../../src/server/absences.server';

describe('Unit - absence server', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('getAbsencesFeed returns a public absence feed', async () => {
    const absences = [{ id: 1 }, { id: 2 }];

    vi.mocked(listAbsences).mockResolvedValue(absences as never);

    const result = await getAbsencesFeed(25, 50);

    expect(listAbsences).toHaveBeenCalledWith(25, 50);
    expect(toPublicAbsenceList).toHaveBeenCalledWith(absences);
    expect(result).toEqual({
      items: [
        { id: 1, public: true },
        { id: 2, public: true },
      ],
      count: 2,
    });
  });

  it('getAbsenceDetails returns a public absence by id', async () => {
    const absence = { id: 1 };

    vi.mocked(getAbsenceById).mockResolvedValue(absence as never);

    const result = await getAbsenceDetails(1);

    expect(getAbsenceById).toHaveBeenCalledWith(1);
    expect(toPublicAbsence).toHaveBeenCalledWith(absence);
    expect(result).toEqual({
      absence: { id: 1, public: true },
    });
  });

  it('createAbsenceFeed creates and returns a public absence', async () => {
    const payload = { typeabsence: 'Maladie' };
    const absence = { id: 1, ...payload };

    vi.mocked(createAbsence).mockResolvedValue(absence as never);

    const result = await createAbsenceFeed(payload as any);

    expect(createAbsence).toHaveBeenCalledWith(payload);
    expect(toPublicAbsence).toHaveBeenCalledWith(absence);
    expect(result).toEqual({
      absence: { id: 1, typeabsence: 'Maladie', public: true },
    });
  });

  it('updateAbsenceFeed updates and returns a public absence', async () => {
    const payload = { commentaire: 'Maj absence' };
    const absence = { id: 1, ...payload };

    vi.mocked(updateAbsenceById).mockResolvedValue(absence as never);

    const result = await updateAbsenceFeed(1, payload as any);

    expect(updateAbsenceById).toHaveBeenCalledWith(1, payload);
    expect(toPublicAbsence).toHaveBeenCalledWith(absence);
    expect(result).toEqual({
      absence: { id: 1, commentaire: 'Maj absence', public: true },
    });
  });

  it('deleteAbsenceFeed deletes and returns a public absence', async () => {
    const absence = { id: 1 };

    vi.mocked(deleteAbsenceById).mockResolvedValue(absence as never);

    const result = await deleteAbsenceFeed(1);

    expect(deleteAbsenceById).toHaveBeenCalledWith(1);
    expect(toPublicAbsence).toHaveBeenCalledWith(absence);
    expect(result).toEqual({
      absence: { id: 1, public: true },
    });
  });

  it('getAbsenceDetails returns null when absence does not exist', async () => {
    vi.mocked(getAbsenceById).mockResolvedValue(null as never);

    const result = await getAbsenceDetails(999);

    expect(result).toEqual({
      absence: null,
    });
  });
});