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

const { requireAuthMock, listAvenantMock, createAvenantMock } = vi.hoisted(() => ({
    requireAuthMock: vi.fn(),
    listAvenantMock: vi.fn(),
    createAvenantMock: vi.fn(),
}));

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

vi.mock('@/server/avenants.server', () => ({
    getAvenantsFeed: listAvenantMock,
    createAvenantFeed: createAvenantMock,
}));

import { GET, POST } from '../../../../src/app/api/avenants/route';

describe('Unit — /api/avenants route', () => {
    beforeEach(() => {
        vi.resetAllMocks();
        requireAuthMock.mockReturnValue(null);
    });

    it('GET returns the paginated avenantlist', async () => {
        listAvenantMock.mockResolvedValue({
            items: [
                {
                    id: 1,
                    avenant: 'avenantautorisee',
                    libavenant: 'AA',
                    date_creation: '2026-05-21T08:16:08.000Z',
                },
            ],
            count: 1,
        });

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

        expect(res.status).toBe(200);
        expect(listAvenantMock).toHaveBeenCalledWith(20, 0);

        const body = await res.json();
        expect(body).toEqual({
            message: 'Avenants retrieved successfully',
            items: [
                {
                    id: 1,
                    avenant: 'avenantautorisee',
                    libavenant: 'AA',
                    date_creation: '2026-05-21T08:16:08.000Z',
                },
            ],
            count: 1,
        });
    });

    it('GET returns 400 for invalid query parameters', async () => {
        const res = await GET(new Request('http://localhost/api/avenants?limit=abc'));

        expect(res.status).toBe(400);
        expect(listAvenantMock).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/avenants'));

        expect(res.status).toBe(401);
        expect(listAvenantMock).not.toHaveBeenCalled();
    });
    it('POST creates a Avenant', async () => {
        createAvenantMock.mockResolvedValue({
            avenant: {
                id: 1,
                id_avenant: 1,
                id_contrat: 1,
                avenant_type: "Nouveau contrat"
            }
        });

        const res = await POST(
            new Request('http://localhost/api/avenants', {
                method: 'POST',
                headers: { 'content-type': 'application/json' },
                body: JSON.stringify({
                    id_avenant: 1,
                    id_contrat: 1,
                    avenant_type: "Nouveau contrat"
                }),
            }),
        );

        expect(res.status).toBe(201);
        expect(createAvenantMock).toHaveBeenCalledWith({
            id_avenant: 1,
            id_contrat: 1,
            avenant_type: "Nouveau contrat"
        });

        const body = await res.json();
        expect(body).toEqual({
            message: 'Avenant created successfully',
            avenant: {
                id: 1,
                id_avenant: 1,
                id_contrat: 1,
                avenant_type: "Nouveau contrat"
            },
        });
    });

    it('POST returns 404 when contrat is not found', async () => {
        createAvenantMock.mockResolvedValue({
            avenant: null,
            error: 'CONTRAT_NOT_FOUND',
        });

        const res = await POST(
            new Request('http://localhost/api/avenants', {
                method: 'POST',
                headers: { 'content-type': 'application/json' },
                body: JSON.stringify({
                    id_avenant: 1,
                    id_contrat: 999,
                    avenant_type: 'Nouveau contrat',
                }),
            }),
        );

        expect(res.status).toBe(404);
        expect(createAvenantMock).toHaveBeenCalledWith({
            id_avenant: 1,
            id_contrat: 999,
            avenant_type: 'Nouveau contrat',
        });

        const body = await res.json();
        expect(body).toEqual({
            message: 'Contrat not found for the provided id_contrat',
        });
    });

    it('POST returns 400 for invalid JSON', async () => {
        const res = await POST(
            new Request('http://localhost/api/avenants', {
                method: 'POST',
                headers: { 'content-type': 'application/json' },
                body: '{"Avenant": "avenantautorisee"',
            }),
        );

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

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

    it('POST returns 400 for invalid body', async () => {
        const res = await POST(
            new Request('http://localhost/api/avenants', {
                method: 'POST',
                headers: { 'content-type': 'application/json' },
                body: JSON.stringify({ libavenant: 'Missing avenant' }),
            }),
        );

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

        const body = await res.json();
        expect(body.message).toBe('Invalid body parameters');
    });
    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/avenants'));

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