/**
 * HAZOP/HAZID AI Service using OpenRouter DeepSeek
 * Provides AI-powered analysis for process hazard studies
 */

// System prompts
const SYSTEM_BASE = `You are NordSafe's AI Safety Engineer with 25 years of Process Safety Engineering expertise. You specialize in HAZOP (IEC 61882) and HAZID (ISO 45001) methodologies. Provide concise, technically accurate responses.`;

const SYSTEM_HAZOP_NODES = `${SYSTEM_BASE}

Generate 4-7 logical process nodes from the process description. Each node should represent a distinct section of the process with clear boundaries (similar to P&ID sections).

Return ONLY valid JSON array with this exact structure:
[
  {
    "nodeNumber": "N-01",
    "description": "Brief node description",
    "designIntent": "What this node is supposed to do",
    "parameters": ["Flow", "Pressure", "Temperature", "Level", "Composition"]
  }
]`;

const SYSTEM_HAZOP_ANALYSIS = `${SYSTEM_BASE}

Analyze the given node using IEC 61882 guidewords: No, More, Less, As Well As, Reverse, Other Than.

For each meaningful deviation, you MUST provide ALL of these fields:
- parameter: The process parameter being analyzed (e.g., "Flow", "Pressure", "Temperature")
- guideword: One of the 6 IEC 61882 guidewords
- deviation: Clear description of what the deviation means (e.g., "No Flow", "High Pressure")
- causes: Array of strings describing what could cause this deviation
- consequences: Array of strings describing what could happen
- safeguards: Array of strings describing existing protections
- recommendations: Array of strings describing additional safeguards needed
- likelihood: Number from 1-5 (1=rare, 5=almost certain)
- severity: Number from 1-5 (1=negligible, 5=catastrophic)

Return ONLY valid JSON array. Example:
[
  {
    "parameter": "Flow",
    "guideword": "No",
    "deviation": "No Flow through reactor",
    "causes": ["Pump failure", "Valve closed", "Line blockage"],
    "consequences": ["Process shutdown", "Product loss", "Equipment damage"],
    "safeguards": ["Flow indicator", "Low flow alarm", "Pump redundancy"],
    "recommendations": ["Install backup pump", "Add automatic shutdown system"],
    "likelihood": 3,
    "severity": 4
  }
]`;

const SYSTEM_HAZID = `${SYSTEM_BASE}

Generate a comprehensive hazard register for the facility across 5 categories:
1. Process Hazards (fires, explosions, toxic releases)
2. Structural Hazards (building collapse, equipment failure)
3. Human Hazards (ergonomics, fatigue, training gaps)
4. Environmental Hazards (spills, emissions, waste)
5. External Hazards (natural disasters, security threats)

For each hazard, provide:
- category: one of the 5 categories above
- description: clear description of the hazard
- cause: what causes this hazard
- consequence: potential impact
- affectedParties: array of who is affected (e.g., ["Workers", "Public", "Environment"])
- safeguards: array of existing controls (e.g., ["PPE", "Training", "Procedures"])
- recommendations: array of 2-3 specific actions to mitigate the hazard (REQUIRED - must not be empty)
- likelihood: 1-5 (1=rare, 5=certain)
- severity: 1-5 (1=negligible, 5=catastrophic)
- priority: "Immediate", "Short-term", or "Long-term"

CRITICAL: Each hazard MUST have at least 2 recommendations in the recommendations array.

Example format:
[
  {
    "category": "Process",
    "description": "Fire risk from flammable materials",
    "cause": "Ignition source near storage area",
    "consequence": "Fire, injuries, property damage",
    "affectedParties": ["Workers", "Facility"],
    "safeguards": ["Fire extinguishers", "No smoking policy"],
    "recommendations": ["Install automatic fire suppression system", "Conduct fire safety training", "Improve ventilation"],
    "likelihood": 3,
    "severity": 4,
    "priority": "Immediate"
  }
]

Return ONLY valid JSON array of hazards with at least one from each category.`;

/**
 * Call OpenRouter API
 */
