/*
 * Copyright 2025 John G Stroh
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Adaptive Communication Orchestrator Service
 * Prevents linguistic hierarchy in pluralistic deliberation
 *
 * Support Service for PluralisticDeliberationOrchestrator
 *
 * Implements:
 * - inst_029: Adaptive Communication Tone (detect and mirror stakeholder style)
 * - inst_030: Anti-Patronizing Language Filter (blocks condescending terms)
 * - inst_031: Regional Communication Norms (Australian/NZ, Japanese, Māori protocols)
 * - inst_032: Multilingual Engagement Protocol (language barrier accommodation)
 *
 * Core Principle:
 * If Tractatus facilitates "non-hierarchical deliberation" but only communicates
 * in formal academic English, it imposes Western liberal norms and excludes
 * non-academics, non-English speakers, and working-class communities.
 *
 * Solution: Same deliberation outcome, culturally appropriate communication.
 */

const logger = require('../utils/logger.util');

/**
 * Communication style profiles
 */
const COMMUNICATION_STYLES = {
  FORMAL_ACADEMIC: {
    name: 'Formal Academic',
    characteristics: ['citations', 'technical terms', 'formal register', 'hedging'],
    tone: 'formal',
    example: 'Thank you for your principled contribution grounded in privacy rights theory.'
  },
  CASUAL_DIRECT: {
    name: 'Casual Direct (Australian/NZ)',
    characteristics: ['directness', 'anti-tall-poppy', 'informal', 'pragmatic'],
    tone: 'casual',
    pub_test: true, // Would this sound awkward in casual pub conversation?
    example: 'Right, here\'s where we landed: Save lives first, but only when it\'s genuinely urgent.'
  },
  MAORI_PROTOCOL: {
    name: 'Te Reo Māori Protocol',
    characteristics: ['mihi', 'whanaungatanga', 'collective framing', 'taonga respect'],
    tone: 'respectful',
    cultural_elements: ['kia ora', 'ngā mihi', 'whānau', 'kōrero', 'whakaaro', 'kei te pai'],
    example: 'Kia ora [Name]. Ngā mihi for bringing the voice of your whānau to this kōrero.'
  },
  JAPANESE_FORMAL: {
    name: 'Japanese Formal (Honne/Tatemae aware)',
    characteristics: ['indirect', 'high context', 'relationship-focused', 'face-saving'],
    tone: 'formal',
    cultural_concepts: ['honne', 'tatemae', 'wa', 'uchi/soto'],
    example: 'We have carefully considered your valued perspective in reaching this decision.'
  },
  PLAIN_LANGUAGE: {
    name: 'Plain Language',
    characteristics: ['simple', 'clear', 'accessible', 'non-jargon'],
    tone: 'neutral',
    example: 'We decided to prioritize safety in this case. Here\'s why...'
  }
};

/**
 * Patronizing terms to filter (inst_030)
 */
const PATRONIZING_PATTERNS = [
  { pattern: /\bsimply\b/gi, reason: 'Implies task is trivial' },
  { pattern: /\bobviously\b/gi, reason: 'Dismisses difficulty' },
  { pattern: /\bclearly\b/gi, reason: 'Assumes shared understanding' },
  { pattern: /\bas you may know\b/gi, reason: 'Condescending hedge' },
  { pattern: /\bof course\b/gi, reason: 'Assumes obviousness' },
  { pattern: /\bjust\b(?= (do|make|use|try))/gi, reason: 'Minimizes complexity' },
  { pattern: /\bbasically\b/gi, reason: 'Can be condescending' }
];

/**
 * Language detection patterns (basic - production would use proper i18n library)
 */
const LANGUAGE_PATTERNS = {
  'te-reo-maori': /\b(kia ora|ngā mihi|whānau|kōrero|aroha|mana|taonga)\b/i,
  'japanese': /[\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FAF]/,
  'spanish': /\b(hola|gracias|por favor|señor|señora)\b/i,
  'french': /\b(bonjour|merci|monsieur|madame)\b/i,
  'german': /\b(guten tag|danke|herr|frau)\b/i
};

class AdaptiveCommunicationOrchestrator {
  constructor() {
    this.styles = COMMUNICATION_STYLES;
    this.patronizingPatterns = PATRONIZING_PATTERNS;
    this.languagePatterns = LANGUAGE_PATTERNS;

    // Statistics tracking
    this.stats = {
      total_adaptations: 0,
      by_style: {
        FORMAL_ACADEMIC: 0,
        CASUAL_DIRECT: 0,
        MAORI_PROTOCOL: 0,
        JAPANESE_FORMAL: 0,
        PLAIN_LANGUAGE: 0
      },
      patronizing_terms_removed: 0,
      languages_detected: {}
    };

    logger.info('AdaptiveCommunicationOrchestrator initialized');
  }

