/**
 * Integration tests for HAZOP AI Service
 * These tests make actual API calls to Gemini and require GEMINI_API_KEY
 * Run with: npm test -- hazop-ai-service.integration.test.js
 */

const { generateHazards } = require('./hazop-ai-service');

// Skip these tests if GEMINI_API_KEY is not set
const describeIfApiKey = process.env.GEMINI_API_KEY ? describe : describe.skip;

describeIfApiKey('HAZOP AI Service - Integration Tests', () => {
  
  describe('generateHazards', () => {
    
    test('should generate hazards with all required properties (Property 8, 9, 10, 11)', async () => {
      const input = {
        facilityName: 'Test Chemical Plant',
        processDescription: 'Chemical reactor for producing polymers using exothermic reactions with flammable solvents',
        materials: 'Ethylene, Propylene, Catalyst, Flammable solvents',
        processType: 'chemical',
        projectPhase: 'design'
      };
      
      const hazards = await generateHazards(input);
      
      // Property 9: Minimum 5 hazards
      expect(hazards.length).toBeGreaterThanOrEqual(5);
      
      // Property 8: All 5 categories covered
      const categories = hazards.map(h => h.category);
      const uniqueCategories = [...new Set(categories)];
      expect(uniqueCategories).toContain('Process');
      expect(uniqueCategories).toContain('Structural');
      expect(uniqueCategories).toContain('Human');
      expect(uniqueCategories).toContain('Environment');
      expect(uniqueCategories).toContain('External');
      
      // Property 10 & 11: Validate each hazard structure
      hazards.forEach((hazard, index) => {
        // Property 10: All required fields present
        expect(hazard).toHaveProperty('hazardRef');
        expect(hazard).toHaveProperty('category');
        expect(hazard).toHaveProperty('description');
        expect(hazard).toHaveProperty('cause');
        expect(hazard).toHaveProperty('consequence');
        expect(hazard).toHaveProperty('affectedParties');
        expect(hazard).toHaveProperty('safeguards');
        expect(hazard).toHaveProperty('recommendations');
        expect(hazard).toHaveProperty('likelihood');
        expect(hazard).toHaveProperty('severity');
        expect(hazard).toHaveProperty('riskScore');
        expect(hazard).toHaveProperty('riskLevel');
        expect(hazard).toHaveProperty('priority');
        expect(hazard).toHaveProperty('accepted');
        
        // Validate field types
        expect(typeof hazard.hazardRef).toBe('string');
        expect(typeof hazard.category).toBe('string');
        expect(typeof hazard.description).toBe('string');
        expect(typeof hazard.cause).toBe('string');
        expect(typeof hazard.consequence).toBe('string');
        expect(Array.isArray(hazard.affectedParties)).toBe(true);
        expect(Array.isArray(hazard.safeguards)).toBe(true);
        expect(Array.isArray(hazard.recommendations)).toBe(true);
        expect(typeof hazard.likelihood).toBe('number');
        expect(typeof hazard.severity).toBe('number');
        expect(typeof hazard.riskScore).toBe('number');
        expect(typeof hazard.riskLevel).toBe('string');
        expect(typeof hazard.priority).toBe('string');
        expect(typeof hazard.accepted).toBe('boolean');
        
        // Validate value ranges
        expect(hazard.likelihood).toBeGreaterThanOrEqual(1);
        expect(hazard.likelihood).toBeLessThanOrEqual(5);
        expect(hazard.severity).toBeGreaterThanOrEqual(1);
        expect(hazard.severity).toBeLessThanOrEqual(5);
        
        // Property 11: Valid priority values
        expect(['Immediate', 'Short-term', 'Long-term']).toContain(hazard.priority);
        
        // Validate risk level matches calculated score
        const expectedScore = hazard.likelihood * hazard.severity;
        expect(hazard.riskScore).toBe(expectedScore);
        
        let expectedLevel;
        if (expectedScore < 6) expectedLevel = 'Low';
        else if (expectedScore <= 11) expectedLevel = 'Medium';
        else if (expectedScore <= 14) expectedLevel = 'High';
        else expectedLevel = 'Critical';
        expect(hazard.riskLevel).toBe(expectedLevel);
        
        // Validate hazard reference format
        expect(hazard.hazardRef).toMatch(/^HZD-\d{2}$/);
        
        // Validate accepted is false by default
        expect(hazard.accepted).toBe(false);
      });
    }, 30000); // 30 second timeout for API call
    
    test('should handle different process types', async () => {
      const input = {
        facilityName: 'Offshore Oil Platform',
        processDescription: 'Oil and gas extraction and processing facility with high-pressure systems',
        materials: 'Crude oil, Natural gas, Drilling fluids',
        processType: 'oil-gas',
        projectPhase: 'operation'
      };
      
      const hazards = await generateHazards(input);
      
      expect(hazards.length).toBeGreaterThanOrEqual(5);
      
      // Verify all categories are covered
      const categories = hazards.map(h => h.category);
      const uniqueCategories = [...new Set(categories)];
      expect(uniqueCategories.length).toBe(5);
    }, 30000);
    
    test('should handle different project phases', async () => {
      const input = {
        facilityName: 'Mining Operation',
        processDescription: 'Underground mining with ore processing and tailings management',
        materials: 'Ore, Explosives, Processing chemicals',
        processType: 'mining',
        projectPhase: 'concept'
      };
      
      const hazards = await generateHazards(input);
      
      expect(hazards.length).toBeGreaterThanOrEqual(5);
      
      // Verify structure is correct
      hazards.forEach(hazard => {
        expect(hazard).toHaveProperty('hazardRef');
        expect(hazard).toHaveProperty('category');
        expect(hazard).toHaveProperty('priority');
      });
    }, 30000);
  });
});
