const IntelligentTechStackAnalyzer = require('./intelligent-tech-stack-analyzer');
const TechStackRecommendation = require('../models/tech_stack_recommendation');
const database = require('../config/database');

/**
 * Automated Tech Stack Analyzer Service
 * Automatically analyzes templates and generates tech stack recommendations
 */
class AutoTechStackAnalyzer {
  constructor() {
    this.analyzer = new IntelligentTechStackAnalyzer();
    this.isProcessing = false;
    this.processingQueue = [];
    this.batchSize = 5; // Process 5 templates at a time
    this.delayBetweenBatches = 2000; // 2 seconds between batches
    this.isInitialized = false;
  }

  /**
   * Initialize the auto analyzer
   */
  async initialize() {
    if (this.isInitialized) {
      console.log('🤖 [AutoTechStack] Already initialized');
      return;
    }

    console.log('🤖 [AutoTechStack] 🚀 Initializing automated tech stack analyzer...');
    
    try {
      // Test database connection
      await database.query('SELECT 1');
      console.log('✅ [AutoTechStack] Database connection verified');
      
      // Test tech stack analyzer
      console.log('🧪 [AutoTechStack] Testing tech stack analyzer...');
      // We'll test with a simple template structure
      const testTemplate = {
        id: 'test',
        title: 'Test Template',
        description: 'Test description',
        category: 'test',
        features: [],
        business_rules: {},
        feature_count: 0
      };
      
      // Just test the analyzer initialization, don't actually analyze
      console.log('✅ [AutoTechStack] Tech stack analyzer ready');
      
      this.isInitialized = true;
      console.log('🎉 [AutoTechStack] Auto analyzer initialized successfully');
      
    } catch (error) {
      console.error('❌ [AutoTechStack] Initialization failed:', error.message);
      throw error;
    }
  }

  /**
   * Automatically analyze a single template when it's created/updated
   * @param {string} templateId - Template ID
   * @param {string} templateType - 'default' or 'custom'
   * @param {Object} templateData - Complete template data
   */
  async autoAnalyzeTemplate(templateId, templateType, templateData = null) {
    try {
      console.log(`🤖 [AutoTechStack] 🚀 Starting auto-analysis for ${templateType} template: ${templateId}`);
      
      // Check if recommendation already exists and is recent (less than 7 days old)
      const existing = await TechStackRecommendation.getByTemplateId(templateId, templateType);
      if (existing && this.isRecentRecommendation(existing)) {
        console.log(`⏭️ [AutoTechStack] ⏸️ Skipping ${templateId} - recent recommendation exists (${existing.last_analyzed_at})`);
        return { status: 'skipped', reason: 'recent_recommendation_exists' };
      }

      // Fetch template data if not provided
      if (!templateData) {
        console.log(`📋 [AutoTechStack] 📥 Fetching template data for: ${templateId}`);
        templateData = await this.fetchTemplateWithFeatures(templateId, templateType);
        if (!templateData) {
          console.error(`❌ [AutoTechStack] ❌ Template not found: ${templateId}`);
          return { status: 'failed', reason: 'template_not_found' };
        }
        console.log(`📋 [AutoTechStack] ✅ Template data fetched: ${templateData.title} (${templateData.feature_count} features)`);
      }

      // Analyze the template
      console.log(`🧠 [AutoTechStack] 🎯 Analyzing template: ${templateData.title} with Claude AI...`);
      const analysisResult = await this.analyzer.analyzeTemplate(templateData);
      
      // Save the recommendation
      console.log(`💾 [AutoTechStack] 💾 Saving tech stack recommendation to database...`);
      const recommendation = await TechStackRecommendation.upsert(
        templateId,
        templateType,
        analysisResult
      );

      console.log(`✅ [AutoTechStack] 🎉 Auto-analysis completed for ${templateId}: ${analysisResult.status}`);
      console.log(`📊 [AutoTechStack] 📈 Recommendation saved with ID: ${recommendation.id}`);
      console.log(`⏱️ [AutoTechStack] ⏱️ Processing time: ${analysisResult.processing_time_ms}ms`);
      
      return {
        status: 'completed',
        recommendation_id: recommendation.id,
        processing_time_ms: analysisResult.processing_time_ms
      };

    } catch (error) {
      console.error(`❌ [AutoTechStack] Auto-analysis failed for ${templateId}:`, error.message);
      
      // Save failed analysis for retry
      await TechStackRecommendation.upsert(templateId, templateType, {
        status: 'failed',
        error_message: error.message,
        processing_time_ms: 0
      });

      return {
        status: 'failed',
        error: error.message
      };
    }
  }

