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

// Integration test skeleton for /api/employes
// Replace placeholders with real calls and assertions.
const BASE = process.env.TEST_BASE_URL ?? 'http://localhost:8000';
const ADMIN_USER = process.env.AUTH_ADMIN_USERNAME ?? 'admin';
const ADMIN_PASS = process.env.AUTH_ADMIN_PASSWORD ?? 'admin';

async function loginAsAdmin() {
    const loginRes = await fetch(`${BASE}/api/auth/login`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ username: ADMIN_USER, password: ADMIN_PASS }),
    });

    expect(loginRes.status).toBeGreaterThanOrEqual(200);
    expect(loginRes.status).toBeLessThan(300);

    const loginBody = await loginRes.json();
    expect(loginBody.token).toBeTruthy();

    return loginBody.token as string;
}

describe('Integration — Employes', () => {
    it('GET /api/employes', async () => {
        const token = await loginAsAdmin();

        const res = await fetch(`${BASE}/api/employes`, {
            method: 'GET',
            headers: { Authorization: `Bearer ${token}` },
        });

        expect(res.status).toBe(200);
        const body = await res.json();
        expect(body).toBeDefined();
        expect(body.message).toBeTruthy();
        expect(Array.isArray(body.items)).toBe(true);
    });

    it('GET /api/employes/[cos]', async () => {
        const token = await loginAsAdmin();

        const cos = Number(String(Date.now()).slice(-6));
        const createRes = await fetch(`${BASE}/api/employes/`, {
            method: 'POST',
            headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
            body: JSON.stringify({
                COS: cos,
                TIT: 'Test',
                PRE: 'Employe',
                EmailE2e: `cos-${cos}@example.com`,
            }),
        });

        expect(createRes.status).toBe(201);

        // Some deployments paginate or serialize COS as string. Instead of
        // relying on the listing, fetch the created employee directly with retries
        // to account for eventual visibility.
        let getCreatedRes: Response | null = null;
        for (let i = 0; i < 6; i++) {
            getCreatedRes = await fetch(`${BASE}/api/employes/${cos}`, {
                method: 'GET',
                headers: { Authorization: `Bearer ${token}` },
            });
            if (getCreatedRes.status === 200) break;
            await new Promise((r) => setTimeout(r, 250));
        }

        expect(getCreatedRes).not.toBeNull();
        expect(getCreatedRes!.status).toBe(200);
        const createdBody = await getCreatedRes!.json();
        expect(createdBody).toBeDefined();
        expect(createdBody.employe).toBeDefined();
        expect(Number(createdBody.employe.COS)).toBe(cos);

        const res = await fetch(`${BASE}/api/employes/${cos}`, {
            method: 'GET',
            headers: { Authorization: `Bearer ${token}` },
        });

        expect(res.status).toBe(200);
        const body = await res.json();
        expect(body).toBeDefined();
        expect(body.message).toBeTruthy();  
        expect(body.employe).toBeDefined();
        expect(body.employe.COS).toBe(cos);
    });

    it('POST /api/employes', async () => {
        const token = await loginAsAdmin();

        const res = await fetch(`${BASE}/api/employes/`, {
            method: 'POST',
            headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
            body: JSON.stringify({
                "COS": 999999,
                "TIT": "Seigneur",
                "NSA": "Le tout puissant",
                "NJF": "",
                "PRE": "Bobo",
                "VIL": "Lille",
                "EmailE2e": "bobolebg@example.com"
            })
        });

        expect(res.status).toBe(201);
        const body = await res.json();
        expect(body).toBeDefined();
        expect(body.message).toBeTruthy();
        expect(body.employe).toBeDefined();
        expect(body.employe.COS).toBe(999999);
    });
    it('PUT /api/employes', async () => {
        const token = await loginAsAdmin();
        const cos = 912345;

        const createRes = await fetch(`${BASE}/api/employes/`, {
            method: 'POST',
            headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
            body: JSON.stringify({ COS: cos, TIT: 'Seigneur', PRE: 'Bobo', EmailE2e: 'update-employe@example.com' }),
        });
        expect(createRes.status).toBe(201);

        const res = await fetch(`${BASE}/api/employes/${cos}`, {
            method: 'PUT',
            headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
            body: JSON.stringify({
                TIT: 'Seigneur D\'Elden (margitt c\'est fait aracher)',
            })
        });

        expect(res.status).toBe(200);
        const body = await res.json();
        expect(body).toBeDefined();
        expect(body.message).toBeTruthy();
        expect(body.employe).toBeDefined();
        expect(body.employe.TIT).toBe("Seigneur D'Elden (margitt c'est fait aracher)");
    });

    it('PUT /api/employes can deactivate an employee without deleting it', async () => {
        const token = await loginAsAdmin();
        const cos = 888888;

        const createRes = await fetch(`${BASE}/api/employes/`, {
            method: 'POST',
            headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
            body: JSON.stringify({ COS: cos, TIT: 'Temp', PRE: 'Temp', EmailE2e: 'temp@example.com' }),
        });
        expect(createRes.status).toBe(201);

        const updateRes = await fetch(`${BASE}/api/employes/${cos}`, {
            method: 'PUT',
            headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
            body: JSON.stringify({ Actif: false }),
        });

        expect(updateRes.status).toBe(200);
        const updateBody = await updateRes.json();
        expect(updateBody.employe).toBeDefined();
        expect(updateBody.employe.Actif).toBe(false);

        const getRes = await fetch(`${BASE}/api/employes/${cos}`, {
            method: 'GET',
            headers: { Authorization: `Bearer ${token}` },
        });

        expect(getRes.status).toBe(200);
        const getBody = await getRes.json();
        expect(getBody.employe).toBeDefined();
        expect(getBody.employe.Actif).toBe(false);

        const deleteRes = await fetch(`${BASE}/api/employes/${cos}`, {
            method: 'DELETE',
            headers: { Authorization: `Bearer ${token}` },
        });

        expect(deleteRes.status).toBe(200);
    });
    it('DELETE /api/employes', async () => {
        const token = await loginAsAdmin();

        const cos = 999999;

        const createRes = await fetch(`${BASE}/api/employes/`, {
            method: 'POST',
            headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
            body: JSON.stringify({ COS: cos, TIT: 'Temp', PRE: 'Temp', EmailE2e: 'delete-employe@example.com' }),
        });
        expect(createRes.status).toBe(201);

        const res = await fetch(`${BASE}/api/employes/${cos}`, {
            method: 'DELETE',
            headers: { Authorization: `Bearer ${token}` },
        });

        expect(res.status).toBe(200);
        const body = await res.json();
        expect(body).toBeDefined();
        expect(body.message).toBeTruthy();
        expect(body.employe).toBeDefined();
        expect(body.employe.COS).toBe(cos);
    });

    it('DELETE /api/employes should return 409 when dependent contrat exists', async () => {
        const token = await loginAsAdmin();

        // create employee
        const cos = 777777;
        const createRes = await fetch(`${BASE}/api/employes/`, {
            method: 'POST',
            headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
            body: JSON.stringify({ COS: cos, TIT: 'Test', PRE: 'T', EmailE2e: 't@example.com' }),
        });
        expect(createRes.status).toBe(201);

        // create a contrat that references the employee via the public field
        const contratRes = await fetch(`${BASE}/api/contrats`, {
            method: 'POST',
            headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
            body: JSON.stringify({ id_salarie: cos }),
        });

        expect(contratRes.status).toBeGreaterThanOrEqual(200);
        expect(contratRes.status).toBeLessThan(300);

        // attempt to delete employe -> should be 409 due to FK constraint
        const delRes = await fetch(`${BASE}/api/employes/${cos}`, {
            method: 'DELETE',
            headers: { Authorization: `Bearer ${token}` },
        });

        expect(delRes.status).toBe(409);
    });
});
