const EnhancedTKGService = require('./enhanced-tkg-service');
const Template = require('../models/template');
const CustomTemplate = require('../models/custom_template');
const Feature = require('../models/feature');
const CustomFeature = require('../models/custom_feature');
const TechStackRecommendation = require('../models/tech_stack_recommendation');
const database = require('../config/database');

/**
 * Template Knowledge Graph Migration Service
 * Migrates data from PostgreSQL to Neo4j for the TKG
 */
class TKGMigrationService {
  constructor() {
    this.neo4j = new EnhancedTKGService();
  }

  /**
   * Migrate all templates to TKG
   */
  async migrateAllTemplates() {
    console.log('🚀 Starting TKG migration...');
    
    try {
      // Test Neo4j connection
      const isConnected = await this.neo4j.testConnection();
      if (!isConnected) {
        throw new Error('Neo4j connection failed');
      }

      // Clear existing Neo4j data
      await this.neo4j.clearTKG();
      
      // Migrate default templates
      await this.migrateDefaultTemplates();
      
      // Migrate custom templates
      await this.migrateCustomTemplates();
      
      // Migrate tech stack recommendations
      await this.migrateTechStackRecommendations();
      
      console.log('✅ TKG migration completed successfully');
    } catch (error) {
      console.error('❌ TKG migration failed:', error.message);
      throw error;
    }
  }

  /**
   * Migrate default templates
   */
  async migrateDefaultTemplates() {
    console.log('📋 Migrating default templates...');
    
    try {
      const templates = await Template.getAllByCategory();
      let templateCount = 0;
      
      for (const [category, templateList] of Object.entries(templates)) {
        console.log(`📂 Processing category: ${category} (${templateList.length} templates)`);
        for (const template of templateList) {
          console.log(`🔄 Processing template: ${template.title} (${template.id})`);
          
          // Sanitize template data to remove any complex objects
          const sanitizedTemplate = this.sanitizeTemplateData(template);
          
          // Create template node
          await this.neo4j.createTemplateNode(sanitizedTemplate);
          
          // Migrate template features
          await this.migrateTemplateFeatures(template.id, 'default');
          
          templateCount++;
        }
      }
      
      console.log(`✅ Migrated ${templateCount} default templates`);
    } catch (error) {
      console.error('❌ Failed to migrate default templates:', error.message);
      throw error;
    }
  }

  /**
   * Migrate custom templates
   */
  async migrateCustomTemplates() {
    console.log('📋 Migrating custom templates...');
    
    try {
      const customTemplates = await CustomTemplate.getAll(1000, 0);
      let templateCount = 0;
      
      for (const template of customTemplates) {
        // Sanitize template data to remove any complex objects
        const sanitizedTemplate = this.sanitizeTemplateData(template);
        sanitizedTemplate.is_active = template.approved; // Custom templates are active when approved
        
        // Create template node
        await this.neo4j.createTemplateNode(sanitizedTemplate);
        
        // Migrate custom template features
        await this.migrateTemplateFeatures(template.id, 'custom');
        
        templateCount++;
      }
      
      console.log(`✅ Migrated ${templateCount} custom templates`);
    } catch (error) {
      console.error('❌ Failed to migrate custom templates:', error.message);
      throw error;
    }
  }

  /**
   * Migrate template features
   */
  async migrateTemplateFeatures(templateId, templateType) {
    try {
      const features = await Feature.getByTemplateId(templateId);
      let featureCount = 0;
      
      console.log(`🔍 Processing ${features.length} features for template ${templateId}`);
      
      for (const feature of features) {
        try {
          // Sanitize feature data to remove any complex objects
          const sanitizedFeature = this.sanitizeFeatureData(feature);
          
          // Create feature node
          await this.neo4j.createFeatureNode(sanitizedFeature);
          
          // Create template-feature relationship
          await this.neo4j.createTemplateFeatureRelationship(templateId, feature.id);
          
          // Extract and create technology relationships
          await this.extractFeatureTechnologies(feature);
          
          featureCount++;
          console.log(`  ✅ Migrated feature: ${feature.name}`);
        } catch (featureError) {
          console.error(`  ❌ Failed to migrate feature ${feature.name}:`, featureError.message);
          // Continue with other features even if one fails
        }
      }
      
      console.log(`✅ Migrated ${featureCount}/${features.length} features for template ${templateId}`);
    } catch (error) {
      console.error(`❌ Failed to migrate features for template ${templateId}:`, error.message);
      // Don't throw error, continue with other templates
      console.log(`⚠️ Continuing with other templates...`);
    }
  }

