import { AutoReporter } from '../reporters/AutoReporter.js';
/**
 * TESTS D'INTÉGRATION COMPLETS - API Server
 * Tests avec serveur HTTP réel et requêtes HTTP authentiques
 */

import { describe, it, before, after } from 'node:test';
import assert from 'node:assert';
import http from 'node:http';
import { requireCommonJS } from '../_helpers/commonjs-bridge.js';

const { ManualServer } = requireCommonJS('modes/ManualServer');

// Helper pour faire des requêtes HTTP
function makeRequest(options, postData = null) {
  return new Promise((resolve, reject) => {
    const req = http.request(options, (res) => {
      let data = '';
      res.on('data', chunk => data += chunk);
      res.on('end', () => {
        try {
          const parsed = res.headers['content-type']?.includes('application/json')
            ? JSON.parse(data)
            : data;
          resolve({ statusCode: res.statusCode, headers: res.headers, data: parsed });
        } catch (e) {
          resolve({ statusCode: res.statusCode, headers: res.headers, data });
        }
      });
    });

    req.on('error', reject);

    if (postData) {
      req.write(typeof postData === 'object' ? JSON.stringify(postData) : postData);
    }
    req.end();
  });
}


// Auto-Reporter Configuration
const autoReporter = new AutoReporter();