async function callOpenRouter(systemPrompt, userPrompt, maxTokens = 2000) {
  if (!process.env.OPENROUTER_API_KEY) {
    throw new Error("OPENROUTER_API_KEY is not configured");
  }

  try {
    const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${process.env.OPENROUTER_API_KEY}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        model: "deepseek/deepseek-chat",
        messages: [
          {
            role: "system",
            content: systemPrompt
          },
          {
            role: "user",
            content: userPrompt
          }
        ],
        temperature: 0.3,
        max_tokens: maxTokens,
      })
    });

    console.log('📡 OpenRouter response status:', response.status);

    if (!response.ok) {
      const errorText = await response.text();
      console.error('❌ OpenRouter API error response:', errorText);
      throw new Error(`OpenRouter API returned ${response.status}: ${errorText}`);
    }

    const data = await response.json();
    console.log('✅ OpenRouter response received');
    
    if (!data.choices || !data.choices[0]) {
      console.error('❌ Invalid AI response structure:', JSON.stringify(data));
      throw new Error("Invalid AI response structure");
    }

    const aiContent = data.choices[0].message.content;
    console.log('📝 AI content length:', aiContent.length);
    
    // Remove markdown code blocks if present
    const cleanContent = aiContent.replace(/```json\n?/g, '').replace(/```\n?/g, '').trim();
    
    const parsed = JSON.parse(cleanContent);
    console.log('✅ Successfully parsed AI response');
    return parsed;
  } catch (error) {
    console.error("❌ OpenRouter API error:", error.message);
    console.error("❌ Full error:", error);
    throw new Error(`AI service error: ${error.message}`);
  }
}

/**
 * Call OpenRouter API for chat (returns plain text, not JSON)
 */
async function callOpenRouterChat(systemPrompt, userPrompt, maxTokens = 500) {
  try {
    console.log('🤖 Calling OpenRouter API for chat...');
    
    const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${process.env.OPENROUTER_API_KEY}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        model: "deepseek/deepseek-chat",
        messages: [
          {
            role: "system",
            content: systemPrompt
          },
          {
            role: "user",
            content: userPrompt
          }
        ],
        temperature: 0.7,
        max_tokens: maxTokens,
      })
    });

    console.log('📡 OpenRouter chat response status:', response.status);

    if (!response.ok) {
      const errorText = await response.text();
      console.error('❌ OpenRouter API error response:', errorText);
      throw new Error(`OpenRouter API returned ${response.status}: ${errorText}`);
    }

    const data = await response.json();
    
    if (!data.choices || !data.choices[0]) {
      console.error('❌ Invalid AI response structure');
      throw new Error("Invalid AI response structure");
    }

    const aiContent = data.choices[0].message.content;
    console.log('✅ Chat response received, length:', aiContent.length);
    
    return aiContent;
  } catch (error) {
    console.error("❌ OpenRouter chat error:", error.message);
    throw new Error(`AI chat error: ${error.message}`);
  }
}

/**
 * Calculate risk score and level from likelihood and severity
 * @param {number} likelihood - Likelihood value (1-5)
 * @param {number} severity - Severity value (1-5)
 * @returns {Object} Object with score and level
 */
function calculateRiskScore(likelihood, severity) {
  const score = likelihood * severity;
  
  let level;
  if (score < 6) level = 'Low';
  else if (score <= 11) level = 'Medium';
  else if (score <= 14) level = 'High';
  else level = 'Critical';
  
  return { score, level };
}

/**
 * Generate HAZOP nodes from process description
 * @param {Object} input - Node generation input
 * @param {string} input.processDescription - Description of the process
 * @param {string} input.materials - Materials involved in the process
 * @param {string} input.operatingPressure - Operating pressure conditions
 * @param {string} input.operatingTemperature - Operating temperature conditions
 * @param {string} input.processType - Type of process (oil-gas, chemical, etc.)
 * @returns {Promise<Array>} Array of generated HAZOP nodes
 */
async function generateNodes(input) {
  const { processDescription, materials, operatingPressure, operatingTemperature, processType } = input;
  
  // Format the prompt with process details
  const userPrompt = `Process Type: ${processType}
Process Description: ${processDescription}
Materials: ${materials}
Operating Pressure: ${operatingPressure}
Operating Temperature: ${operatingTemperature}

Generate 4-7 logical process nodes for this process. Each node should represent a distinct section with clear boundaries.

Return ONLY a valid JSON array with no additional text.`;

  try {
    const nodes = await callOpenRouter(SYSTEM_HAZOP_NODES, userPrompt, 1500);
    
    // Validate the response
    if (!Array.isArray(nodes) || nodes.length === 0) {
      throw new Error('Invalid nodes format');
    }

    // Ensure each node has required fields
    nodes.forEach((node, index) => {
      if (!node.nodeNumber) node.nodeNumber = `N-${String(index + 1).padStart(2, '0')}`;
      if (!node.description) throw new Error(`Node ${node.nodeNumber} missing description`);
      if (!node.designIntent) throw new Error(`Node ${node.nodeNumber} missing designIntent`);
      if (!Array.isArray(node.parameters) || node.parameters.length === 0) {
        node.parameters = ['Flow', 'Pressure', 'Temperature'];
      }
      node.findings = [];
    });

    return nodes;
  } catch (error) {
    console.error('Error generating nodes:', error);
    throw error;
  }
}