  /**
   * Extract technologies from feature and create relationships
   */
  async extractFeatureTechnologies(feature) {
    try {
      // Extract technologies from feature description and business rules
      const technologies = await this.analyzeFeatureForTechnologies(feature);
      
      for (const tech of technologies) {
        // Sanitize technology data to remove any complex objects
        const sanitizedTech = this.sanitizeTechnologyData(tech);
        
        // Create technology node
        await this.neo4j.createTechnologyNode(sanitizedTech);
        
        // Create feature-technology relationship
        await this.neo4j.createFeatureTechnologyRelationship(feature.id, tech.name, {
          confidence: tech.confidence,
          necessity: tech.necessity,
          source: tech.source
        });
      }
    } catch (error) {
      console.error(`❌ Failed to extract technologies for feature ${feature.id}:`, error.message);
      // Don't throw error, continue with migration
    }
  }

  /**
   * Analyze feature for technologies using AI
   */
  async analyzeFeatureForTechnologies(feature) {
    try {
      // Use AI to extract technologies from feature
      const prompt = `Extract technology requirements from this feature:
      
      Feature: ${feature.name}
      Description: ${feature.description}
      Business Rules: ${JSON.stringify(feature.business_rules || {})}
      Technical Requirements: ${JSON.stringify(feature.technical_requirements || {})}
      
      Return JSON array of technologies:
      [{
        "name": "React",
        "category": "Frontend",
        "type": "Framework",
        "version": "18.x",
        "popularity": 95,
        "confidence": 0.9,
        "necessity": "high",
        "source": "feature_analysis"
      }]`;

      // Use your existing Claude AI service
      const analysis = await this.analyzeWithClaude(prompt);
      return JSON.parse(analysis);
    } catch (error) {
      console.error(`❌ Failed to analyze feature ${feature.id}:`, error.message);
      // Return empty array if analysis fails
      return [];
    }
  }

  /**
   * Migrate tech stack recommendations
   */
  async migrateTechStackRecommendations() {
    console.log('📋 Migrating tech stack recommendations...');
    
    try {
      const recommendations = await TechStackRecommendation.getAll(1000, 0);
      let recommendationCount = 0;
      
      for (const rec of recommendations) {
        // Sanitize tech stack data to remove any complex objects
        const sanitizedRec = this.sanitizeTechStackData(rec);
        
        // Create tech stack node
        await this.neo4j.createTechStackNode(sanitizedRec);
        
        // Create template-tech stack relationship
        await this.neo4j.createTemplateTechStackRelationship(rec.template_id, rec.id);
        
        // Migrate technology recommendations by category
        await this.migrateTechStackTechnologies(rec);
        
        recommendationCount++;
      }
      
      console.log(`✅ Migrated ${recommendationCount} tech stack recommendations`);
    } catch (error) {
      console.error('❌ Failed to migrate tech stack recommendations:', error.message);
      throw error;
    }
  }

  /**
   * Migrate tech stack technologies by category
   */
  async migrateTechStackTechnologies(recommendation) {
    try {
      const categories = ['frontend', 'backend', 'mobile', 'testing', 'ai_ml', 'devops', 'cloud', 'tools'];
      
      for (const category of categories) {
        const techData = recommendation[category];
        if (techData && Array.isArray(techData)) {
          for (const tech of techData) {
            // Sanitize technology data to remove any complex objects
            const sanitizedTech = this.sanitizeTechnologyData({
              name: tech.name,
              category: tech.category || category,
              type: tech.type,
              version: tech.version,
              popularity: tech.popularity,
              description: tech.description,
              website: tech.website,
              documentation: tech.documentation
            });
            
            // Create technology node
            await this.neo4j.createTechnologyNode(sanitizedTech);
            
            // Create tech stack-technology relationship
            await this.neo4j.createTechStackTechnologyRelationship(
              recommendation.id,
              tech.name,
              category,
              {
                confidence: tech.confidence,
                necessity: tech.necessity,
                reasoning: tech.reasoning
              }
            );
          }
        }
      }
    } catch (error) {
      console.error(`❌ Failed to migrate tech stack technologies for ${recommendation.id}:`, error.message);
      // Don't throw error, continue with migration
    }
  }

