const { Pool } = require('pg');
const logger = require('../utils/logger');

class DatabaseService {
  constructor() {
    this.pool = new Pool({
      host: process.env.POSTGRES_HOST || 'postgres',
      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,
    });

    this.initializeDatabase();
  }

  async initializeDatabase() {
    try {
      // Wait a bit for database to be ready
      await new Promise(resolve => setTimeout(resolve, 2000));
      await this.createRecommendationsTable();
      logger.info('Database service initialized successfully');
    } catch (error) {
      logger.error('Failed to initialize database service:', error);
      // Don't throw error, just log it
    }
  }

  async createRecommendationsTable() {
    const createTableQuery = `
      CREATE TABLE IF NOT EXISTS claude_recommendations (
        id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
        request_id VARCHAR(255) UNIQUE NOT NULL,
        domain VARCHAR(100) NOT NULL,
        budget DECIMAL(10,2) NOT NULL,
        preferred_technologies TEXT[],
        template_id UUID,
        stack_name VARCHAR(255) NOT NULL,
        monthly_cost DECIMAL(10,2) NOT NULL,
        setup_cost DECIMAL(10,2) NOT NULL,
        team_size VARCHAR(50) NOT NULL,
        development_time INTEGER NOT NULL,
        satisfaction INTEGER NOT NULL CHECK (satisfaction >= 0 AND satisfaction <= 100),
        success_rate INTEGER NOT NULL CHECK (success_rate >= 0 AND success_rate <= 100),
        frontend VARCHAR(100) NOT NULL,
        backend VARCHAR(100) NOT NULL,
        database VARCHAR(100) NOT NULL,
        cloud VARCHAR(100) NOT NULL,
        testing VARCHAR(100) NOT NULL,
        mobile VARCHAR(100),
        devops VARCHAR(100) NOT NULL,
        ai_ml VARCHAR(100),
        recommended_tool VARCHAR(100) NOT NULL,
        recommendation_score DECIMAL(5,2) NOT NULL CHECK (recommendation_score >= 0 AND recommendation_score <= 100),
        message TEXT NOT NULL,
        claude_model VARCHAR(100) NOT NULL,
        processing_time INTEGER NOT NULL,
        created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
      );
    `;

    const createIndexQuery = `
      CREATE INDEX IF NOT EXISTS idx_claude_recommendations_domain ON claude_recommendations(domain);
      CREATE INDEX IF NOT EXISTS idx_claude_recommendations_budget ON claude_recommendations(budget);
      CREATE INDEX IF NOT EXISTS idx_claude_recommendations_template_id ON claude_recommendations(template_id);
      CREATE INDEX IF NOT EXISTS idx_claude_recommendations_created_at ON claude_recommendations(created_at);
    `;

    try {
      await this.pool.query(createTableQuery);
      await this.pool.query(createIndexQuery);
      logger.info('Claude recommendations table created successfully');
    } catch (error) {
      logger.error('Error creating recommendations table:', error);
      throw error;
    }
  }

  async storeRecommendation(recommendationData) {
    const {
      requestId,
      domain,
      budget,
      preferredTechnologies,
      templateId,
      stackName,
      monthlyCost,
      setupCost,
      teamSize,
      developmentTime,
      satisfaction,
      successRate,
      frontend,
      backend,
      database,
      cloud,
      testing,
      mobile,
      devops,
      aiMl,
      recommendedTool,
      recommendationScore,
      message,
      claudeModel,
      processingTime
    } = recommendationData;

    const insertQuery = `
      INSERT INTO claude_recommendations (
        request_id, domain, budget, preferred_technologies, template_id,
        stack_name, monthly_cost, setup_cost, team_size, development_time,
        satisfaction, success_rate, frontend, backend, database, cloud,
        testing, mobile, devops, ai_ml, recommended_tool, recommendation_score,
        message, claude_model, processing_time
      ) 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, $25
      )
      RETURNING id, created_at;
    `;

    const values = [
      requestId,
      domain,
      budget,
      preferredTechnologies || [],
      templateId,
      stackName,
      monthlyCost,
      setupCost,
      teamSize,
      developmentTime,
      satisfaction,
      successRate,
      frontend,
      backend,
      database,
      cloud,
      testing,
      mobile || null,
      devops,
      aiMl || null,
      recommendedTool,
      recommendationScore,
      message,
      claudeModel,
      processingTime
    ];

    try {
      const result = await this.pool.query(insertQuery, values);
      logger.info(`Recommendation stored successfully with ID: ${result.rows[0].id}`);
      return {
        success: true,
        id: result.rows[0].id,
        createdAt: result.rows[0].created_at
      };
    } catch (error) {
      logger.error('Error storing recommendation:', error);
      return {
        success: false,
        error: error.message
      };
    }
  }

  async getRecommendationById(id) {
    const query = 'SELECT * FROM claude_recommendations WHERE id = $1';
    try {
      const result = await this.pool.query(query, [id]);
      return result.rows[0] || null;
    } catch (error) {
      logger.error('Error fetching recommendation by ID:', error);
      return null;
    }
  }

  async getRecommendationsByDomain(domain, limit = 10) {
    const query = `
      SELECT * FROM claude_recommendations 
      WHERE domain = $1 
      ORDER BY created_at DESC 
      LIMIT $2
    `;
    try {
      const result = await this.pool.query(query, [domain, limit]);
      return result.rows;
    } catch (error) {
      logger.error('Error fetching recommendations by domain:', error);
      return [];
    }
  }

  async getRecommendationsByTemplateId(templateId, limit = 10) {
    const query = `
      SELECT * FROM claude_recommendations 
      WHERE template_id = $1 
      ORDER BY created_at DESC 
      LIMIT $2
    `;
    try {
      const result = await this.pool.query(query, [templateId, limit]);
      return result.rows;
    } catch (error) {
      logger.error('Error fetching recommendations by template ID:', error);
      return [];
    }
  }

  async getRecentRecommendations(limit = 20) {
    const query = `
      SELECT * FROM claude_recommendations 
      ORDER BY created_at DESC 
      LIMIT $1
    `;
    try {
      const result = await this.pool.query(query, [limit]);
      return result.rows;
    } catch (error) {
      logger.error('Error fetching recent recommendations:', error);
      return [];
    }
  }

  async getRecommendationStats() {
    const query = `
      SELECT 
        COUNT(*) as total_recommendations,
        COUNT(DISTINCT domain) as unique_domains,
        COUNT(DISTINCT template_id) as unique_templates,
        AVG(recommendation_score) as avg_score,
        AVG(processing_time) as avg_processing_time,
        MIN(created_at) as first_recommendation,
        MAX(created_at) as last_recommendation
      FROM claude_recommendations
    `;
    try {
      const result = await this.pool.query(query);
      return result.rows[0];
    } catch (error) {
      logger.error('Error fetching recommendation stats:', error);
      return null;
    }
  }

  async isHealthy() {
    try {
      await this.pool.query('SELECT 1');
      return true;
    } catch (error) {
      logger.error('Database health check failed:', error);
      return false;
    }
  }

  async close() {
    try {
      await this.pool.end();
      logger.info('Database connection pool closed');
    } catch (error) {
      logger.error('Error closing database connection:', error);
    }
  }
}

module.exports = DatabaseService;