describe('API Server - Tests d\'Intégration Complets', () => {
  let server;
  let baseUrl;
  const testPort = 3099; // Port spécifique pour les tests

  before(async () => {
    // Démarrer serveur de test
    server = new ManualServer({ port: testPort, wsPort: 8099 });
    await server.start();
    baseUrl = `http://localhost:${testPort}`;

    console.log(`🚀 Serveur de test démarré sur ${baseUrl}`);
  });

  after(async () => {
    if (server) {
      await server.stop();
      console.log('🛑 Serveur de test arrêté');
    }
  });

  describe('🏥 Health Check Integration', () => {
    it('should respond to health check with real HTTP', async () => {
      const response = await makeRequest({
        hostname: 'localhost',
        port: testPort,
        path: '/api/health',
        method: 'GET',
        headers: { 'Accept': 'application/json' }
      });

      assert.strictEqual(response.statusCode, 200);
      assert.strictEqual(response.data.success, true);
      assert.strictEqual(response.data.data.status, 'healthy');
      assert.ok(response.data.data.version);
      assert.ok(typeof response.data.data.uptime === 'number');
    });

    it('should include correct headers in health response', async () => {
      const response = await makeRequest({
        hostname: 'localhost',
        port: testPort,
        path: '/api/health',
        method: 'GET'
      });

      assert.ok(response.headers['content-type'].includes('application/json'));
      assert.strictEqual(response.statusCode, 200);
    });
  });

  describe('📊 Metrics Integration', () => {
    it('should return system metrics via real HTTP', async () => {
      const response = await makeRequest({
        hostname: 'localhost',
        port: testPort,
        path: '/api/metrics',
        method: 'GET',
        headers: { 'Accept': 'application/json' }
      });

      assert.strictEqual(response.statusCode, 200);
      assert.strictEqual(response.data.success, true);
      assert.ok(response.data.data.articles);
      assert.ok(response.data.data.projects);
      assert.ok(response.data.data.templates);
      assert.ok(response.data.data.system);

      // Vérifier types
      assert.strictEqual(typeof response.data.data.articles.total, 'number');
      assert.strictEqual(typeof response.data.data.system.uptime, 'number');
    });
  });

  describe('📁 Projects Integration', () => {
    let createdProjectId;

    it('should create project via POST request', async () => {
      const projectData = {
        name: 'Test Integration Project',
        description: 'Projet créé via test d\'intégration',
        config: {
          defaultPersonality: 'Marc',
          selectiveStack: 'standardEnhancement'
        }
      };

      const response = await makeRequest({
        hostname: 'localhost',
        port: testPort,
        path: '/api/projects',
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json'
        }
      }, projectData);

      assert.strictEqual(response.statusCode, 201);
      assert.strictEqual(response.data.success, true);
      assert.strictEqual(response.data.data.name, projectData.name);
      assert.strictEqual(response.data.data.description, projectData.description);
      assert.ok(response.data.data.id);
      assert.ok(response.data.data.createdAt);

      createdProjectId = response.data.data.id;
    });

    it('should return 400 for invalid project data', async () => {
      const response = await makeRequest({
        hostname: 'localhost',
        port: testPort,
        path: '/api/projects',
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        }
      }, { description: 'Sans nom' });

      assert.strictEqual(response.statusCode, 400);
      assert.strictEqual(response.data.success, false);
      assert.ok(response.data.error.includes('Nom du projet requis'));
    });

    it('should retrieve projects list including created project', async () => {
      const response = await makeRequest({
        hostname: 'localhost',
        port: testPort,
        path: '/api/projects',
        method: 'GET',
        headers: { 'Accept': 'application/json' }
      });

      assert.strictEqual(response.statusCode, 200);
      assert.strictEqual(response.data.success, true);
      assert.ok(Array.isArray(response.data.data.projects));
      assert.ok(response.data.data.projects.length >= 1);

      // Vérifier que notre projet créé est présent
      const createdProject = response.data.data.projects.find(p => p.id === createdProjectId);
      assert.ok(createdProject);
      assert.strictEqual(createdProject.name, 'Test Integration Project');
    });
  });

  describe('📋 Templates Integration', () => {
    let createdTemplateId;

    it('should create template via POST request', async () => {
      const templateData = {
        name: 'Template Integration Test',
        content: '<?xml version="1.0" encoding="UTF-8"?><template><title>{{TITLE}}</title><content>{{CONTENT}}</content></template>',
        description: 'Template créé via test d\'intégration',
        category: 'integration-test'
      };

      const response = await makeRequest({
        hostname: 'localhost',
        port: testPort,
        path: '/api/templates',
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json'
        }
      }, templateData);

      assert.strictEqual(response.statusCode, 201);
      assert.strictEqual(response.data.success, true);
      assert.strictEqual(response.data.data.name, templateData.name);
      assert.strictEqual(response.data.data.content, templateData.content);
      assert.strictEqual(response.data.data.category, templateData.category);

      createdTemplateId = response.data.data.id;
    });

    it('should retrieve templates list', async () => {
      const response = await makeRequest({
        hostname: 'localhost',
        port: testPort,
        path: '/api/templates',
        method: 'GET'
      });

      assert.strictEqual(response.statusCode, 200);
      assert.ok(Array.isArray(response.data.data.templates));

      const createdTemplate = response.data.data.templates.find(t => t.id === createdTemplateId);
      assert.ok(createdTemplate);
    });
  });

  describe('📝 Articles Integration', () => {
    it('should validate article creation input', async () => {
      const response = await makeRequest({
        hostname: 'localhost',
        port: testPort,
        path: '/api/articles',
        method: 'POST',
        headers: { 'Content-Type': 'application/json' }
      }, {});

      assert.strictEqual(response.statusCode, 400);
      assert.strictEqual(response.data.success, false);
      assert.ok(response.data.error.includes('Mot-clé ou numéro de ligne requis'));
    });

    it('should accept valid article creation request', async () => {
      const articleData = {
        keyword: 'test intégration keyword',
        project: 'integration-test',
        config: {
          selectiveStack: 'lightEnhancement',
          adversarialMode: 'none'
        }
      };

      // Note: Ce test peut prendre du temps car il fait appel aux LLMs
      const response = await makeRequest({
        hostname: 'localhost',
        port: testPort,
        path: '/api/articles',
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json'
        }
      }, articleData);

      // Peut être 201 (succès) ou 500 (erreur LLM/Google Sheets)
      assert.ok([201, 500].includes(response.statusCode));

      if (response.statusCode === 201) {
        assert.strictEqual(response.data.success, true);
        assert.ok(response.data.data.id || response.data.data.article);
      } else {
        // Erreur attendue si pas d'accès LLM/Sheets
        assert.strictEqual(response.data.success, false);
      }
    });

    it('should retrieve articles list', async () => {
      const response = await makeRequest({
        hostname: 'localhost',
        port: testPort,
        path: '/api/articles',
        method: 'GET',
        headers: { 'Accept': 'application/json' }
      });

      // Peut être 200 (succès) ou 500 (erreur Google Sheets)
      assert.ok([200, 500].includes(response.statusCode));

      if (response.statusCode === 200) {
        assert.ok(Array.isArray(response.data.data.articles));
        assert.ok(typeof response.data.data.total === 'number');
      }
    });

    it('should handle pagination parameters', async () => {
      const response = await makeRequest({
        hostname: 'localhost',
        port: testPort,
        path: '/api/articles?limit=10&offset=5',
        method: 'GET'
      });

      // Même si ça échoue côté Google Sheets, la structure doit être correcte
      if (response.statusCode === 200) {
        assert.strictEqual(response.data.data.limit, 10);
        assert.strictEqual(response.data.data.offset, 5);
      }
    });
  });

  describe('⚙️ Configuration Integration', () => {
    it('should retrieve personalities configuration', async () => {
      const response = await makeRequest({
        hostname: 'localhost',
        port: testPort,
        path: '/api/config/personalities',
        method: 'GET'
      });

      // Peut échouer si Google Sheets non accessible
      assert.ok([200, 500].includes(response.statusCode));

      if (response.statusCode === 200) {
        assert.strictEqual(response.data.success, true);
        assert.ok(Array.isArray(response.data.data.personalities));
        assert.ok(typeof response.data.data.total === 'number');
      }
    });
  });

  describe('🌐 HTTP Protocol Compliance', () => {
    it('should handle OPTIONS requests (CORS preflight)', async () => {
      const response = await makeRequest({
        hostname: 'localhost',
        port: testPort,
        path: '/api/health',
        method: 'OPTIONS'
      });

      // Express + CORS devrait gérer OPTIONS
      assert.ok([200, 204].includes(response.statusCode));
    });

    it('should return 404 for non-existent endpoints', async () => {
      const response = await makeRequest({
        hostname: 'localhost',
        port: testPort,
        path: '/api/nonexistent',
        method: 'GET'
      });

      assert.strictEqual(response.statusCode, 404);
    });

    it('should handle malformed JSON gracefully', async () => {
      const response = await makeRequest({
        hostname: 'localhost',
        port: testPort,
        path: '/api/projects',
        method: 'POST',
        headers: { 'Content-Type': 'application/json' }
      }, '{ invalid json }');

      assert.strictEqual(response.statusCode, 400);
    });

    it('should set correct content-type headers', async () => {
      const response = await makeRequest({
        hostname: 'localhost',
        port: testPort,
        path: '/api/health',
        method: 'GET'
      });

      assert.ok(response.headers['content-type'].includes('application/json'));
    });
  });

  describe('🔒 Error Handling Integration', () => {
    it('should handle server errors gracefully', async () => {
      // Tenter de récupérer un article avec ID invalide
      const response = await makeRequest({
        hostname: 'localhost',
        port: testPort,
        path: '/api/articles/invalid_id_format',
        method: 'GET'
      });

      assert.strictEqual(response.statusCode, 500);
      assert.strictEqual(response.data.success, false);
      assert.ok(response.data.error);
      assert.ok(response.data.message);
    });

    it('should maintain consistent error format across endpoints', async () => {
      const responses = await Promise.all([
        makeRequest({
          hostname: 'localhost',
          port: testPort,
          path: '/api/projects',
          method: 'POST',
          headers: { 'Content-Type': 'application/json' }
        }, {}),
        makeRequest({
          hostname: 'localhost',
          port: testPort,
          path: '/api/templates',
          method: 'POST',
          headers: { 'Content-Type': 'application/json' }
        }, {}),
        makeRequest({
          hostname: 'localhost',
          port: testPort,
          path: '/api/articles',
          method: 'POST',
          headers: { 'Content-Type': 'application/json' }
        }, {})
      ]);

      responses.forEach(response => {
        assert.strictEqual(response.statusCode, 400);
        assert.strictEqual(response.data.success, false);
        assert.ok(response.data.error);
        assert.ok(typeof response.data.error === 'string');
      });
    });
  });

  describe('📈 Performance Integration', () => {
    it('should respond to health check within reasonable time', async () => {
      const start = Date.now();

      const response = await makeRequest({
        hostname: 'localhost',
        port: testPort,
        path: '/api/health',
        method: 'GET'
      });

      const duration = Date.now() - start;

      assert.strictEqual(response.statusCode, 200);
      assert.ok(duration < 1000, `Health check took ${duration}ms, should be < 1000ms`);
    });

    it('should handle concurrent requests', async () => {
      const concurrentRequests = Array(5).fill().map(() =>
        makeRequest({
          hostname: 'localhost',
          port: testPort,
          path: '/api/metrics',
          method: 'GET'
        })
      );

      const responses = await Promise.all(concurrentRequests);

      responses.forEach(response => {
        assert.strictEqual(response.statusCode, 200);
        assert.strictEqual(response.data.success, true);
      });
    });
  });
});

console.log('🔥 Tests d\'Intégration API Server - Validation HTTP complète');