/**
 * @ai-summary Vehicle data repository for hierarchical dropdown queries
 * @ai-context Queries denormalized vehicle_options table with string-based cascade
 * @ai-migration Updated to use new ETL-generated database (1.1M+ vehicle configurations)
 */
import { Pool } from 'pg';
import { VINDecodeResult } from '../models/responses';
import { logger } from '../../../core/logging/logger';

export class VehicleDataRepository {
  /**
   * Get distinct years from vehicle_options table
   */
  async getYears(pool: Pool): Promise<number[]> {
    const query = `
      SELECT DISTINCT year
      FROM vehicle_options
      ORDER BY year DESC
    `;

    try {
      const result = await pool.query(query);
      return result.rows.map(row => row.year);
    } catch (error) {
      logger.error('Repository error: getYears', { error });
      throw new Error('Failed to retrieve years from database');
    }
  }

  /**
   * Get makes for a specific year using database function
   */
  async getMakes(pool: Pool, year: number): Promise<string[]> {
    const query = `
      SELECT make FROM get_makes_for_year($1)
    `;

    try {
      const result = await pool.query(query, [year]);
      return result.rows.map(row => row.make);
    } catch (error) {
      logger.error('Repository error: getMakes', { error, year });
      throw new Error(`Failed to retrieve makes for year ${year}`);
    }
  }

  /**
   * Get models for a specific year and make using database function
   */
  async getModels(pool: Pool, year: number, make: string): Promise<string[]> {
    const query = `
      SELECT model FROM get_models_for_year_make($1, $2)
    `;

    try {
      const result = await pool.query(query, [year, make]);
      return result.rows.map(row => row.model);
    } catch (error) {
      logger.error('Repository error: getModels', { error, year, make });
      throw new Error(`Failed to retrieve models for year ${year}, make ${make}`);
    }
  }

  /**
   * Get trims for a specific year, make, and model using database function
   */
  async getTrims(pool: Pool, year: number, make: string, model: string): Promise<string[]> {
    const query = `
      SELECT trim_name FROM get_trims_for_year_make_model($1, $2, $3)
    `;

    try {
      const result = await pool.query(query, [year, make, model]);
      return result.rows.map(row => row.trim_name);
    } catch (error) {
      logger.error('Repository error: getTrims', { error, year, make, model });
      throw new Error(`Failed to retrieve trims for year ${year}, make ${make}, model ${model}`);
    }
  }

  /**
   * Get engines for a specific year, make, model, and trim
   * Returns 'N/A (Electric)' for electric vehicles with NULL engine_id
   */
  async getEngines(pool: Pool, year: number, make: string, model: string, trim: string): Promise<string[]> {
    const query = `
      SELECT engine_name FROM get_engines_for_vehicle($1, $2, $3, $4)
    `;

    try {
      const result = await pool.query(query, [year, make, model, trim]);
      return result.rows.map(row => row.engine_name);
    } catch (error) {
      logger.error('Repository error: getEngines', { error, year, make, model, trim });
      throw new Error(`Failed to retrieve engines for year ${year}, make ${make}, model ${model}, trim ${trim}`);
    }
  }

  /**
   * Get transmissions for a specific year, make, model, and trim
   * Returns real transmission types from the database (not hardcoded)
   */
  async getTransmissionsForTrim(pool: Pool, year: number, make: string, model: string, trim: string): Promise<string[]> {
    const query = `
      SELECT transmission_type FROM get_transmissions_for_vehicle($1, $2, $3, $4)
    `;

    try {
      const result = await pool.query(query, [year, make, model, trim]);
      return result.rows.map(row => row.transmission_type);
    } catch (error) {
      logger.error('Repository error: getTransmissionsForTrim', { error, year, make, model, trim });
      throw new Error(`Failed to retrieve transmissions for year ${year}, make ${make}, model ${model}, trim ${trim}`);
    }
  }

  async getTransmissionsForTrimAndEngine(pool: Pool, year: number, make: string, model: string, trim: string, engine: string): Promise<string[]> {
    const query = `
      SELECT transmission_type FROM get_transmissions_for_vehicle_engine($1, $2, $3, $4, $5)
    `;
    try {
      const result = await pool.query(query, [year, make, model, trim, engine]);
      return result.rows.map(row => row.transmission_type);
    } catch (error) {
      logger.error('Repository error: getTransmissionsForTrimAndEngine', { error, year, make, model, trim, engine });
      throw new Error(`Failed to retrieve transmissions for year ${year}, make ${make}, model ${model}, trim ${trim}, engine ${engine}`);
    }
  }

  async getEnginesForTrimAndTransmission(pool: Pool, year: number, make: string, model: string, trim: string, transmission: string): Promise<string[]> {
    const query = `
      SELECT engine_name FROM get_engines_for_vehicle_trans($1, $2, $3, $4, $5)
    `;
    try {
      const result = await pool.query(query, [year, make, model, trim, transmission]);
      return result.rows.map(row => row.engine_name);
    } catch (error) {
      logger.error('Repository error: getEnginesForTrimAndTransmission', { error, year, make, model, trim, transmission });
      throw new Error(`Failed to retrieve engines for year ${year}, make ${make}, model ${model}, trim ${trim}, transmission ${transmission}`);
    }
  }

  /**
   * Decode VIN using PostgreSQL function
   * NOTE: This function may need updates after vehicles.* schema migration
   * If the old f_decode_vin function no longer exists, it will need to be
   * reimplemented against the new vehicle_options schema
   */
  async decodeVIN(pool: Pool, vin: string): Promise<VINDecodeResult | null> {
    const query = `
      SELECT * FROM vehicles.f_decode_vin($1)
    `;

    try {
      const result = await pool.query(query, [vin]);

      if (result.rows.length === 0) {
        return null;
      }

      const row = result.rows[0];
      return {
        make: row.make || null,
        model: row.model || null,
        year: row.year || null,
        trim_name: row.trim_name || null,
        engine_description: row.engine_description || null,
        transmission_description: row.transmission_description || null,
        horsepower: row.horsepower || null,
        torque: row.torque || null,
        top_speed: row.top_speed || null,
        fuel: row.fuel || null,
        confidence_score: row.confidence_score ? parseFloat(row.confidence_score) : null,
        vehicle_type: row.vehicle_type || null
      };
    } catch (error) {
      logger.error('Repository error: decodeVIN', { error, vin });
      throw new Error(`Failed to decode VIN ${vin}`);
    }
  }
}
