/**
 * Unit Tests for AdaptiveCommunicationOrchestrator
 * Tests culturally-adaptive communication to prevent linguistic hierarchy
 */

const orchestrator = require('../../src/services/AdaptiveCommunicationOrchestrator.service');

describe('AdaptiveCommunicationOrchestrator', () => {
  beforeEach(() => {
    // Orchestrator is a singleton instance
  });

  describe('Anti-Patronizing Filter (inst_030)', () => {
    test('should remove "simply" from messages', () => {
      const message = 'You can simply implement this feature easily.';

      const adapted = orchestrator.adaptCommunication(message);

      expect(adapted).not.toContain('simply');
    });

    test('should remove "obviously" from messages', () => {
      const message = 'Obviously, this approach is the best solution.';

      const adapted = orchestrator.adaptCommunication(message);

      expect(adapted).not.toContain('obviously');
    });

    test('should remove "as you may know" from messages', () => {
      const message = 'As you may know, AI governance requires careful consideration.';

      const adapted = orchestrator.adaptCommunication(message);

      expect(adapted).not.toContain('as you may know');
    });

    test('should track patronizing terms removed', () => {
      const statsBefore = orchestrator.getStats();

      orchestrator.adaptCommunication('Simply put, obviously this is clear.');

      const statsAfter = orchestrator.getStats();

      expect(statsAfter.patronizing_terms_removed).toBeGreaterThan(statsBefore.patronizing_terms_removed);
    });

    test('should handle multiple patronizing terms', () => {
      const message = 'Simply put, it is obviously clear that you can just do this, of course.';

      const adapted = orchestrator.adaptCommunication(message);

      expect(adapted).not.toContain('simply');
      expect(adapted).not.toContain('obviously');
      expect(adapted).not.toContain('of course');
    });
  });

  describe('Pub Test (inst_029)', () => {
    test('should flag overly formal language', () => {
      const message = 'Notwithstanding the aforementioned circumstances, we hereby decree...';

      const result = orchestrator.pubTest(message);

      expect(result.passes).toBe(false);
      expect(result.violations.length).toBeGreaterThan(0);
    });

    test('should pass casual conversational language', () => {
      const message = 'Right, here\'s what we decided: We\'re going with option A.';

      const result = orchestrator.pubTest(message);

      expect(result.passes).toBe(true);
      expect(result.violations.length).toBe(0);
    });

    test('should flag "pursuant to" as too legal', () => {
      const message = 'Pursuant to our discussion, we will proceed accordingly.';

      const result = orchestrator.pubTest(message);

      expect(result.passes).toBe(false);
      const hasLegalViolation = result.violations.some(v => v.reason.includes('legal'));
      expect(hasLegalViolation).toBe(true);
    });

    test('should flag "notwithstanding" as unnecessarily complex', () => {
      const message = 'Notwithstanding your concerns, we shall continue.';

      const result = orchestrator.pubTest(message);

      expect(result.passes).toBe(false);
      expect(result.violations[0].reason).toContain('Unnecessarily complex');
    });
  });

  describe('Communication Style Detection', () => {
    test('should detect formal academic style', () => {
      const message = 'Furthermore, notwithstanding the theoretical implications, we must therefore consider...';

      const detected = orchestrator.detectStyle(message);

      expect(detected).toBe('FORMAL_ACADEMIC');
    });

    test('should detect casual direct style', () => {
      const message = 'Right, here\'s the deal. Fair enough?';

      const detected = orchestrator.detectStyle(message);

      expect(detected).toBe('CASUAL_DIRECT');
    });

    test('should detect Māori protocol indicators', () => {
      const message = 'Kia ora! Ngā mihi for your contribution to this kōrero.';

      const detected = orchestrator.detectStyle(message);

      expect(detected).toBe('MAORI_PROTOCOL');
    });

    test('should default to plain language', () => {
      const message = 'This is a simple message without strong style indicators.';

      const detected = orchestrator.detectStyle(message);

      expect(detected).toBe('PLAIN_LANGUAGE');
    });
  });

  describe('Style Adaptation (inst_029)', () => {
    test('should adapt to formal academic style', () => {
      const message = 'We decided to go with this approach.';
      const context = { audience: 'FORMAL_ACADEMIC' };

      const adapted = orchestrator.adaptCommunication(message, context);

      expect(adapted).toBeDefined();
      // In full implementation, would check for formal register
    });

    test('should adapt to casual direct style', () => {
      const message = 'I would like to inform you that we have made a decision.';
      const context = { audience: 'CASUAL_DIRECT' };

      const adapted = orchestrator.adaptCommunication(message, context);

      // Should simplify formal phrases
      expect(adapted).not.toContain('I would like to inform you that');
    });

    test('should track adaptations by style', () => {
      const statsBefore = orchestrator.getStats();
      const beforeCount = statsBefore.by_style.FORMAL_ACADEMIC;

      orchestrator.adaptCommunication('Test message 1', { audience: 'FORMAL_ACADEMIC' });
      orchestrator.adaptCommunication('Test message 2', { audience: 'FORMAL_ACADEMIC' });

      const statsAfter = orchestrator.getStats();
      const afterCount = statsAfter.by_style.FORMAL_ACADEMIC;

      expect(afterCount).toBe(beforeCount + 2);
    });

    test('should handle plain language adaptation', () => {
      const message = 'We must utilize this methodology to facilitate implementation.';
      const context = { audience: 'PLAIN_LANGUAGE' };

      const adapted = orchestrator.adaptCommunication(message, context);

      // Should replace jargon with plain equivalents
      expect(adapted).not.toContain('utilize');
      expect(adapted).toContain('use');
    });
  });

  describe('Language Detection (inst_032)', () => {
    test('should detect Te Reo Māori', () => {
      const message = 'Kia ora, let me share some whakaaro about this kaupapa.';

      const adapted = orchestrator.adaptCommunication(message);

      // Should detect and track Māori language
      const stats = orchestrator.getStats();
      expect(stats.languages_detected['te-reo-maori']).toBeGreaterThan(0);
    });

    test('should default to English', () => {
      const message = 'This is a standard English message with no special indicators.';

      const adapted = orchestrator.adaptCommunication(message);

      // Should process as English without issues
      expect(adapted).toBeDefined();
    });
  });

  describe('Greeting Generation', () => {
    test('should generate Māori protocol greeting', () => {
      const greeting = orchestrator.generateGreeting('John', {
        communication_style: 'MAORI_PROTOCOL'
      });

      expect(greeting).toContain('Kia ora');
      expect(greeting).toContain('John');
    });

    test('should generate casual direct greeting', () => {
      const greeting = orchestrator.generateGreeting('Jane', {
        communication_style: 'CASUAL_DIRECT'
      });

      expect(greeting).toBe('Hi Jane');
    });

    test('should generate formal academic greeting', () => {
      const greeting = orchestrator.generateGreeting('Dr. Smith', {
        communication_style: 'FORMAL_ACADEMIC'
      });

      expect(greeting).toContain('Dear Dr. Smith');
    });

    test('should generate plain language greeting by default', () => {
      const greeting = orchestrator.generateGreeting('Alex');

      expect(greeting).toContain('Hello');
      expect(greeting).toContain('Alex');
    });
  });

  describe('Cultural Context Application (inst_031)', () => {
    test('should apply cultural adaptations when context provided', () => {
      const message = 'Thank you for your contribution.';
      const context = {
        audience: 'MAORI_PROTOCOL',
        cultural_context: 'maori'
      };

      const adapted = orchestrator.adaptCommunication(message, context);

      // Should apply Māori protocol adaptations
      expect(adapted).toBeDefined();
    });

    test('should handle multiple cultural contexts', () => {
      const messages = [
        { text: 'Test 1', context: { cultural_context: 'australian' } },
        { text: 'Test 2', context: { cultural_context: 'japanese' } },
        { text: 'Test 3', context: { cultural_context: 'maori' } }
      ];

      messages.forEach(({ text, context }) => {
        const adapted = orchestrator.adaptCommunication(text, context);
        expect(adapted).toBeDefined();
      });
    });
  });

  describe('Statistics Tracking', () => {
    test('should track total adaptations', () => {
      const statsBefore = orchestrator.getStats();

      orchestrator.adaptCommunication('Test message', { audience: 'PLAIN_LANGUAGE' });

      const statsAfter = orchestrator.getStats();

      expect(statsAfter.total_adaptations).toBeGreaterThan(statsBefore.total_adaptations);
    });

    test('should track adaptations by style', () => {
      orchestrator.adaptCommunication('Test 1', { audience: 'FORMAL_ACADEMIC' });
      orchestrator.adaptCommunication('Test 2', { audience: 'CASUAL_DIRECT' });

      const stats = orchestrator.getStats();

      expect(stats.by_style.FORMAL_ACADEMIC).toBeGreaterThan(0);
      expect(stats.by_style.CASUAL_DIRECT).toBeGreaterThan(0);
    });

    test('should track languages detected', () => {
      orchestrator.adaptCommunication('Kia ora whānau');

      const stats = orchestrator.getStats();

      expect(stats.languages_detected).toBeDefined();
      expect(Object.keys(stats.languages_detected).length).toBeGreaterThan(0);
    });
  });

  describe('Preventing Linguistic Hierarchy', () => {
    test('should not favor formal academic over casual direct', () => {
      const formalResult = orchestrator.adaptCommunication('Test', { audience: 'FORMAL_ACADEMIC' });
      const casualResult = orchestrator.adaptCommunication('Test', { audience: 'CASUAL_DIRECT' });

      // Both should be processed without error, neither privileged
      expect(formalResult).toBeDefined();
      expect(casualResult).toBeDefined();
    });

    test('should support non-Western communication norms', () => {
      const contexts = [
        { audience: 'MAORI_PROTOCOL' },
        { audience: 'JAPANESE_FORMAL' }
      ];

      contexts.forEach(context => {
        const adapted = orchestrator.adaptCommunication('Test message', context);
        expect(adapted).toBeDefined();
      });
    });

    test('should remove condescension from all styles', () => {
      const patronizingMessage = 'Simply put, obviously you can just do this.';

      const contexts = [
        { audience: 'FORMAL_ACADEMIC' },
        { audience: 'CASUAL_DIRECT' },
        { audience: 'PLAIN_LANGUAGE' }
      ];

      contexts.forEach(context => {
        const adapted = orchestrator.adaptCommunication(patronizingMessage, context);
        expect(adapted).not.toContain('simply');
        expect(adapted).not.toContain('obviously');
      });
    });
  });

  describe('Singleton Pattern', () => {
    test('should export singleton instance with required methods', () => {
      expect(typeof orchestrator.adaptCommunication).toBe('function');
      expect(typeof orchestrator.pubTest).toBe('function');
      expect(typeof orchestrator.detectStyle).toBe('function');
      expect(typeof orchestrator.generateGreeting).toBe('function');
      expect(typeof orchestrator.getStats).toBe('function');
    });
  });

  describe('Error Handling', () => {
    test('should handle null message gracefully', () => {
      expect(() => {
        orchestrator.adaptCommunication(null);
      }).not.toThrow();
    });

    test('should handle empty message', () => {
      const result = orchestrator.adaptCommunication('');

      expect(result).toBeDefined();
      expect(result).toBe('');
    });

    test('should handle unknown communication style', () => {
      const result = orchestrator.adaptCommunication('Test', { audience: 'UNKNOWN_STYLE' });

      expect(result).toBeDefined();
      expect(result).toBe('Test');
    });
  });

  describe('Integration Points', () => {
    test('should be usable by PluralisticDeliberationOrchestrator', () => {
      // Simulates how PDO would use this service
      const message = 'We need your input on this values conflict.';
      const stakeholder = {
        communication_style: 'formal_academic',
        cultural_context: 'western_academic'
      };

      const adapted = orchestrator.adaptCommunication(message, {
        audience: 'FORMAL_ACADEMIC',
        cultural_context: stakeholder.cultural_context
      });

      expect(adapted).toBeDefined();
    });

    test('should handle multiple stakeholder adaptations in sequence', () => {
      const message = 'Thank you for your contribution to this deliberation.';

      const stakeholders = [
        { style: 'FORMAL_ACADEMIC', context: 'academic' },
        { style: 'CASUAL_DIRECT', context: 'australian' },
        { style: 'MAORI_PROTOCOL', context: 'maori' }
      ];

      const adaptations = stakeholders.map(s =>
        orchestrator.adaptCommunication(message, {
          audience: s.style,
          cultural_context: s.context
        })
      );

      expect(adaptations.length).toBe(3);
      adaptations.forEach(adapted => {
        expect(adapted).toBeDefined();
      });
    });
  });
});