/**
 * Analyze a HAZOP node using IEC 61882 guidewords
 * @param {Object} input - Node analysis input
 * @param {Object} input.node - The HAZOP node to analyze
 * @param {string} input.processDescription - Description of the process
 * @param {string} input.materials - Materials involved in the process
 * @param {string} input.operatingConditions - Operating conditions (pressure, temperature)
 * @returns {Promise<Array>} Array of HAZOP findings
 */
async function analyzeNode(input) {
  const { node, processDescription, materials, operatingConditions } = input;
  
  // Format the prompt with node and process details
  const userPrompt = `Process Description: ${processDescription}
Materials: ${materials}
Operating Conditions: ${operatingConditions}

Node to Analyze:
- Node Number: ${node.nodeNumber}
- Description: ${node.description}
- Design Intent: ${node.designIntent}
- Parameters: ${node.parameters.join(', ')}

Analyze this node using IEC 61882 guidewords (No, More, Less, As Well As, Reverse, Other Than).

For EACH parameter (${node.parameters.join(', ')}), apply the relevant guidewords and generate findings.

Each finding MUST include:
1. parameter - from the node's parameters list
2. guideword - one of the 6 IEC 61882 guidewords
3. deviation - clear description (e.g., "No Flow", "High Pressure", "Low Temperature")
4. causes - array of 2-4 specific causes
5. consequences - array of 2-4 specific consequences
6. safeguards - array of 2-3 existing protections
7. recommendations - array of 1-3 additional safeguards
8. likelihood - number 1-5
9. severity - number 1-5

Generate at least 3-5 meaningful findings. Return ONLY valid JSON array, no other text.`;

  try {
    const findings = await callOpenRouter(SYSTEM_HAZOP_ANALYSIS, userPrompt, 3000);
    
    console.log('📊 Raw AI findings:', JSON.stringify(findings, null, 2));
    
    // Validate and process findings
    if (!Array.isArray(findings) || findings.length === 0) {
      throw new Error('Invalid findings format - not an array or empty');
    }

    const validatedFindings = findings.map((finding, i) => {
      // Validate required fields
      if (!finding.parameter || finding.parameter === 'Unknown') {
        console.warn(`⚠️ Finding ${i} has invalid parameter:`, finding);
      }
      if (!finding.deviation || finding.deviation === 'Deviation') {
        console.warn(`⚠️ Finding ${i} has invalid deviation:`, finding);
      }
      
      // Calculate risk score and level
      const likelihood = finding.likelihood || 3;
      const severity = finding.severity || 3;
      const { score, level } = calculateRiskScore(likelihood, severity);
      
      // Generate finding reference
      const findingRef = `${node.nodeNumber}-F-${(i + 1).toString().padStart(2, '0')}`;
      
      return {
        findingRef,
        parameter: finding.parameter || 'Unknown',
        guideword: finding.guideword || 'No',
        deviation: finding.deviation || 'Deviation',
        causes: Array.isArray(finding.causes) ? finding.causes : ['Unknown cause'],
        consequences: Array.isArray(finding.consequences) ? finding.consequences : ['Unknown consequence'],
        safeguards: Array.isArray(finding.safeguards) ? finding.safeguards : ['No safeguards identified'],
        recommendations: Array.isArray(finding.recommendations) ? finding.recommendations : ['Review required'],
        likelihood,
        severity,
        riskScore: score,
        riskLevel: level,
        accepted: false
      };
    });

    console.log('✅ Validated findings count:', validatedFindings.length);
    return validatedFindings;
  } catch (error) {
    console.error('Error analyzing node:', error);
    throw error;
  }
}

/**
 * Generate HAZID hazards across 5 categories
 * @param {Object} input - Hazard generation input
 * @param {string} input.facilityName - Name of the facility
 * @param {string} input.processDescription - Description of the process
 * @param {string} input.materials - Materials involved in the process
 * @param {string} input.processType - Type of process (oil-gas, chemical, etc.)
 * @param {string} input.projectPhase - Project phase (concept, design, construction, operation, decommission)
 * @returns {Promise<Array>} Array of generated HAZID hazards
 */