  /**
   * Analyze with Claude AI
   */
  async analyzeWithClaude(prompt) {
    try {
      // Use your existing Claude AI integration
      const response = await fetch('http://localhost:8009/api/analyze-feature', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ 
          featureName: 'Feature Analysis',
          description: prompt,
          requirements: [],
          projectType: 'web application'
        })
      });
      
      const result = await response.json();
      if (result.success && result.analysis) {
        // Extract technologies from the analysis
        const technologies = [];
        
        // Parse the analysis to extract technologies
        if (result.analysis.technical_requirements) {
          for (const req of result.analysis.technical_requirements) {
            technologies.push({
              name: req,
              category: 'General',
              type: 'Technology',
              version: 'latest',
              popularity: 50,
              confidence: 0.7,
              necessity: 'medium',
              source: 'ai_analysis'
            });
          }
        }
        
        return JSON.stringify(technologies);
      } else {
        // Fallback to basic technology extraction
        return JSON.stringify([{
          name: 'Node.js',
          category: 'Backend',
          type: 'Runtime',
          version: '18.x',
          popularity: 90,
          confidence: 0.8,
          necessity: 'high',
          source: 'fallback_analysis'
        }]);
      }
    } catch (error) {
      console.error('❌ Failed to analyze with Claude:', error.message);
      // Return fallback technologies
      return JSON.stringify([{
        name: 'Node.js',
        category: 'Backend',
        type: 'Runtime',
        version: '18.x',
        popularity: 90,
        confidence: 0.8,
        necessity: 'high',
        source: 'fallback_analysis'
      }]);
    }
  }

  /**
   * Get migration statistics
   */
  async getMigrationStats() {
    try {
      const stats = await this.neo4j.getMigrationStats();
      return {
        templates: stats.templates ? stats.templates.toNumber() : 0,
        features: stats.features ? stats.features.toNumber() : 0,
        technologies: stats.technologies ? stats.technologies.toNumber() : 0,
        tech_stacks: stats.tech_stacks ? stats.tech_stacks.toNumber() : 0
      };
    } catch (error) {
      console.error('❌ Failed to get migration stats:', error.message);
      // Return default stats if query fails
      return {
        templates: 0,
        features: 0,
        technologies: 0,
        tech_stacks: 0
      };
    }
  }

  /**
   * Migrate single template to TKG
   */
  async migrateTemplateToTKG(templateId) {
    try {
      console.log(`🔄 Migrating template ${templateId} to TKG...`);
      
      // Get template data
      const template = await Template.getByIdWithFeatures(templateId);
      if (!template) {
        throw new Error(`Template ${templateId} not found`);
      }
      
      // Create template node
      await this.neo4j.createTemplateNode({
        id: template.id,
        type: template.type,
        title: template.title,
        description: template.description,
        category: template.category,
        complexity: 'medium',
        is_active: template.is_active,
        created_at: template.created_at,
        updated_at: template.updated_at
      });
      
      // Migrate features
      await this.migrateTemplateFeatures(templateId, 'default');
      
      console.log(`✅ Template ${templateId} migrated to TKG`);
    } catch (error) {
      console.error(`❌ Failed to migrate template ${templateId}:`, error.message);
      throw error;
    }
  }

  /**
   * Sanitize template data to remove complex objects
   */
  sanitizeTemplateData(template) {
    const sanitized = {
      id: template.id,
      type: template.type,
      title: template.title,
      description: template.description,
      category: template.category,
      complexity: template.complexity || 'medium',
      is_active: template.is_active,
      created_at: template.created_at,
      updated_at: template.updated_at
    };
    
    // Debug: Log the sanitized data to see what's being passed
    console.log('🔍 Sanitized template data:', JSON.stringify(sanitized, null, 2));
    
    return sanitized;
  }

  /**
   * Sanitize feature data to remove complex objects
   */
  sanitizeFeatureData(feature) {
    return {
      id: feature.id,
      name: feature.name,
      description: feature.description,
      feature_type: feature.feature_type,
      complexity: feature.complexity,
      display_order: feature.display_order,
      usage_count: feature.usage_count,
      user_rating: feature.user_rating,
      is_default: feature.is_default,
      created_by_user: feature.created_by_user
    };
  }

  /**
   * Sanitize tech stack data to remove complex objects
   */
  sanitizeTechStackData(techStack) {
    return {
      id: techStack.id,
      template_id: techStack.template_id,
      template_type: techStack.template_type,
      status: techStack.status,
      ai_model: techStack.ai_model,
      analysis_version: techStack.analysis_version,
      processing_time_ms: techStack.processing_time_ms,
      created_at: techStack.created_at,
      last_analyzed_at: techStack.last_analyzed_at
    };
  }

  /**
   * Sanitize technology data to remove complex objects
   */
  sanitizeTechnologyData(tech) {
    return {
      name: tech.name,
      category: tech.category,
      type: tech.type,
      version: tech.version,
      popularity: tech.popularity,
      description: tech.description,
      website: tech.website,
      documentation: tech.documentation
    };
  }

  /**
   * Close connections
   */
  async close() {
    await this.neo4j.close();
  }
}

module.exports = TKGMigrationService;
