// tests/unit/routes/employes.route.spec.ts
import { beforeEach, describe, expect, it, vi } from 'vitest';

const { requireAuthMock, getVisitesMedicalesFeedMock, createVisiteMedicaleFeedMock } = vi.hoisted(() => ({
    requireAuthMock: vi.fn(),
    getVisitesMedicalesFeedMock: vi.fn(),
    createVisiteMedicaleFeedMock: vi.fn(),
}));

vi.mock('../../../../src/lib/requireAuth', () => ({
    requireAuth: requireAuthMock,
}));

vi.mock('../../../../src/server/visites-medicales.server', () => ({
    getVisitesMedicalesFeed: getVisitesMedicalesFeedMock,
    createVisiteMedicaleFeed: createVisiteMedicaleFeedMock,
}));

import { GET, POST } from '../../../../src/app/api/visites-medicales/route';
const mockDate = "2024-11-27T13:30:00.000Z";
describe('Unit — /api/visites-medicales route', () => {
    beforeEach(() => {
        vi.resetAllMocks();
        requireAuthMock.mockReturnValue(null);
    });

    it('GET returns 200 and default pagination values', async () => {
        getVisitesMedicalesFeedMock.mockResolvedValue({
            items: [{
                id_salarie: 1903,
                datedde: null,
                dec: null,
                dvp: mockDate,
                obv: "Embauche",
                mtc: null,
                apt: "Apte",
                vmp: null,
                commentaire: null,
                dateprochainevm: null,
                daterappel: null,
                date_creation: mockDate
            }],
            count: 1,
        });

        const res = await GET(new Request('http://localhost/api/visites-medicales'));

        expect(res.status).toBe(200);
        expect(getVisitesMedicalesFeedMock).toHaveBeenCalledWith(10, 0);

        const body = await res.json();
        expect(body).toEqual({
            message: 'Visites médicales retrieved successfully',
            items: [{
                id_salarie: 1903,
                datedde: null,
                dec: null,
                dvp: mockDate,
                obv: "Embauche",
                mtc: null,
                apt: "Apte",
                vmp: null,
                commentaire: null,
                dateprochainevm: null,
                daterappel: null,
                date_creation: mockDate
            }],
            count: 1,
        });
    });

    it('GET returns 400 when query params are invalid', async () => {
        const res = await GET(new Request('http://localhost/api/visites-mediacales?limit=abc&offset=abc'));

        expect(res.status).toBe(400);
        expect(getVisitesMedicalesFeedMock).not.toHaveBeenCalled();

        const body = await res.json();
        expect(body.message).toBe('Invalid query parameters');
    });

    it('GET returns auth error when request is unauthorized', async () => {
        requireAuthMock.mockReturnValue(new Response('Unauthorized', { status: 401 }));

        const res = await GET(new Request('http://localhost/api/visites-mediacales'));

        expect(res.status).toBe(401);
        expect(getVisitesMedicalesFeedMock).not.toHaveBeenCalled();
    });

    it('POST returns 201 when body is valid', async () => {
        createVisiteMedicaleFeedMock.mockResolvedValue({
            visiteMedicale: {
                id_salarie: 1987,
                datedde: mockDate,
                dec: mockDate,
                obv: "Objet visite",
                mtc: "Médecin du travail",
                commentaire: "Visite de routine"
            },
        });

        const res = await POST(
            new Request('http://localhost/api/visites-mediacales', {
                method: 'POST',
                headers: { 'content-type': 'application/json' },
                body: JSON.stringify({
                    id_salarie: 1987,
                    datedde: mockDate,
                    dec: mockDate,
                    obv: "Objet visite",
                    mtc: "Médecin du travail",
                    commentaire: "Visite de routine"
                }),
            }),
        );

        expect(res.status).toBe(201);
        expect(createVisiteMedicaleFeedMock).toHaveBeenCalledWith({
            id_salarie: 1987,
            datedde: new Date(mockDate),
            dec: new Date(mockDate),
            obv: "Objet visite",
            mtc: "Médecin du travail",
            commentaire: "Visite de routine"
        });

        const body = await res.json();
        expect(body).toEqual({
            message: 'Visite médicale created successfully',
            visiteMedicale: { 
                id_salarie: 1987,
            datedde: mockDate,
            dec: mockDate,
            obv: "Objet visite",
            mtc: "Médecin du travail",
            commentaire: "Visite de routine"
             },
        });
    });

    it('POST returns 400 when JSON is malformed', async () => {
        const res = await POST(
            new Request('http://localhost/api/visites-mediacales', {
                method: 'POST',
                headers: { 'content-type': 'application/json' },
                body: '{"id": 1',
            }),
        );

        expect(res.status).toBe(400);
        expect(createVisiteMedicaleFeedMock).not.toHaveBeenCalled();

        const body = await res.json();
        expect(body.message).toBe('Invalid JSON body');
    });

    it('POST returns 400 when body validation fails', async () => {
        const res = await POST(
            new Request('http://localhost/api/visites-mediacales', {
                method: 'POST',
                headers: { 'content-type': 'application/json' },
                body: JSON.stringify({ commentaire: 'Missing com' }),
            }),
        );

        expect(res.status).toBe(400);
        expect(createVisiteMedicaleFeedMock).not.toHaveBeenCalled();

        const body = await res.json();
        expect(body.message).toBe('Validation error');
    });

    it('POST returns 400 when the employee foreign key is invalid', async () => {
        createVisiteMedicaleFeedMock.mockRejectedValueOnce(new Error('Foreign key constraint failed'));

        const res = await POST(
            new Request('http://localhost/api/visites-mediacales', {
                method: 'POST',
                headers: { 'content-type': 'application/json' },
                body: JSON.stringify({
                    id_salarie: 1987,
                    datedde: mockDate,
                    dec: mockDate,
                    obv: 'Objet visite',
                    mtc: 'Médecin du travail',
                    commentaire: 'Visite de routine',
                }),
            }),
        );

        expect(res.status).toBe(400);
        expect(createVisiteMedicaleFeedMock).toHaveBeenCalled();

        const body = await res.json();
        expect(body.message).toBe('Invalid id_salarie: employee does not exist');
    });

    it('POST rethrows unexpected errors', async () => {
        createVisiteMedicaleFeedMock.mockRejectedValueOnce(new Error('boom'));

        await expect(
            POST(
                new Request('http://localhost/api/visites-mediacales', {
                    method: 'POST',
                    headers: { 'content-type': 'application/json' },
                    body: JSON.stringify({
                        id_salarie: 1987,
                        datedde: mockDate,
                        dec: mockDate,
                        obv: 'Objet visite',
                        mtc: 'Médecin du travail',
                        commentaire: 'Visite de routine',
                    }),
                }),
            ),
        ).rejects.toThrow('boom');
    });
    it('Post returns auth error when request is unauthorized', async () => {
        requireAuthMock.mockReturnValue(new Response('Unauthorized', { status: 401 }));

        const res = await POST(new Request('http://localhost/api/visites-mediacales'));

        expect(res.status).toBe(401);
        expect(getVisitesMedicalesFeedMock).not.toHaveBeenCalled();
    });
});