async function generateHazards(input) {
  const { facilityName, processDescription, materials, processType, projectPhase } = input;
  
  // Format the prompt with facility details
  const userPrompt = `Facility Name: ${facilityName}
Process Type: ${processType}
Project Phase: ${projectPhase}
Process Description: ${processDescription}
Materials: ${materials}

Generate a comprehensive hazard register across ALL 5 categories:
1. Process Hazards (fires, explosions, toxic releases)
2. Structural Hazards (building collapse, equipment failure)
3. Human Hazards (ergonomics, fatigue, training gaps)
4. Environmental Hazards (spills, emissions, waste)
5. External Hazards (natural disasters, security threats)

For each hazard provide:
- category, description, cause, consequence
- affectedParties (array)
- safeguards (array of existing controls)
- recommendations (array of 2-3 specific mitigation actions - REQUIRED, must not be empty)
- likelihood (1-5), severity (1-5)
- priority (Immediate/Short-term/Long-term)

IMPORTANT: Each hazard MUST include at least 2 specific, actionable recommendations.

Return ONLY a valid JSON array with at least one hazard from EACH category.`;

  try {
    const hazards = await callOpenRouter(SYSTEM_HAZID, userPrompt, 3000);
    
    // Validate and process hazards
    if (!Array.isArray(hazards) || hazards.length === 0) {
      throw new Error('Invalid hazards format');
    }

    const validCategories = ['Process', 'Structural', 'Human', 'Environment', 'External'];
    const validPriorities = ['Immediate', 'Short-term', 'Long-term'];

    const validatedHazards = hazards.map((hazard, i) => {
      // Calculate risk score and level
      const { score, level } = calculateRiskScore(hazard.likelihood || 3, hazard.severity || 3);
      
      // Generate hazard reference
      const hazardRef = `HZD-${(i + 1).toString().padStart(2, '0')}`;
      
      // Ensure recommendations array is not empty
      let recommendations = Array.isArray(hazard.recommendations) ? hazard.recommendations : [];
      if (recommendations.length === 0) {
        // Add default recommendations if none provided
        recommendations = [
          'Conduct risk assessment and implement controls',
          'Provide training and awareness to affected personnel',
          'Review and update safety procedures'
        ];
        console.log(`⚠️ Added default recommendations for ${hazardRef}`);
      }
      
      return {
        hazardRef,
        category: validCategories.includes(hazard.category) ? hazard.category : 'Process',
        description: hazard.description || 'Hazard description',
        cause: hazard.cause || 'Unknown cause',
        consequence: hazard.consequence || 'Potential consequences',
        affectedParties: Array.isArray(hazard.affectedParties) ? hazard.affectedParties : ['Workers'],
        safeguards: Array.isArray(hazard.safeguards) ? hazard.safeguards : [],
        recommendations: recommendations,
        likelihood: hazard.likelihood || 3,
        severity: hazard.severity || 3,
        riskScore: score,
        riskLevel: level,
        priority: validPriorities.includes(hazard.priority) ? hazard.priority : 'Short-term',
        accepted: false
      };
    });

    return validatedHazards;
  } catch (error) {
    console.error('Error generating hazards:', error);
    throw error;
  }
}

/**
 * Chat with AI assistant about HAZOP/HAZID studies
 * @param {Object} input - Chat input
 * @returns {Promise<string>} AI response
 */
async function chatWithAI(input) {
  const { message, studyContext, conversationHistory } = input;
  
  const systemPrompt = `You are an expert safety consultant specializing in HAZOP (Hazard and Operability Study) and HAZID (Hazard Identification) methodologies. You help teams conduct thorough process safety analyses following IEC 61882 and ISO 45001 standards.

Your role is to:
- Answer questions about HAZOP/HAZID methodology
- Provide guidance on identifying hazards and deviations
- Suggest appropriate safeguards and recommendations
- Explain risk assessment principles
- Help interpret findings and prioritize actions

Be concise, practical, and safety-focused in your responses.`;

  // Build conversation context
  let contextPrompt = `Study Context:
- Study Type: ${studyContext.studyType.toUpperCase()}
- Process Type: ${studyContext.processType}
- Facility: ${studyContext.facilityName}
- Process: ${studyContext.processDescription}

`;

  // Add conversation history
  if (conversationHistory && conversationHistory.length > 0) {
    contextPrompt += "Previous conversation:\n";
    conversationHistory.slice(-5).forEach(msg => {
      contextPrompt += `${msg.role === 'user' ? 'User' : 'Assistant'}: ${msg.content}\n`;
    });
    contextPrompt += "\n";
  }

  contextPrompt += `Current question: ${message}`;

  try {
    const response = await callOpenRouterChat(systemPrompt, contextPrompt, 500);
    return response;
  } catch (error) {
    console.error('Error in chat:', error);
    throw error;
  }
}

module.exports = {
  generateNodes,
  analyzeNode,
  generateHazards,
  chatWithAI,
  calculateRiskScore
};