  /**
   * Queue a template for analysis (for background processing)
   * @param {string} templateId - Template ID
   * @param {string} templateType - 'default' or 'custom'
   * @param {number} priority - Priority level (1 = high, 2 = normal, 3 = low)
   */
  queueForAnalysis(templateId, templateType, priority = 2) {
    // Ensure analyzer is initialized
    if (!this.isInitialized) {
      console.log('⚠️ [AutoTechStack] Analyzer not initialized, initializing now...');
      this.initialize().then(() => {
        this.queueForAnalysis(templateId, templateType, priority);
      }).catch(error => {
        console.error('❌ [AutoTechStack] Failed to initialize:', error.message);
      });
      return;
    }

    const queueItem = {
      templateId,
      templateType,
      priority,
      queuedAt: new Date(),
      attempts: 0
    };

    // Insert based on priority
    if (priority === 1) {
      this.processingQueue.unshift(queueItem); // High priority at front
    } else {
      this.processingQueue.push(queueItem); // Normal/low priority at back
    }

    console.log(`📋 [AutoTechStack] 📝 Queued ${templateType} template ${templateId} for analysis (priority: ${priority})`);
    console.log(`📋 [AutoTechStack] 📊 Queue length: ${this.processingQueue.length} items`);
    
    // Start processing if not already running
    if (!this.isProcessing) {
      console.log(`🚀 [AutoTechStack] 🚀 Starting queue processing...`);
      this.processQueue();
    }
  }

  /**
   * Process the analysis queue
   */
  async processQueue() {
    if (this.isProcessing || this.processingQueue.length === 0) {
      return;
    }

    this.isProcessing = true;
    console.log(`🚀 [AutoTechStack] 🚀 Starting queue processing (${this.processingQueue.length} items)`);

    while (this.processingQueue.length > 0) {
      const batch = this.processingQueue.splice(0, this.batchSize);
      
      console.log(`📦 [AutoTechStack] 📦 Processing batch of ${batch.length} templates`);
      console.log(`📦 [AutoTechStack] 📋 Batch items:`, batch.map(item => `${item.templateId} (${item.templateType}, priority: ${item.priority})`));
      
      // Process batch in parallel
      const batchPromises = batch.map(async (item) => {
        try {
          item.attempts++;
          console.log(`🔄 [AutoTechStack] 🔄 Processing ${item.templateId} (attempt ${item.attempts})`);
          const result = await this.autoAnalyzeTemplate(item.templateId, item.templateType);
          
          if (result.status === 'failed' && item.attempts < 3) {
            // Retry failed items (up to 3 attempts)
            console.log(`🔄 [AutoTechStack] 🔄 Retrying ${item.templateId} (attempt ${item.attempts + 1})`);
            this.processingQueue.push(item);
          } else {
            console.log(`✅ [AutoTechStack] ✅ Completed ${item.templateId}: ${result.status}`);
          }
        } catch (error) {
          console.error(`❌ [AutoTechStack] ❌ Batch processing error for ${item.templateId}:`, error.message);
        }
      });

      await Promise.allSettled(batchPromises);

      // Delay between batches to avoid overwhelming the system
      if (this.processingQueue.length > 0) {
        console.log(`⏳ [AutoTechStack] ⏳ Waiting ${this.delayBetweenBatches}ms before next batch (${this.processingQueue.length} items remaining)`);
        await new Promise(resolve => setTimeout(resolve, this.delayBetweenBatches));
      }
    }

    this.isProcessing = false;
    console.log(`✅ [AutoTechStack] ✅ Queue processing completed`);
  }