  /**
   * Adapt communication to target audience style
   * @param {String} message - The message to adapt
   * @param {Object} context - Audience context
   * @returns {String} Adapted message
   */
  adaptCommunication(message, context = {}) {
    try {
      let adaptedMessage = message;

      // 1. Detect input language (inst_032)
      const detectedLanguage = this._detectLanguage(message);
      if (detectedLanguage && detectedLanguage !== 'english') {
        logger.info('Non-English language detected', { language: detectedLanguage });
        // In production, would trigger translation workflow
      }

      // 2. Apply anti-patronizing filter (inst_030)
      adaptedMessage = this._removePatronizingLanguage(adaptedMessage);

      // 3. Adapt to target communication style (inst_029)
      const targetStyle = context.audience || 'PLAIN_LANGUAGE';
      adaptedMessage = this._adaptToStyle(adaptedMessage, targetStyle, context);

      // 4. Apply regional/cultural adaptations (inst_031)
      if (context.cultural_context) {
        adaptedMessage = this._applyCulturalContext(adaptedMessage, context.cultural_context);
      }

      this.stats.total_adaptations++;
      if (this.stats.by_style[targetStyle] !== undefined) {
        this.stats.by_style[targetStyle]++;
      }

      return adaptedMessage;

    } catch (error) {
      logger.error('Communication adaptation error:', error);
      // Fallback: return original message
      return message;
    }
  }

  /**
   * Check if message passes pub test (inst_029)
   * Would this sound awkward in casual Australian/NZ pub conversation?
   * @param {String} message - The message to check
   * @returns {Object} Pub test result
   */
  pubTest(message) {
    const awkwardIndicators = [
      { pattern: /\bhereby\b/gi, reason: 'Too formal/legal' },
      { pattern: /\bforthwith\b/gi, reason: 'Archaic formal' },
      { pattern: /\bnotwithstanding\b/gi, reason: 'Unnecessarily complex' },
      { pattern: /\bpursuant to\b/gi, reason: 'Overly legal' },
      { pattern: /\bin accordance with\b/gi, reason: 'Bureaucratic' },
      { pattern: /\bas per\b/gi, reason: 'Business jargon' }
    ];

    const violations = [];

    for (const indicator of awkwardIndicators) {
      const matches = message.match(indicator.pattern);
      if (matches) {
        violations.push({
          term: matches[0],
          reason: indicator.reason,
          suggestion: 'Use simpler, conversational language'
        });
      }
    }

    return {
      passes: violations.length === 0,
      violations,
      message: violations.length === 0
        ? 'Message passes pub test - sounds natural in casual conversation'
        : 'Message would sound awkward in casual pub conversation'
    };
  }

  /**
   * Detect communication style from incoming message
   * @param {String} message - The message to analyze
   * @returns {String} Detected style key
   */
  detectStyle(message) {
    const lowerMessage = message.toLowerCase();

    // Check for Māori protocol indicators
    if (this.languagePatterns['te-reo-maori'].test(message)) {
      return 'MAORI_PROTOCOL';
    }

    // Check for formal academic indicators
    const formalIndicators = ['furthermore', 'notwithstanding', 'pursuant to', 'hereby', 'therefore'];
    const formalCount = formalIndicators.filter(term => lowerMessage.includes(term)).length;
    if (formalCount >= 2) {
      return 'FORMAL_ACADEMIC';
    }

    // Check for casual/direct indicators
    const casualIndicators = ['right,', 'ok,', 'yeah,', 'fair?', 'reckon', 'mate'];
    const casualCount = casualIndicators.filter(term => lowerMessage.includes(term)).length;
    if (casualCount >= 1) {
      return 'CASUAL_DIRECT';
    }

    // Default to plain language
    return 'PLAIN_LANGUAGE';
  }

  /**
   * Generate culturally-adapted greeting
   * @param {String} recipientName - Name of recipient
   * @param {Object} context - Cultural context
   * @returns {String} Appropriate greeting
   */
  generateGreeting(recipientName, context = {}) {
    const style = context.communication_style || 'PLAIN_LANGUAGE';

    switch (style) {
      case 'MAORI_PROTOCOL':
        return `Kia ora ${recipientName}`;
      case 'JAPANESE_FORMAL':
        return `${recipientName}様、いつもお世話になっております。`; // Formal Japanese greeting
      case 'CASUAL_DIRECT':
        return `Hi ${recipientName}`;
      case 'FORMAL_ACADEMIC':
        return `Dear ${recipientName},`;
      default:
        return `Hello ${recipientName}`;
    }
  }

