/**
 * Response Handling Integration Tests
 * Checks response codes, payload shapes, and tolerant handling of unsupported or
 * edge-case requests across backend endpoints.
 */
const request = require('supertest');
const app = require('../../../server');

describe('Response Handling Tests', () => {
    describe('Status Codes', () => {
        it('should return 200 for successful GET requests', async () => {
            const endpoints = [
                '/api/atlases',
                '/api/models',
                '/annotations'
            ];
            
            for (const endpoint of endpoints) {
                const res = await request(app).get(endpoint);
                expect(res.status).toBe(200);
            }
        });

        it('should return 404 for non-existent endpoints', async () => {
            const res = await request(app).get('/api/nonexistent-endpoint');
            expect(res.status).toBeGreaterThanOrEqual(400);
        });

        it('should return appropriate status for invalid data', async () => {
            const res = await request(app)
                .post('/annotations')
                .send({ invalid: 'data' });
            expect(res.status).toBeGreaterThanOrEqual(400);
        });
    });

    describe('Response Body Structure', () => {
        it('should return JSON responses', async () => {
            const res = await request(app).get('/api/atlases');
            expect(res.type).toMatch(/json/i);
            expect(typeof res.body).not.toBe('string');
        });

        it('should return consistent array format', async () => {
            const res = await request(app).get('/api/atlases');
            expect(Array.isArray(res.body)).toBe(true);
        });

        it('should return annotations wrapped in object', async () => {
            const res = await request(app).get('/annotations');
            expect(res.body).toHaveProperty('annotations');
            expect(Array.isArray(res.body.annotations)).toBe(true);
        });

        it('should not return null response bodies', async () => {
            const res = await request(app).get('/api/atlases');
            expect(res.body).not.toBeNull();
        });
    });

    describe('Empty Data Handling', () => {
        it('should return empty array instead of null', async () => {
            const res = await request(app).get('/api/models?annotated=false');
            expect(Array.isArray(res.body)).toBe(true);
            // Empty is fine, just not null
        });

        it('should handle export with no data', async () => {
            const res = await request(app).get('/export/full');
            expect(res.status).toBe(200);
            expect(Array.isArray(res.body)).toBe(true);
        });
    });

    describe('Data Integrity', () => {
        it('should return consistent data on multiple requests', async () => {
            const res1 = await request(app).get('/api/atlases');
            const res2 = await request(app).get('/api/atlases');
            
            expect(res1.body).toEqual(res2.body);
        });

        it('should preserve data types in responses', async () => {
            const res = await request(app).get('/api/models');
            
            res.body.forEach(model => {
                if (model.created_at) {
                    // Should be string (from JSON) or Date object
                    expect(typeof model.created_at).toBe('string');
                }
                if (model.has_annotations !== undefined) {
                    expect(typeof model.has_annotations).toBe('boolean');
                }
            });
        });

        it('should maintain referential integrity', async () => {
            const annotationsRes = await request(app).get('/annotations');
            const modelsRes = await request(app).get('/api/models');
            
            if (annotationsRes.body.annotations.length > 0 && modelsRes.body.length > 0) {
                const ann = annotationsRes.body.annotations[0];
                // Should have valid references
                expect(ann).toHaveProperty('annotationId');
                expect(ann).toHaveProperty('atlasId');
            }
        });
    });

    describe('HTTP Methods', () => {
        it('should handle GET requests', async () => {
            const res = await request(app).get('/api/atlases');
            expect(res.status).toBe(200);
        });

        it('should handle POST requests', async () => {
            const res = await request(app)
                .post('/annotations')
                .field('test', 'value');
            // Will fail validation but should process POST
            expect(res.status).toBeGreaterThanOrEqual(400);
        });

        it('should handle DELETE requests', async () => {
            const uuid = '00000000-0000-0000-0000-000000000000';
            const res = await request(app).delete(`/annotations/${uuid}`);
            // Should handle DELETE gracefully
            expect([200, 404, 500]).toContain(res.status);
        });

        it('should handle PATCH requests', async () => {
            const uuid = '00000000-0000-0000-0000-000000000000';
            const res = await request(app)
                .patch(`/api/annotations/${uuid}/check`)
                .send({ isChecked: true });
            // Should handle PATCH gracefully
            expect([200, 404, 500]).toContain(res.status);
        });

        it('should reject unsupported methods', async () => {
            const res = await request(app)
                .put('/api/atlases')
                .send({});
            // PUT may not be supported
            expect([404, 405, 500]).toContain(res.status);
        });
    });
});