  /**
   * Analyze all templates that don't have recommendations
   */
  async analyzeAllPendingTemplates() {
    try {
      console.log(`🔍 [AutoTechStack] Finding templates without tech stack recommendations...`);
      
      // Get all templates
      const allTemplates = await this.getAllTemplatesWithoutRecommendations();
      
      if (allTemplates.length === 0) {
        console.log(`✅ [AutoTechStack] All templates already have recommendations`);
        return { status: 'completed', processed: 0, message: 'All templates already analyzed' };
      }

      console.log(`📊 [AutoTechStack] Found ${allTemplates.length} templates without recommendations`);
      
      // Queue all templates for analysis
      allTemplates.forEach(template => {
        this.queueForAnalysis(template.id, template.type, 2); // Normal priority
      });

      return {
        status: 'queued',
        queued_count: allTemplates.length,
        message: `${allTemplates.length} templates queued for analysis`
      };

    } catch (error) {
      console.error(`❌ [AutoTechStack] Error analyzing pending templates:`, error.message);
      throw error;
    }
  }

  /**
   * Analyze ALL templates regardless of existing recommendations (force analysis)
   */
  async analyzeAllTemplates(forceUpdate = false) {
    try {
      console.log(`🔍 [AutoTechStack] Finding ALL templates for analysis (force: ${forceUpdate})...`);
      
      // Get all templates regardless of existing recommendations
      const allTemplates = await this.getAllTemplates();
      
      if (allTemplates.length === 0) {
        console.log(`✅ [AutoTechStack] No templates found in database`);
        return { status: 'completed', processed: 0, message: 'No templates found' };
      }

      console.log(`📊 [AutoTechStack] Found ${allTemplates.length} total templates`);
      
      // Queue all templates for analysis
      allTemplates.forEach(template => {
        this.queueForAnalysis(template.id, template.type, 2); // Normal priority
      });

      return {
        status: 'queued',
        queued_count: allTemplates.length,
        message: `${allTemplates.length} templates queued for analysis`
      };

    } catch (error) {
      console.error(`❌ [AutoTechStack] Error analyzing all templates:`, error.message);
      throw error;
    }
  }

  /**
   * Get ALL templates from database
   */
  async getAllTemplates() {
    try {
      console.log(`🔍 [AutoTechStack] Fetching all templates from database...`);
      
      // Get all default templates
      const defaultTemplates = await database.query(`
        SELECT t.id, 'default' as type, t.title, t.category
        FROM templates t
        WHERE t.is_active = true
      `);
      console.log(`📊 [AutoTechStack] Found ${defaultTemplates.rows.length} default templates`);

      // Get all custom templates
      const customTemplates = await database.query(`
        SELECT ct.id, 'custom' as type, ct.title, ct.category
        FROM custom_templates ct
      `);
      console.log(`📊 [AutoTechStack] Found ${customTemplates.rows.length} custom templates`);

      const allTemplates = [...defaultTemplates.rows, ...customTemplates.rows];
      console.log(`📊 [AutoTechStack] Total templates: ${allTemplates.length}`);
      
      return allTemplates;

    } catch (error) {
      console.error(`❌ [AutoTechStack] Error fetching all templates:`, error.message);
      throw error;
    }
  }

  /**
   * Get all templates that don't have tech stack recommendations
   */
  async getAllTemplatesWithoutRecommendations() {
    try {
      console.log(`🔍 [AutoTechStack] Checking for templates without recommendations...`);
      
      // First, let's check if the tech_stack_recommendations table exists and has data
      const tableCheck = await database.query(`
        SELECT COUNT(*) as count FROM tech_stack_recommendations
      `);
      console.log(`📊 [AutoTechStack] Tech stack recommendations table has ${tableCheck.rows[0].count} records`);
      
      // Get all default templates
      const defaultTemplates = await database.query(`
        SELECT t.id, 'default' as type, t.title, t.category
        FROM templates t
        WHERE t.is_active = true
        AND NOT EXISTS (
          SELECT 1 FROM tech_stack_recommendations tsr 
          WHERE tsr.template_id = t.id AND tsr.template_type = 'default'
        )
      `);
      console.log(`📊 [AutoTechStack] Found ${defaultTemplates.rows.length} default templates without recommendations`);

      // Get all custom templates
      const customTemplates = await database.query(`
        SELECT ct.id, 'custom' as type, ct.title, ct.category
        FROM custom_templates ct
        WHERE NOT EXISTS (
          SELECT 1 FROM tech_stack_recommendations tsr 
          WHERE tsr.template_id = ct.id AND tsr.template_type = 'custom'
        )
      `);
      console.log(`📊 [AutoTechStack] Found ${customTemplates.rows.length} custom templates without recommendations`);

      const allTemplates = [...defaultTemplates.rows, ...customTemplates.rows];
      console.log(`📊 [AutoTechStack] Total templates without recommendations: ${allTemplates.length}`);
      
      return allTemplates;

    } catch (error) {
      console.error(`❌ [AutoTechStack] Error fetching templates without recommendations:`, error.message);
      throw error;
    }
  }