  /**
   * Private helper methods
   */

  _detectLanguage(message) {
    for (const [language, pattern] of Object.entries(this.languagePatterns)) {
      if (pattern.test(message)) {
        // Track language detection
        if (!this.stats.languages_detected[language]) {
          this.stats.languages_detected[language] = 0;
        }
        this.stats.languages_detected[language]++;

        return language;
      }
    }
    return 'english'; // Default assumption
  }

  _removePatronizingLanguage(message) {
    let cleaned = message;
    let removedCount = 0;

    for (const { pattern, reason } of this.patronizingPatterns) {
      const beforeLength = cleaned.length;
      cleaned = cleaned.replace(pattern, '');
      const afterLength = cleaned.length;

      if (beforeLength !== afterLength) {
        removedCount++;
        logger.debug('Removed patronizing term', { reason });
      }
    }

    if (removedCount > 0) {
      this.stats.patronizing_terms_removed += removedCount;
      // Clean up extra spaces left by removals
      cleaned = cleaned.replace(/\s{2,}/g, ' ').trim();
    }

    return cleaned;
  }

  _adaptToStyle(message, styleKey, context) {
    const style = this.styles[styleKey];

    if (!style) {
      logger.warn('Unknown communication style', { styleKey });
      return message;
    }

    // Style-specific adaptations
    switch (styleKey) {
      case 'FORMAL_ACADEMIC':
        return this._adaptToFormalAcademic(message, context);
      case 'CASUAL_DIRECT':
        return this._adaptToCasualDirect(message, context);
      case 'MAORI_PROTOCOL':
        return this._adaptToMaoriProtocol(message, context);
      case 'JAPANESE_FORMAL':
        return this._adaptToJapaneseFormal(message, context);
      case 'PLAIN_LANGUAGE':
        return this._adaptToPlainLanguage(message, context);
      default:
        return message;
    }
  }

  _adaptToFormalAcademic(message, context) {
    // Add formal register, hedge appropriately
    // (In production, would use NLP transformation)
    return message;
  }

  _adaptToCasualDirect(message, context) {
    // Remove unnecessary formality, make direct
    let adapted = message;

    // Replace formal phrases with casual equivalents
    const replacements = [
      { formal: /I would like to inform you that/gi, casual: 'Just so you know,' },
      { formal: /It is important to note that/gi, casual: 'Key thing:' },
      { formal: /We have determined that/gi, casual: 'We figured' },
      { formal: /In accordance with/gi, casual: 'Following' }
    ];

    for (const { formal, casual } of replacements) {
      adapted = adapted.replace(formal, casual);
    }

    return adapted;
  }

  _adaptToMaoriProtocol(message, context) {
    // Add appropriate te reo Māori protocol elements
    // (In production, would consult with Māori language experts)
    return message;
  }

  _adaptToJapaneseFormal(message, context) {
    // Add appropriate Japanese formal register elements
    // (In production, would use Japanese language processing)
    return message;
  }

  _adaptToPlainLanguage(message, context) {
    // Simplify jargon, use clear language
    let adapted = message;

    // Replace jargon with plain equivalents
    const jargonReplacements = [
      { jargon: /utilize/gi, plain: 'use' },
      { jargon: /facilitate/gi, plain: 'help' },
      { jargon: /implement/gi, plain: 'do' },
      { jargon: /endeavor/gi, plain: 'try' }
    ];

    for (const { jargon, plain } of jargonReplacements) {
      adapted = adapted.replace(jargon, plain);
    }

    return adapted;
  }

  _applyCulturalContext(message, culturalContext) {
    // Apply cultural adaptations based on context
    // (In production, would be much more sophisticated)
    return message;
  }

  /**
   * Get communication adaptation statistics
   * @returns {Object} Statistics object
   */
  getStats() {
    return {
      ...this.stats,
      timestamp: new Date()
    };
  }
}

// Singleton instance
const orchestrator = new AdaptiveCommunicationOrchestrator();

// Export both singleton (default) and class (for testing)
module.exports = orchestrator;
module.exports.AdaptiveCommunicationOrchestrator = AdaptiveCommunicationOrchestrator;
