/**
 * @ai-summary Vehicle data service with caching for dropdown queries
 * @ai-context String-based cascade queries with Redis caching
 * @ai-migration Updated to use string parameters (not IDs)
 */
import { Pool } from 'pg';
import { VehicleDataRepository } from '../data/vehicle-data.repository';
import { PlatformCacheService } from './platform-cache.service';
import { logger } from '../../../core/logging/logger';

export class VehicleDataService {
  private repository: VehicleDataRepository;
  private cache: PlatformCacheService;

  constructor(cache: PlatformCacheService, repository?: VehicleDataRepository) {
    this.cache = cache;
    this.repository = repository || new VehicleDataRepository();
  }

  /**
   * Get available years with caching
   */
  async getYears(pool: Pool): Promise<number[]> {
    try {
      const cached = await this.cache.getYears();
      if (cached) {
        logger.debug('Years retrieved from cache');
        return cached;
      }

      const years = await this.repository.getYears(pool);
      await this.cache.setYears(years);
      logger.debug('Years retrieved from database and cached', { count: years.length });
      return years;
    } catch (error) {
      logger.error('Service error: getYears', { error });
      throw error;
    }
  }

  /**
   * Get makes for a year with caching
   */
  async getMakes(pool: Pool, year: number): Promise<string[]> {
    try {
      const cached = await this.cache.getMakes(year);
      if (cached) {
        logger.debug('Makes retrieved from cache', { year });
        return cached;
      }

      const makes = await this.repository.getMakes(pool, year);
      await this.cache.setMakes(year, makes);
      logger.debug('Makes retrieved from database and cached', { year, count: makes.length });
      return makes;
    } catch (error) {
      logger.error('Service error: getMakes', { error, year });
      throw error;
    }
  }

  /**
   * Get models for a year and make with caching
   */
  async getModels(pool: Pool, year: number, make: string): Promise<string[]> {
    try {
      const cached = await this.cache.getModels(year, make);
      if (cached) {
        logger.debug('Models retrieved from cache', { year, make });
        return cached;
      }

      const models = await this.repository.getModels(pool, year, make);
      await this.cache.setModels(year, make, models);
      logger.debug('Models retrieved from database and cached', { year, make, count: models.length });
      return models;
    } catch (error) {
      logger.error('Service error: getModels', { error, year, make });
      throw error;
    }
  }

  /**
   * Get trims for a year, make, and model with caching
   */
  async getTrims(pool: Pool, year: number, make: string, model: string): Promise<string[]> {
    try {
      const cached = await this.cache.getTrims(year, make, model);
      if (cached) {
        logger.debug('Trims retrieved from cache', { year, make, model });
        return cached;
      }

      const trims = await this.repository.getTrims(pool, year, make, model);
      await this.cache.setTrims(year, make, model, trims);
      logger.debug('Trims retrieved from database and cached', { year, make, model, count: trims.length });
      return trims;
    } catch (error) {
      logger.error('Service error: getTrims', { error, year, make, model });
      throw error;
    }
  }

  /**
   * Get engines for a year, make, model, and trim with caching
   */
  async getEngines(pool: Pool, year: number, make: string, model: string, trim: string): Promise<string[]> {
    try {
      const cached = await this.cache.getEngines(year, make, model, trim);
      if (cached) {
        logger.debug('Engines retrieved from cache', { year, make, model, trim });
        return cached;
      }

      const engines = await this.repository.getEngines(pool, year, make, model, trim);
      await this.cache.setEngines(year, make, model, trim, engines);
      logger.debug('Engines retrieved from database and cached', { year, make, model, trim, count: engines.length });
      return engines;
    } catch (error) {
      logger.error('Service error: getEngines', { error, year, make, model, trim });
      throw error;
    }
  }

  /**
   * Get transmissions for a year, make, model, and trim with caching
   */
  async getTransmissionsForTrim(pool: Pool, year: number, make: string, model: string, trim: string): Promise<string[]> {
    try {
      const cached = await this.cache.getTransmissionsForTrim(year, make, model, trim);
      if (cached) {
        logger.debug('Transmissions retrieved from cache', { year, make, model, trim });
        return cached;
      }

      const transmissions = await this.repository.getTransmissionsForTrim(pool, year, make, model, trim);
      await this.cache.setTransmissionsForTrim(year, make, model, trim, transmissions);
      logger.debug('Transmissions retrieved from database and cached', { year, make, model, trim, count: transmissions.length });
      return transmissions;
    } catch (error) {
      logger.error('Service error: getTransmissionsForTrim', { error, year, make, model, trim });
      throw error;
    }
  }

  async getTransmissionsForTrimAndEngine(
    pool: Pool,
    year: number,
    make: string,
    model: string,
    trim: string,
    engine: string
  ): Promise<string[]> {
    try {
      const cached = await this.cache.getTransmissionsForTrimAndEngine(year, make, model, trim, engine);
      if (cached) {
        logger.debug('Transmissions (engine-filtered) retrieved from cache', { year, make, model, trim, engine });
        return cached;
      }

      const transmissions = await this.repository.getTransmissionsForTrimAndEngine(pool, year, make, model, trim, engine);
      await this.cache.setTransmissionsForTrimAndEngine(year, make, model, trim, engine, transmissions);
      logger.debug('Transmissions (engine-filtered) retrieved from database and cached', { year, make, model, trim, engine, count: transmissions.length });
      return transmissions;
    } catch (error) {
      logger.error('Service error: getTransmissionsForTrimAndEngine', { error, year, make, model, trim, engine });
      throw error;
    }
  }

  async getEnginesForTrimAndTransmission(
    pool: Pool,
    year: number,
    make: string,
    model: string,
    trim: string,
    transmission: string
  ): Promise<string[]> {
    try {
      const cached = await this.cache.getEnginesForTrimAndTransmission(year, make, model, trim, transmission);
      if (cached) {
        logger.debug('Engines (transmission-filtered) retrieved from cache', { year, make, model, trim, transmission });
        return cached;
      }

      const engines = await this.repository.getEnginesForTrimAndTransmission(pool, year, make, model, trim, transmission);
      await this.cache.setEnginesForTrimAndTransmission(year, make, model, trim, transmission, engines);
      logger.debug('Engines (transmission-filtered) retrieved from database and cached', { year, make, model, trim, transmission, count: engines.length });
      return engines;
    } catch (error) {
      logger.error('Service error: getEnginesForTrimAndTransmission', { error, year, make, model, trim, transmission });
      throw error;
    }
  }

  async getOptions(
    pool: Pool,
    year: number,
    make: string,
    model: string,
    trim: string,
    engine?: string,
    transmission?: string
  ): Promise<{ engines: string[]; transmissions: string[] }> {
    const [engines, transmissions] = await Promise.all([
      transmission
        ? this.getEnginesForTrimAndTransmission(pool, year, make, model, trim, transmission)
        : this.getEngines(pool, year, make, model, trim),
      engine
        ? this.getTransmissionsForTrimAndEngine(pool, year, make, model, trim, engine)
        : this.getTransmissionsForTrim(pool, year, make, model, trim)
    ]);

    return { engines, transmissions };
  }
}
