/**
 * Security and Validation Integration Tests
 * Exercises malformed input, CORS handling, and information-leak prevention
 * behavior at the HTTP API boundary.
 */
const request = require('supertest');
const app = require('../../../server');

describe('Security & Validation Tests', () => {
    describe('Input Validation', () => {
        it('should reject SQL injection in query parameters', async () => {
            const maliciousId = "'; DROP TABLE annotations; --";
            const res = await request(app).get(`/annotations/${maliciousId}`);
            // Should not execute, just return 404 or error
            expect([400, 404, 500]).toContain(res.status);
            expect(res.status).not.toBe(200);
        });

        it('should reject very long strings in POST data', async () => {
            const longString = 'x'.repeat(10000);
            const res = await request(app)
                .post('/annotations')
                .field('atlasId', longString)
                .field('fileHash', 'hash')
                .field('annotatorName', 'user')
                .field('values', '{}');
            
            expect(res.status).toBeGreaterThanOrEqual(400);
        });

        it('should handle special characters in names', async () => {
            const specialName = "<script>alert('xss')</script>";
            const res = await request(app)
                .post('/annotations')
                .field('atlasId', 'atlas-1')
                .field('fileHash', 'hash123')
                .field('annotatorName', specialName)
                .field('values', '{}');
            
            // Should handle gracefully (400-500 range)
            expect(res.status).toBeGreaterThanOrEqual(400);
        });
    });

    describe('CORS & Headers', () => {
        it('should allow requests without origin', async () => {
            const res = await request(app).get('/api/atlases');
            expect(res.status).toBe(200);
        });

        it('should set appropriate content-type headers', async () => {
            const res = await request(app).get('/api/atlases');
            expect(res.headers['content-type']).toMatch(/json/i);
        });

        it('should handle preflight requests', async () => {
            const res = await request(app)
                .options('/api/atlases')
                .set('Origin', 'http://localhost:3000');
            // Expect strict preflight handling
            expect(res.status).toBe(204);
        });
    });

    describe('Error Response Format', () => {
        it('should return error object on bad request', async () => {
            const res = await request(app).post('/annotations');
            expect(res.status).toBeGreaterThanOrEqual(400);
            if (res.body && typeof res.body === 'object') {
                // Should have some error property
                expect(
                    res.body.error || res.body.message || Object.keys(res.body).length > 0
                ).toBeTruthy();
            }
        });

        it('should not expose sensitive database information in errors', async () => {
            const res = await request(app).get('/annotations/invalid');
            const bodyStr = JSON.stringify(res.body);
            // Should not contain database connection strings
            expect(bodyStr).not.toMatch(/postgres:\/\//);
            expect(bodyStr).not.toMatch(/password/i);
        });
    });

    describe('Rate Limiting & Performance', () => {
        it('should handle multiple rapid requests', async () => {
            const requests = [];
            for (let i = 0; i < 10; i++) {
                requests.push(request(app).get('/api/atlases'));
            }
            
            const results = await Promise.all(requests);
            
            results.forEach(res => {
                expect(res.status).toBe(200);
            });
        });

        it('should not timeout on large queries', async () => {
            const res = await request(app)
                .get('/api/models')
                .timeout(5000);
            
            expect([200]).toContain(res.status);
        }, 10000);
    });

    describe('Concurrency', () => {
        it('should handle concurrent reads', async () => {
            const requests = [
                request(app).get('/annotations'),
                request(app).get('/api/models'),
                request(app).get('/api/atlases'),
                request(app).get('/api/form-schema')
            ];
            
            const results = await Promise.all(requests);
            
            results.forEach(res => {
                expect(res.status).toBe(200);
            });
        });
    });
});