  /**
   * Fetch template with features and business rules
   */
  async fetchTemplateWithFeatures(templateId, templateType) {
    try {
      console.log(`📋 [AutoTechStack] 🔍 Fetching ${templateType} template: ${templateId}`);
      
      // Determine which table to query
      const tableName = templateType === 'default' ? 'templates' : 'custom_templates';
      
      // Get template data
      const templateQuery = `
        SELECT * FROM ${tableName} 
        WHERE id = $1 AND is_active = true
      `;
      
      // Get features data
      const featuresQuery = `
        SELECT * FROM template_features 
        WHERE template_id = $1 
        ORDER BY display_order, name
      `;
      
      // Get business rules
      const businessRulesQuery = `
        SELECT feature_id, business_rules 
        FROM feature_business_rules 
        WHERE template_id = $1
      `;
      
      // Execute all queries in parallel
      const [templateResult, featuresResult, businessRulesResult] = await Promise.all([
        database.query(templateQuery, [templateId]),
        database.query(featuresQuery, [templateId]),
        database.query(businessRulesQuery, [templateId])
      ]);
      
      if (templateResult.rows.length === 0) {
        console.log(`❌ [AutoTechStack] Template not found: ${templateId}`);
        return null;
      }
      
      const template = templateResult.rows[0];
      const features = featuresResult.rows;
      
      // Convert business rules to object
      const businessRules = {};
      businessRulesResult.rows.forEach(row => {
        businessRules[row.feature_id] = row.business_rules;
      });
      
      const templateData = {
        id: template.id,
        title: template.title,
        description: template.description,
        category: template.category,
        features: features,
        business_rules: businessRules,
        feature_count: features.length,
        is_custom: templateType === 'custom'
      };
      
      console.log(`✅ [AutoTechStack] Template data fetched: ${template.title} (${features.length} features, ${Object.keys(businessRules).length} business rules)`);
      return templateData;
      
    } catch (error) {
      console.error(`❌ [AutoTechStack] Error fetching template with features:`, error.message);
      throw error;
    }
  }

  /**
   * Check if a recommendation is recent (less than specified days old)
   */
  isRecentRecommendation(recommendation, daysOld = 7) {
    const daysInMs = daysOld * 24 * 60 * 60 * 1000;
    const recommendationAge = Date.now() - new Date(recommendation.last_analyzed_at).getTime();
    return recommendationAge < daysInMs;
  }

  /**
   * Get queue status
   */
  getQueueStatus() {
    return {
      isProcessing: this.isProcessing,
      queueLength: this.processingQueue.length,
      isInitialized: this.isInitialized,
      queueItems: this.processingQueue.map(item => ({
        templateId: item.templateId,
        templateType: item.templateType,
        priority: item.priority,
        queuedAt: item.queuedAt,
        attempts: item.attempts
      }))
    };
  }

  /**
   * Check if analyzer is ready
   */
  isReady() {
    return this.isInitialized;
  }

  /**
   * Clear the processing queue
   */
  clearQueue() {
    const clearedCount = this.processingQueue.length;
    this.processingQueue = [];
    console.log(`🗑️ [AutoTechStack] Cleared ${clearedCount} items from processing queue`);
    return clearedCount;
  }
}

// Create singleton instance
const autoTechStackAnalyzer = new AutoTechStackAnalyzer();

module.exports = autoTechStackAnalyzer;
