const neo4j = require('neo4j-driver');
const { v4: uuidv4 } = require('uuid');

/**
 * Enhanced Neo4j Combinatorial Knowledge Graph (CKG) Service
 * Provides robust feature permutation/combination analysis with intelligent tech-stack recommendations
 */
class EnhancedCKGService {
  constructor() {
    this.driver = neo4j.driver(
      process.env.CKG_NEO4J_URI || process.env.NEO4J_URI || 'bolt://localhost:7687',
      neo4j.auth.basic(
        process.env.CKG_NEO4J_USERNAME || process.env.NEO4J_USERNAME || 'neo4j',
        process.env.CKG_NEO4J_PASSWORD || process.env.NEO4J_PASSWORD || 'password'
      )
    );
  }

  /**
   * Clear all existing CKG data
   */
  async clearCKG() {
    const session = this.driver.session();
    try {
      console.log('🧹 Clearing existing CKG data...');
      await session.run(`
        MATCH (n)
        WHERE n:Feature OR n:Permutation OR n:Combination OR n:TechStack OR n:Technology OR n:Template
        DETACH DELETE n
      `);
      console.log('✅ Cleared existing CKG data');
    } catch (error) {
      console.error('❌ Failed to clear CKG data:', error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Create enhanced feature node with dependencies and conflicts
   */
  async createFeatureNode(featureData) {
    const session = this.driver.session();
    try {
      const params = {
        id: String(featureData.id),
        name: String(featureData.name),
        description: String(featureData.description || ''),
        feature_type: String(featureData.feature_type),
        complexity: String(featureData.complexity),
        template_id: String(featureData.template_id),
        display_order: Number(featureData.display_order) || 0,
        usage_count: Number(featureData.usage_count) || 0,
        user_rating: Number(featureData.user_rating) || 0,
        is_default: Boolean(featureData.is_default),
        created_by_user: Boolean(featureData.created_by_user),
        dependencies: JSON.stringify(featureData.dependencies || []),
        conflicts: JSON.stringify(featureData.conflicts || [])
      };
      
      const result = await session.run(`
        MERGE (f:Feature {id: $id})
        SET f.name = $name,
            f.description = $description,
            f.feature_type = $feature_type,
            f.complexity = $complexity,
            f.template_id = $template_id,
            f.display_order = $display_order,
            f.usage_count = $usage_count,
            f.user_rating = $user_rating,
            f.is_default = $is_default,
            f.created_by_user = $created_by_user,
            f.dependencies = $dependencies,
            f.conflicts = $conflicts
        RETURN f
      `, params);
      return result.records[0].get('f');
    } catch (error) {
      console.error('❌ Failed to create feature node:', error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Create enhanced permutation node with performance metrics
   */
  async createPermutationNode(permutationData) {
    const session = this.driver.session();
    try {
      const params = {
        id: String(permutationData.id),
        template_id: String(permutationData.template_id),
        feature_sequence: JSON.stringify(permutationData.feature_sequence),
        sequence_length: Number(permutationData.sequence_length),
        complexity_score: Number(permutationData.complexity_score) || 0,
        usage_frequency: Number(permutationData.usage_frequency) || 0,
        performance_score: Number(permutationData.performance_score) || 0,
        compatibility_score: Number(permutationData.compatibility_score) || 0,
        created_at: permutationData.created_at instanceof Date ? permutationData.created_at.toISOString() : String(permutationData.created_at)
      };
      
      const result = await session.run(`
        MERGE (p:Permutation {id: $id})
        SET p.template_id = $template_id,
            p.feature_sequence = $feature_sequence,
            p.sequence_length = $sequence_length,
            p.complexity_score = $complexity_score,
            p.usage_frequency = $usage_frequency,
            p.performance_score = $performance_score,
            p.compatibility_score = $compatibility_score,
            p.created_at = $created_at
        RETURN p
      `, params);
      return result.records[0].get('p');
    } catch (error) {
      console.error('❌ Failed to create permutation node:', error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Create enhanced combination node with synergy metrics
   */
  async createCombinationNode(combinationData) {
    const session = this.driver.session();
    try {
      const params = {
        id: String(combinationData.id),
        template_id: String(combinationData.template_id),
        feature_set: JSON.stringify(combinationData.feature_set),
        set_size: Number(combinationData.set_size),
        complexity_score: Number(combinationData.complexity_score) || 0,
        usage_frequency: Number(combinationData.usage_frequency) || 0,
        synergy_score: Number(combinationData.synergy_score) || 0,
        compatibility_score: Number(combinationData.compatibility_score) || 0,
        created_at: combinationData.created_at instanceof Date ? combinationData.created_at.toISOString() : String(combinationData.created_at)
      };
      
      const result = await session.run(`
        MERGE (c:Combination {id: $id})
        SET c.template_id = $template_id,
            c.feature_set = $feature_set,
            c.set_size = $set_size,
            c.complexity_score = $complexity_score,
            c.usage_frequency = $usage_frequency,
            c.synergy_score = $synergy_score,
            c.compatibility_score = $compatibility_score,
            c.created_at = $created_at
        RETURN c
      `, params);
      return result.records[0].get('c');
    } catch (error) {
      console.error('❌ Failed to create combination node:', error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Create enhanced tech stack node with comprehensive technology mappings
   */
  async createTechStackNode(techStackData) {
    const session = this.driver.session();
    try {
      const params = {
        id: String(techStackData.id),
        combination_id: String(techStackData.combination_id || ''),
        permutation_id: String(techStackData.permutation_id || ''),
        frontend_tech: JSON.stringify(techStackData.frontend_tech || []),
        backend_tech: JSON.stringify(techStackData.backend_tech || []),
        database_tech: JSON.stringify(techStackData.database_tech || []),
        devops_tech: JSON.stringify(techStackData.devops_tech || []),
        mobile_tech: JSON.stringify(techStackData.mobile_tech || []),
        cloud_tech: JSON.stringify(techStackData.cloud_tech || []),
        testing_tech: JSON.stringify(techStackData.testing_tech || []),
        ai_ml_tech: JSON.stringify(techStackData.ai_ml_tech || []),
        tools_tech: JSON.stringify(techStackData.tools_tech || []),
        confidence_score: Number(techStackData.confidence_score) || 0,
        complexity_level: String(techStackData.complexity_level),
        estimated_effort: String(techStackData.estimated_effort),
        ai_model: String(techStackData.ai_model || 'claude-3-5-sonnet'),
        analysis_version: String(techStackData.analysis_version || '1.0'),
        created_at: techStackData.created_at instanceof Date ? techStackData.created_at.toISOString() : String(techStackData.created_at)
      };
      
      const result = await session.run(`
        MERGE (ts:TechStack {id: $id})
        SET ts.combination_id = $combination_id,
            ts.permutation_id = $permutation_id,
            ts.frontend_tech = $frontend_tech,
            ts.backend_tech = $backend_tech,
            ts.database_tech = $database_tech,
            ts.devops_tech = $devops_tech,
            ts.mobile_tech = $mobile_tech,
            ts.cloud_tech = $cloud_tech,
            ts.testing_tech = $testing_tech,
            ts.ai_ml_tech = $ai_ml_tech,
            ts.tools_tech = $tools_tech,
            ts.confidence_score = $confidence_score,
            ts.complexity_level = $complexity_level,
            ts.estimated_effort = $estimated_effort,
            ts.ai_model = $ai_model,
            ts.analysis_version = $analysis_version,
            ts.created_at = $created_at
        RETURN ts
      `, params);
      return result.records[0].get('ts');
    } catch (error) {
      console.error('❌ Failed to create tech stack node:', error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Create technology node with comprehensive metadata
   */
  async createTechnologyNode(techData) {
    const session = this.driver.session();
    try {
      const params = {
        name: String(techData.name),
        category: String(techData.category),
        type: String(techData.type),
        version: String(techData.version || 'latest'),
        popularity: Number(techData.popularity) || 0,
        description: String(techData.description || ''),
        website: String(techData.website || ''),
        documentation: String(techData.documentation || ''),
        compatibility: JSON.stringify(techData.compatibility || []),
        performance_score: Number(techData.performance_score) || 0,
        learning_curve: String(techData.learning_curve || 'medium'),
        community_support: String(techData.community_support || 'medium'),
        cost: String(techData.cost || 'free'),
        scalability: String(techData.scalability || 'medium'),
        security_score: Number(techData.security_score) || 0
      };
      
      const result = await session.run(`
        MERGE (tech:Technology {name: $name})
        SET tech.category = $category,
            tech.type = $type,
            tech.version = $version,
            tech.popularity = $popularity,
            tech.description = $description,
            tech.website = $website,
            tech.documentation = $documentation,
            tech.compatibility = $compatibility,
            tech.performance_score = $performance_score,
            tech.learning_curve = $learning_curve,
            tech.community_support = $community_support,
            tech.cost = $cost,
            tech.scalability = $scalability,
            tech.security_score = $security_score
        RETURN tech
      `, params);
      return result.records[0].get('tech');
    } catch (error) {
      console.error('❌ Failed to create technology node:', error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Create feature dependency relationships
   */
  async createFeatureDependencyRelationships(featureId, dependencies) {
    const session = this.driver.session();
    try {
      for (const dependency of dependencies) {
        await session.run(`
          MATCH (f1:Feature {id: $featureId})
          MATCH (f2:Feature {id: $dependencyId})
          MERGE (f1)-[r:DEPENDS_ON {strength: $strength}]->(f2)
        `, {
          featureId,
          dependencyId: dependency.id,
          strength: dependency.strength || 0.5
        });
      }
    } catch (error) {
      console.error('❌ Failed to create feature dependency relationships:', error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Create feature conflict relationships
   */
  async createFeatureConflictRelationships(featureId, conflicts) {
    const session = this.driver.session();
    try {
      for (const conflict of conflicts) {
        await session.run(`
          MATCH (f1:Feature {id: $featureId})
          MATCH (f2:Feature {id: $conflictId})
          MERGE (f1)-[r:CONFLICTS_WITH {severity: $severity}]->(f2)
        `, {
          featureId,
          conflictId: conflict.id,
          severity: conflict.severity || 'medium'
        });
      }
    } catch (error) {
      console.error('❌ Failed to create feature conflict relationships:', error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Create technology synergy relationships
   */
  async createTechnologySynergyRelationships(tech1Name, tech2Name, synergyScore) {
    const session = this.driver.session();
    try {
      await session.run(`
        MATCH (t1:Technology {name: $tech1Name})
        MATCH (t2:Technology {name: $tech2Name})
        MERGE (t1)-[r:SYNERGY {score: $synergyScore}]->(t2)
        MERGE (t2)-[r2:SYNERGY {score: $synergyScore}]->(t1)
      `, {
        tech1Name,
        tech2Name,
        synergyScore
      });
    } catch (error) {
      console.error('❌ Failed to create technology synergy relationships:', error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Create technology conflict relationships
   */
  async createTechnologyConflictRelationships(tech1Name, tech2Name, severity) {
    const session = this.driver.session();
    try {
      await session.run(`
        MATCH (t1:Technology {name: $tech1Name})
        MATCH (t2:Technology {name: $tech2Name})
        MERGE (t1)-[r:CONFLICTS {severity: $severity}]->(t2)
        MERGE (t2)-[r2:CONFLICTS {severity: $severity}]->(t1)
      `, {
        tech1Name,
        tech2Name,
        severity
      });
    } catch (error) {
      console.error('❌ Failed to create technology conflict relationships:', error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Get intelligent tech stack recommendations for a permutation
   */
  async getIntelligentPermutationRecommendations(permutationId, options = {}) {
    const session = this.driver.session();
    try {
      const limit = options.limit || 10;
      const minConfidence = options.minConfidence || 0.7;
      
      const result = await session.run(`
        MATCH (p:Permutation {id: $permutationId})
        MATCH (p)-[:HAS_ORDERED_FEATURE]->(f)
        MATCH (p)-[:RECOMMENDS_TECH_STACK]->(ts)
        WHERE ts.confidence_score >= $minConfidence
        WITH p, collect(f) as features, ts
        MATCH (ts)-[r:RECOMMENDS_TECHNOLOGY]->(tech)
        WITH p, features, ts, collect({tech: tech, category: r.category, confidence: r.confidence}) as technologies
        RETURN p, features, ts, technologies
        ORDER BY ts.confidence_score DESC, p.performance_score DESC
        LIMIT $limit
      `, { permutationId, minConfidence, limit });
      
      return result.records.map(record => ({
        permutation: record.get('p').properties,
        features: record.get('features').map(f => f.properties),
        techStack: record.get('ts').properties,
        technologies: record.get('technologies')
      }));
    } catch (error) {
      console.error('❌ Failed to get intelligent permutation recommendations:', error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Get intelligent tech stack recommendations for a combination
   */
  async getIntelligentCombinationRecommendations(combinationId, options = {}) {
    const session = this.driver.session();
    try {
      const limit = options.limit || 10;
      const minConfidence = options.minConfidence || 0.7;
      
      const result = await session.run(`
        MATCH (c:Combination {id: $combinationId})
        MATCH (c)-[:CONTAINS_FEATURE]->(f)
        MATCH (c)-[:RECOMMENDS_TECH_STACK]->(ts)
        WHERE ts.confidence_score >= $minConfidence
        WITH c, collect(f) as features, ts
        MATCH (ts)-[r:RECOMMENDS_TECHNOLOGY]->(tech)
        WITH c, features, ts, collect({tech: tech, category: r.category, confidence: r.confidence}) as technologies
        RETURN c, features, ts, technologies
        ORDER BY ts.confidence_score DESC, c.synergy_score DESC
        LIMIT $limit
      `, { combinationId, minConfidence, limit });
      
      return result.records.map(record => ({
        combination: record.get('c').properties,
        features: record.get('features').map(f => f.properties),
        techStack: record.get('ts').properties,
        technologies: record.get('technologies')
      }));
    } catch (error) {
      console.error('❌ Failed to get intelligent combination recommendations:', error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Analyze feature compatibility and generate recommendations
   */
  async analyzeFeatureCompatibility(featureIds) {
    const session = this.driver.session();
    try {
      const result = await session.run(`
        MATCH (f1:Feature)
        WHERE f1.id IN $featureIds
        MATCH (f2:Feature)
        WHERE f2.id IN $featureIds AND f1.id <> f2.id
        OPTIONAL MATCH (f1)-[r1:DEPENDS_ON]->(f2)]
        OPTIONAL MATCH (f1)-[r2:CONFLICTS_WITH]->(f2)
        WITH f1, f2, r1, r2
        RETURN f1, f2, 
               CASE WHEN r1 IS NOT NULL THEN 'dependency' 
                    WHEN r2 IS NOT NULL THEN 'conflict'
                    ELSE 'neutral' END as relationship_type,
               COALESCE(r1.strength, 0) as dependency_strength,
               COALESCE(r2.severity, 'none') as conflict_severity
      `, { featureIds });
      
      const compatibility = {
        compatible: [],
        dependencies: [],
        conflicts: [],
        neutral: []
      };
      
      for (const record of result.records) {
        const f1 = record.get('f1').properties;
        const f2 = record.get('f2').properties;
        const relationshipType = record.get('relationship_type');
        const dependencyStrength = record.get('dependency_strength');
        const conflictSeverity = record.get('conflict_severity');
        
        const analysis = {
          feature1: f1,
          feature2: f2,
          relationshipType,
          dependencyStrength,
          conflictSeverity
        };
        
        if (relationshipType === 'dependency') {
          compatibility.dependencies.push(analysis);
        } else if (relationshipType === 'conflict') {
          compatibility.conflicts.push(analysis);
        } else {
          compatibility.neutral.push(analysis);
        }
      }
      
      // Determine overall compatibility
      if (compatibility.conflicts.length === 0) {
        compatibility.compatible = featureIds;
      }
      
      return compatibility;
    } catch (error) {
      console.error('❌ Failed to analyze feature compatibility:', error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Get technology synergies and conflicts
   */
  async getTechnologyRelationships(techNames) {
    const session = this.driver.session();
    try {
      const result = await session.run(`
        MATCH (t1:Technology)
        WHERE t1.name IN $techNames
        MATCH (t2:Technology)
        WHERE t2.name IN $techNames AND t1.name <> t2.name
        OPTIONAL MATCH (t1)-[r1:SYNERGY]->(t2)
        OPTIONAL MATCH (t1)-[r2:CONFLICTS]->(t2)
        WITH t1, t2, r1, r2
        RETURN t1, t2,
               CASE WHEN r1 IS NOT NULL THEN 'synergy'
                    WHEN r2 IS NOT NULL THEN 'conflict'
                    ELSE 'neutral' END as relationship_type,
               COALESCE(r1.score, 0) as synergy_score,
               COALESCE(r2.severity, 'none') as conflict_severity
      `, { techNames });
      
      const relationships = {
        synergies: [],
        conflicts: [],
        neutral: []
      };
      
      for (const record of result.records) {
        const t1 = record.get('t1').properties;
        const t2 = record.get('t2').properties;
        const relationshipType = record.get('relationship_type');
        const synergyScore = record.get('synergy_score');
        const conflictSeverity = record.get('conflict_severity');
        
        const analysis = {
          tech1: t1,
          tech2: t2,
          relationshipType,
          synergyScore,
          conflictSeverity
        };
        
        if (relationshipType === 'synergy') {
          relationships.synergies.push(analysis);
        } else if (relationshipType === 'conflict') {
          relationships.conflicts.push(analysis);
        } else {
          relationships.neutral.push(analysis);
        }
      }
      
      return relationships;
    } catch (error) {
      console.error('❌ Failed to get technology relationships:', error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Get comprehensive CKG statistics
   */
  async getCKGStats() {
    const session = this.driver.session();
    try {
      const result = await session.run(`
        MATCH (f:Feature)
        MATCH (p:Permutation)
        MATCH (c:Combination)
        MATCH (ts:TechStack)
        MATCH (tech:Technology)
        RETURN 
          count(DISTINCT f) as features,
          count(DISTINCT p) as permutations,
          count(DISTINCT c) as combinations,
          count(DISTINCT ts) as tech_stacks,
          count(DISTINCT tech) as technologies,
          avg(p.performance_score) as avg_performance_score,
          avg(c.synergy_score) as avg_synergy_score,
          avg(ts.confidence_score) as avg_confidence_score
      `);
      
      return result.records[0];
    } catch (error) {
      console.error('❌ Failed to get CKG stats:', error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Test CKG connection
   */
  async testConnection() {
    const session = this.driver.session();
    try {
      const result = await session.run('RETURN 1 as test');
      console.log('✅ Enhanced CKG Neo4j connection successful');
      return true;
    } catch (error) {
      console.error('❌ Enhanced CKG Neo4j connection failed:', error.message);
      return false;
    } finally {
      await session.close();
    }
  }

  /**
   * Create or update template node (prevents duplicates)
   */
  async createTemplateNode(templateData) {
    const session = this.driver.session();
    try {
      const params = {
        id: String(templateData.id),
        type: String(templateData.type),
        title: String(templateData.title),
        description: String(templateData.description || ''),
        category: String(templateData.category || ''),
        created_at: new Date().toISOString(),
        updated_at: new Date().toISOString()
      };

      const result = await session.run(`
        MERGE (t:Template {id: $id})
        ON CREATE SET 
          t.type = $type,
          t.title = $title,
          t.description = $description,
          t.category = $category,
          t.created_at = $created_at,
          t.updated_at = $updated_at
        ON MATCH SET 
          t.type = $type,
          t.title = $title,
          t.description = $description,
          t.category = $category,
          t.updated_at = $updated_at
        RETURN t, 
               CASE WHEN t.created_at = $created_at THEN 'created' ELSE 'updated' END as action
      `, params);

      const action = result.records[0].get('action');
      console.log(`✅ ${action === 'created' ? 'Created' : 'Updated'} template node: ${templateData.title}`);
    } catch (error) {
      console.error(`❌ Failed to create/update template node:`, error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Create template-feature relationship
   */
  async createTemplateFeatureRelationship(templateId, featureId) {
    const session = this.driver.session();
    try {
      await session.run(`
        MATCH (t:Template {id: $templateId})
        MATCH (f:Feature {id: $featureId})
        CREATE (t)-[:HAS_FEATURE]->(f)
      `, { templateId: String(templateId), featureId: String(featureId) });

      console.log(`✅ Created template-feature relationship: ${templateId} -> ${featureId}`);
    } catch (error) {
      console.error(`❌ Failed to create template-feature relationship:`, error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Create permutation-feature relationships
   */
  async createPermutationFeatureRelationships(permutationId, features) {
    const session = this.driver.session();
    try {
      for (let i = 0; i < features.length; i++) {
        const feature = features[i];
        await session.run(`
          MATCH (p:Permutation {id: $permutationId})
          MATCH (f:Feature {id: $featureId})
          CREATE (p)-[:HAS_ORDERED_FEATURE {order: $order}]->(f)
        `, { 
          permutationId: String(permutationId), 
          featureId: String(feature.id), 
          order: i 
        });
      }
      console.log(`✅ Created permutation-feature relationships for ${features.length} features`);
    } catch (error) {
      console.error(`❌ Failed to create permutation-feature relationships:`, error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Create combination-feature relationships
   */
  async createCombinationFeatureRelationships(combinationId, features) {
    const session = this.driver.session();
    try {
      for (const feature of features) {
        await session.run(`
          MATCH (c:Combination {id: $combinationId})
          MATCH (f:Feature {id: $featureId})
          CREATE (c)-[:CONTAINS_FEATURE]->(f)
        `, { 
          combinationId: String(combinationId), 
          featureId: String(feature.id) 
        });
      }
      console.log(`✅ Created combination-feature relationships for ${features.length} features`);
    } catch (error) {
      console.error(`❌ Failed to create combination-feature relationships:`, error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Create tech stack relationships
   */
  async createTechStackRelationships(sourceId, sourceType, techStackId) {
    const session = this.driver.session();
    try {
      await session.run(`
        MATCH (s:${sourceType} {id: $sourceId})
        MATCH (ts:TechStack {id: $techStackId})
        CREATE (s)-[:RECOMMENDS_TECH_STACK]->(ts)
      `, { 
        sourceId: String(sourceId), 
        techStackId: String(techStackId) 
      });
      console.log(`✅ Created tech stack relationship: ${sourceType} ${sourceId} -> TechStack ${techStackId}`);
    } catch (error) {
      console.error(`❌ Failed to create tech stack relationship:`, error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Create tech stack-technology relationships
   */
  async createTechStackTechnologyRelationship(techStackId, technologyName, category, confidence) {
    const session = this.driver.session();
    try {
      await session.run(`
        MATCH (ts:TechStack {id: $techStackId})
        MERGE (t:Technology {name: $technologyName})
        CREATE (ts)-[:INCLUDES_TECHNOLOGY {category: $category, confidence: $confidence}]->(t)
      `, { 
        techStackId: String(techStackId), 
        technologyName: String(technologyName),
        category: String(category),
        confidence: parseFloat(confidence) || 0.8
      });
      console.log(`✅ Created tech stack-technology relationship: ${techStackId} -> ${technologyName}`);
    } catch (error) {
      console.error(`❌ Failed to create tech stack-technology relationship:`, error.message);
      throw error;
    } finally {
      await session.close();
    }
  }

  /**
   * Get intelligent permutation recommendations
   */
  async getIntelligentPermutationRecommendations(templateId, options = {}) {
    const session = this.driver.session();
    try {
      const limit = Math.floor(options.limit || 10);
      const minConfidence = parseFloat(options.minConfidence || 0.7);
      
      const result = await session.run(`
        MATCH (p:Permutation:TM {template_id: $templateId})
        MATCH (p)-[:RECOMMENDS_TECH_STACK_TM]->(ts:TechStack:TM)
        WHERE ts.confidence_score >= $minConfidence
        WITH p, ts
        MATCH (ts)-[r:INCLUDES_TECHNOLOGY_TM]->(tech:Technology:TM)
        WITH p, ts, collect({tech: tech, category: r.category, confidence: r.confidence}) as technologies
        RETURN p, ts, technologies
        ORDER BY ts.confidence_score DESC, p.performance_score DESC
        LIMIT $limit
      `, { 
        templateId, 
        minConfidence, 
        limit: neo4j.int(limit) 
      });
      
      return result.records.map(record => ({
        permutation: record.get('p').properties,
        techStack: record.get('ts').properties,
        technologies: record.get('technologies')
      }));
    } catch (error) {
      console.error('❌ Failed to get intelligent permutation recommendations:', error.message);
      return [];
    } finally {
      await session.close();
    }
  }

  /**
   * Get intelligent combination recommendations
   */
  async getIntelligentCombinationRecommendations(templateId, options = {}) {
    const session = this.driver.session();
    try {
      const limit = Math.floor(options.limit || 10);
      const minConfidence = parseFloat(options.minConfidence || 0.7);
      
      const result = await session.run(`
        MATCH (c:Combination:TM {template_id: $templateId})
        MATCH (c)-[:RECOMMENDS_TECH_STACK_TM]->(ts:TechStack:TM)
        WHERE ts.confidence_score >= $minConfidence
        WITH c, ts
        MATCH (ts)-[r:INCLUDES_TECHNOLOGY_TM]->(tech:Technology:TM)
        WITH c, ts, collect({tech: tech, category: r.category, confidence: r.confidence}) as technologies
        RETURN c, ts, technologies
        ORDER BY ts.confidence_score DESC, c.synergy_score DESC
        LIMIT $limit
      `, { 
        templateId, 
        minConfidence, 
        limit: neo4j.int(limit) 
      });
      
      return result.records.map(record => ({
        combination: record.get('c').properties,
        techStack: record.get('ts').properties,
        technologies: record.get('technologies')
      }));
    } catch (error) {
      console.error('❌ Failed to get intelligent combination recommendations:', error.message);
      return [];
    } finally {
      await session.close();
    }
  }

  /**
   * Clean up duplicate templates and ensure data integrity
   */
  async cleanupDuplicates() {
    const session = this.driver.session();
    try {
      console.log('🧹 Starting duplicate cleanup...');
      
      // Step 1: Remove templates without categories (keep the ones with categories)
      const removeResult = await session.run(`
        MATCH (t:Template)
        WHERE t.category IS NULL OR t.category = ''
        DETACH DELETE t
        RETURN count(t) as removed_count
      `);
      
      const removedCount = removeResult.records[0].get('removed_count');
      console.log(`✅ Removed ${removedCount} duplicate templates without categories`);
      
      // Step 2: Verify no duplicates remain
      const verifyResult = await session.run(`
        MATCH (t:Template)
        WITH t.id as id, count(t) as count
        WHERE count > 1
        RETURN count(*) as duplicate_count
      `);
      
      const duplicateCount = verifyResult.records[0].get('duplicate_count');
      
      if (duplicateCount === 0) {
        console.log('✅ No duplicate templates found');
      } else {
        console.log(`⚠️ Found ${duplicateCount} template IDs with duplicates`);
      }
      
      // Step 3: Get final template count
      const finalResult = await session.run(`
        MATCH (t:Template)
        RETURN count(t) as total_templates
      `);
      
      const totalTemplates = finalResult.records[0].get('total_templates');
      console.log(`📊 Final template count: ${totalTemplates}`);
      
      return {
        success: true,
        removedCount: removedCount,
        duplicateCount: duplicateCount,
        totalTemplates: totalTemplates
      };
      
    } catch (error) {
      console.error('❌ Failed to cleanup duplicates:', error.message);
      return { success: false, error: error.message };
    } finally {
      await session.close();
    }
  }

  /**
   * Check for and prevent duplicate template creation
   */
  async checkTemplateExists(templateId) {
    const session = this.driver.session();
    try {
      const result = await session.run(`
        MATCH (t:Template {id: $templateId})
        RETURN t.id as id, t.title as title, t.category as category
      `, { templateId });
      
      if (result.records.length > 0) {
        const record = result.records[0];
        return {
          exists: true,
          id: record.get('id'),
          title: record.get('title'),
          category: record.get('category')
        };
      }
      
      return { exists: false };
    } catch (error) {
      console.error('❌ Failed to check template existence:', error.message);
      return { exists: false, error: error.message };
    } finally {
      await session.close();
    }
  }

  /**
   * Close CKG driver
   */
  async close() {
    await this.driver.close();
  }
}

module.exports = EnhancedCKGService;
