const { Pool } = require('pg');
const crypto = require('crypto');

/**
 * Database client for Unified Tech Stack Service
 * Connects to the same PostgreSQL database as template-manager service
 */
class DatabaseClient {
  constructor() {
    this.pool = new Pool({
      host: process.env.POSTGRES_HOST || 'localhost',
      port: process.env.POSTGRES_PORT || 5432,
      database: process.env.POSTGRES_DB || 'dev_pipeline',
      user: process.env.POSTGRES_USER || 'pipeline_admin',
      password: process.env.POSTGRES_PASSWORD || 'secure_pipeline_2024',
      max: 20,
      idleTimeoutMillis: 30000,
      connectionTimeoutMillis: 2000,
    });

    // Test connection on startup
    this.testConnection();
  }

  async testConnection() {
    try {
      const client = await this.pool.connect();
      console.log('✅ Unified Tech Stack Service - Database connected successfully');
      client.release();
    } catch (err) {
      console.error('❌ Unified Tech Stack Service - Database connection failed:', err.message);
      // Don't exit process, just log error - service can work without database
    }
  }

  async query(text, params) {
    const start = Date.now();
    try {
      const res = await this.pool.query(text, params);
      const duration = Date.now() - start;
      console.log('📊 Unified Service Query executed:', { 
        text: text.substring(0, 50), 
        duration, 
        rows: res.rowCount 
      });
      return res;
    } catch (err) {
      console.error('❌ Unified Service Query error:', err.message);
      throw err;
    }
  }

  async getClient() {
    return await this.pool.connect();
  }

  async connect() {
    return await this.pool.connect();
  }

  async close() {
    await this.pool.end();
    console.log('🔌 Unified Tech Stack Service - Database connection closed');
  }

  /**
   * Generate hash for request deduplication
   */
  generateRequestHash(requestData) {
    const normalizedData = {
      templateId: requestData.templateId,
      budget: requestData.budget,
      domain: requestData.domain,
      features: requestData.features?.sort() || [],
      includeClaude: requestData.includeClaude,
      includeTemplateBased: requestData.includeTemplateBased,
      includeDomainBased: requestData.includeDomainBased
    };
    
    return crypto
      .createHash('sha256')
      .update(JSON.stringify(normalizedData))
      .digest('hex');
  }

