const moment = require('moment');
const DataAvailabilityChecker = require('./dataAvailabilityChecker');

class HybridQueryGenerator {
  constructor() {
    this.dataChecker = new DataAvailabilityChecker();
  }

  /**
   * Generate rental trend query - always use transactions table for rental trends
   */
  async generateRentalTrendQuery(parsedQuery) {
    const { time_period, areas, property_types, room_types } = parsedQuery;
    const area = areas && areas.length > 0 ? areas[0] : null;
    const startDate = time_period ? time_period.startDate : moment().subtract(6, 'months').format('YYYY-MM-DD');

    if (!area) {
      throw new Error('No area specified for rental trend query');
    }

    // For rental trend queries, always use transactions table
    const dataSource = {
      table: 'transactions',
      dateColumn: 'instance_date',
      priceColumn: 'trans_value',
      areaColumn: 'area_en',
      reason: 'Using transaction data for rental price trends'
    };

    return this.generateRentalTrendFromTransactions(parsedQuery, dataSource);
  }

  /**
   * Generate rental trend query from rents table
   */
  generateRentalTrendFromRents(parsedQuery, dataSource) {
    const { time_period, areas, property_types } = parsedQuery;
    
    let sql = `
      SELECT 
        DATE_FORMAT(${dataSource.dateColumn}, '%Y-%m') as month,
        AVG(${dataSource.priceColumn}) as avg_price,
        COUNT(*) as transaction_count,
        AVG(actual_area) as avg_area
      FROM ${dataSource.table} 
      WHERE ${dataSource.areaColumn} = ? 
        AND ${dataSource.dateColumn} >= ?
    `;

    const params = [areas[0], time_period.startDate];

    // Add property type filter if specified
    if (property_types && property_types.length > 0) {
      sql += ` AND prop_sub_type_en = ?`;
      params.push(property_types[0]);
    }

    sql += ` GROUP BY DATE_FORMAT(${dataSource.dateColumn}, '%Y-%m') ORDER BY month`;

    return { 
      sql, 
      params, 
      dataSource: dataSource.table,
      fallbackReason: dataSource.reason
    };
  }

  /**
   * Generate rental trend query from transactions table (fallback)
   */
  generateRentalTrendFromTransactions(parsedQuery, dataSource) {
    const { time_period, areas, property_types } = parsedQuery;
    
    let sql = `
      SELECT 
        DATE_FORMAT(${dataSource.dateColumn}, '%Y-%m') as month,
        AVG(${dataSource.priceColumn}) as avg_price,
        COUNT(*) as transaction_count,
        AVG(actual_area) as avg_area
      FROM ${dataSource.table} 
      WHERE ${dataSource.areaColumn} = ? 
        AND ${dataSource.dateColumn} >= ?
        AND usage_en = 'residential'
    `;

    const params = [areas[0], time_period.startDate];

    // Add property type filter if specified
    if (property_types && property_types.length > 0) {
      sql += ` AND prop_type_en = ?`;
      params.push(property_types[0]);
    }

    sql += ` GROUP BY DATE_FORMAT(${dataSource.dateColumn}, '%Y-%m') ORDER BY month`;

    return { 
      sql, 
      params, 
      dataSource: dataSource.table,
      fallbackReason: dataSource.reason
    };
  }

  /**
   * Generate area comparison query with fallback
   */
  async generateAreaComparisonQuery(parsedQuery) {
    const { time_period, areas } = parsedQuery;
    const startDate = time_period ? time_period.startDate : moment().subtract(6, 'months').format('YYYY-MM-DD');

    // Check if we have rental data for any of the areas
    let hasRentalData = false;
    if (areas && areas.length > 0) {
      for (const area of areas) {
        if (await this.dataChecker.hasRentalData(area, startDate)) {
          hasRentalData = true;
          break;
        }
      }
    }

    if (hasRentalData) {
      return this.generateAreaComparisonFromRents(parsedQuery);
    } else {
      return this.generateAreaComparisonFromTransactions(parsedQuery);
    }
  }

  /**
   * Generate area comparison from rents table
   */
  generateAreaComparisonFromRents(parsedQuery) {
    const { time_period, areas } = parsedQuery;
    
    let sql = `
      SELECT 
        area_en,
        AVG(annual_amount) as avg_price,
        COUNT(*) as transaction_count,
        AVG(actual_area) as avg_area
      FROM rents 
      WHERE 1=1
    `;

    const params = [];

    if (time_period && time_period.startDate) {
      sql += ` AND start_date >= ?`;
      params.push(time_period.startDate);
    }

    if (areas && areas.length > 0) {
      const areaPlaceholders = areas.map(() => '?').join(',');
      sql += ` AND area_en IN (${areaPlaceholders})`;
      params.push(...areas);
    }

    sql += ` GROUP BY area_en ORDER BY avg_price DESC`;

    return { 
      sql, 
      params, 
      dataSource: 'rents',
      fallbackReason: 'Using rental data'
    };
  }

  /**
   * Generate area comparison from transactions table
   */
  generateAreaComparisonFromTransactions(parsedQuery) {
    const { time_period, areas } = parsedQuery;
    
    let sql = `
      SELECT 
        area_en,
        AVG(trans_value) as avg_price,
        COUNT(*) as transaction_count,
        AVG(actual_area) as avg_area
      FROM transactions 
      WHERE usage_en = 'residential'
    `;

    const params = [];

    if (time_period && time_period.startDate) {
      sql += ` AND instance_date >= ?`;
      params.push(time_period.startDate);
    }

    if (areas && areas.length > 0) {
      const areaPlaceholders = areas.map(() => '?').join(',');
      sql += ` AND area_en IN (${areaPlaceholders})`;
      params.push(...areas);
    }

    sql += ` GROUP BY area_en ORDER BY avg_price DESC`;

    return { 
      sql, 
      params, 
      dataSource: 'transactions',
      fallbackReason: 'Using transaction data as fallback (no rental data)'
    };
  }

  /**
   * Get suggested areas when no data is found
   */
  async getSuggestedAreas(originalArea, limit = 5) {
    try {
      // Get areas with rental data
      const rentalAreas = await this.dataChecker.getAvailableAreas('rents', limit);
      
      // Get areas with transaction data
      const transactionAreas = await this.dataChecker.getAvailableAreas('transactions', limit);
      
      // Combine and deduplicate
      const allAreas = [...new Set([...rentalAreas, ...transactionAreas])];
      
      return {
        suggested: allAreas.slice(0, limit),
        rentalAreas: rentalAreas.slice(0, 3),
        transactionAreas: transactionAreas.slice(0, 3),
        originalArea
      };
    } catch (error) {
      console.error('Error getting suggested areas:', error);
      return {
        suggested: [],
        rentalAreas: [],
        transactionAreas: [],
        originalArea
      };
    }
  }
}

module.exports = HybridQueryGenerator;