  /**
   * Save unified recommendations to database
   */
  async saveRecommendations(recommendationData) {
    const {
      templateId,
      userId = null,
      sessionId = null,
      recommendationType = 'user',
      template,
      features,
      businessContext,
      unifiedData,
      claudeData,
      templateBasedData,
      domainBasedData,
      analysisData,
      expiresAt = null
    } = recommendationData;

    try {
      // Generate request hash for deduplication
      const requestHash = this.generateRequestHash({
        templateId,
        budget: unifiedData?.budget,
        domain: unifiedData?.domain,
        features: features?.map(f => f.name),
        includeClaude: !!claudeData,
        includeTemplateBased: !!templateBasedData,
        includeDomainBased: !!domainBasedData
      });

      // Extract tech stack categories from unified data
      const techStackCategories = this.extractTechStackCategories(unifiedData);
      
      // Prepare confidence scores
      const confidenceScores = {
        claude: claudeData?.success ? 0.5 : 0,
        template: templateBasedData?.success ? 0.3 : 0,
        domain: domainBasedData?.success ? 0.2 : 0,
        overall: unifiedData?.confidence || 0
      };

      // Prepare reasoning data
      const reasoning = {
        claude: claudeData?.data?.claude_recommendations || null,
        template: templateBasedData?.data || null,
        domain: domainBasedData?.data || null,
        analysis: analysisData || null
      };

      const query = `
        INSERT INTO tech_stack_recommendations (
          template_id, template_type, user_id, session_id, request_hash,
          recommendation_type, user_context, unified_data, source_services,
          frontend, backend, mobile, testing, ai_ml, devops, cloud, tools,
          confidence_scores, reasoning, ai_model, analysis_version,
          status, processing_time_ms, expires_at
        ) VALUES (
          $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24
        )
        ON CONFLICT (template_id, template_type, user_id, recommendation_type)
        DO UPDATE SET
          session_id = EXCLUDED.session_id,
          request_hash = EXCLUDED.request_hash,
          user_context = EXCLUDED.user_context,
          unified_data = EXCLUDED.unified_data,
          source_services = EXCLUDED.source_services,
          frontend = EXCLUDED.frontend,
          backend = EXCLUDED.backend,
          mobile = EXCLUDED.mobile,
          testing = EXCLUDED.testing,
          ai_ml = EXCLUDED.ai_ml,
          devops = EXCLUDED.devops,
          cloud = EXCLUDED.cloud,
          tools = EXCLUDED.tools,
          confidence_scores = EXCLUDED.confidence_scores,
          reasoning = EXCLUDED.reasoning,
          status = EXCLUDED.status,
          processing_time_ms = EXCLUDED.processing_time_ms,
          expires_at = EXCLUDED.expires_at,
          updated_at = NOW(),
          last_analyzed_at = NOW()
        RETURNING id, created_at, updated_at
      `;

      const values = [
        templateId,
        template?.type || template?.category || template?.title || 'default',
        userId,
        sessionId,
        requestHash,
        recommendationType,
        JSON.stringify(businessContext),
        JSON.stringify(unifiedData),
        JSON.stringify({
          claude: !!claudeData?.success,
          template: !!templateBasedData?.success,
          domain: !!domainBasedData?.success
        }),
        techStackCategories.frontend,
        techStackCategories.backend,
        techStackCategories.mobile,
        techStackCategories.testing,
        techStackCategories.ai_ml,
        techStackCategories.devops,
        techStackCategories.cloud,
        techStackCategories.tools,
        JSON.stringify(confidenceScores),
        JSON.stringify(reasoning),
        'claude-3-5-sonnet-20241022',
        '1.0',
        'completed',
        null, // processing_time_ms - could be calculated if needed
        expiresAt
      ];

      const result = await this.query(query, values);
      
      console.log('✅ Saved unified recommendations to database:', {
        id: result.rows[0].id,
        templateId,
        userId,
        recommendationType
      });

      return {
        success: true,
        data: {
          id: result.rows[0].id,
          created_at: result.rows[0].created_at,
          updated_at: result.rows[0].updated_at
        }
      };

    } catch (error) {
      console.error('❌ Error saving recommendations to database:', error.message);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * Get recommendations for user with fallback logic
   */
  async getRecommendations(templateId, userId = null, sessionId = null) {
    try {
      const query = `
        SELECT * FROM get_recommendations_for_user($1, $2, $3)
      `;

      const result = await this.query(query, [templateId, userId, sessionId]);
      
      if (result.rows.length > 0) {
        const rec = result.rows[0];
        console.log('✅ Retrieved recommendations from database:', {
          id: rec.id,
          templateId: rec.template_id,
          userId: rec.user_id,
          sessionId: rec.session_id,
          recommendationType: rec.recommendation_type
        });

        return {
          success: true,
          data: {
            id: rec.id,
            templateId: rec.template_id,
            templateType: rec.template_type,
            userId: rec.user_id,
            sessionId: rec.session_id,
            recommendationType: rec.recommendation_type,
            frontend: rec.frontend,
            backend: rec.backend,
            mobile: rec.mobile,
            testing: rec.testing,
            ai_ml: rec.ai_ml,
            devops: rec.devops,
            cloud: rec.cloud,
            tools: rec.tools,
            unifiedData: rec.unified_data,
            confidenceScores: rec.confidence_scores,
            reasoning: rec.reasoning,
            createdAt: rec.created_at,
            lastAnalyzedAt: rec.last_analyzed_at
          }
        };
      } else {
        console.log('📝 No recommendations found in database for:', { templateId, userId, sessionId });
        return {
          success: false,
          error: 'No recommendations found'
        };
      }

    } catch (error) {
      console.error('❌ Error retrieving recommendations from database:', error.message);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * Extract tech stack categories from unified data
   */
  extractTechStackCategories(unifiedData) {
    const categories = {
      frontend: null,
      backend: null,
      mobile: null,
      testing: null,
      ai_ml: null,
      devops: null,
      cloud: null,
      tools: null
    };

    if (!unifiedData) return categories;

    // Extract from tech stacks
    if (unifiedData.techStacks && Array.isArray(unifiedData.techStacks)) {
      unifiedData.techStacks.forEach(techStack => {
        if (techStack.frontend) categories.frontend = techStack.frontend;
        if (techStack.backend) categories.backend = techStack.backend;
        if (techStack.mobile) categories.mobile = techStack.mobile;
        if (techStack.testing) categories.testing = techStack.testing;
        if (techStack.ai_ml) categories.ai_ml = techStack.ai_ml;
        if (techStack.devops) categories.devops = techStack.devops;
        if (techStack.cloud) categories.cloud = techStack.cloud;
        if (techStack.tools) categories.tools = techStack.tools;
      });
    }
     
    // Extract from claudeRecommendations.claude_recommendations.technology_recommendations
    if (unifiedData.claudeRecommendations?.claude_recommendations?.technology_recommendations) {
      const claudeRecs = unifiedData.claudeRecommendations.claude_recommendations.technology_recommendations;
      if (claudeRecs.frontend) categories.frontend = claudeRecs.frontend;
      if (claudeRecs.backend) categories.backend = claudeRecs.backend;
      if (claudeRecs.mobile) categories.mobile = claudeRecs.mobile;
      if (claudeRecs.devops) categories.devops = claudeRecs.devops;
      if (claudeRecs.ai_ml) categories.ai_ml = claudeRecs.ai_ml;
    }

    // Extract from claude_recommendations directly (alternative structure)
    if (unifiedData.claude_recommendations?.technology_recommendations) {
      const claudeRecs = unifiedData.claude_recommendations.technology_recommendations;
      if (claudeRecs.frontend) categories.frontend = claudeRecs.frontend;
      if (claudeRecs.backend) categories.backend = claudeRecs.backend;
      if (claudeRecs.mobile) categories.mobile = claudeRecs.mobile;
      if (claudeRecs.devops) categories.devops = claudeRecs.devops;
      if (claudeRecs.ai_ml) categories.ai_ml = claudeRecs.ai_ml;
    }

    return categories;
  }

  /**
   * Clean up expired recommendations
   */
  async cleanupExpiredRecommendations() {
    try {
      const result = await this.query('SELECT cleanup_expired_recommendations()');
      const deletedCount = result.rows[0].cleanup_expired_recommendations;
      
      if (deletedCount > 0) {
        console.log(`🧹 Cleaned up ${deletedCount} expired recommendations`);
      }
      
      return {
        success: true,
        deletedCount
      };
    } catch (error) {
      console.error('❌ Error cleaning up expired recommendations:', error.message);
      return {
        success: false,
        error: error.message
      };
    }
  }

  /**
   * Get user's recommendation history
   */
  async getUserRecommendationHistory(userId, limit = 10) {
    try {
      const query = `
        SELECT 
          id, template_id, template_type, recommendation_type,
          frontend, backend, mobile, testing, ai_ml, devops, cloud, tools,
          confidence_scores, created_at, last_analyzed_at
        FROM tech_stack_recommendations
        WHERE user_id = $1
        AND recommendation_type = 'user'
        ORDER BY created_at DESC
        LIMIT $2
      `;

      const result = await this.query(query, [userId, limit]);
      
      return {
        success: true,
        data: result.rows
      };
    } catch (error) {
      console.error('❌ Error getting user recommendation history:', error.message);
      return {
        success: false,
        error: error.message
      };
    }
  }
}

module.exports = new DatabaseClient();
