/**
 * @ai-summary Data access layer for vehicles
 * @ai-context All database operations, no business logic
 */

import { Pool } from 'pg';
import { Vehicle, CreateVehicleRequest, VehicleImageMeta, CostInterval } from '../domain/vehicles.types';

export class VehiclesRepository {
  constructor(private pool: Pool) {}

  async create(data: CreateVehicleRequest & { userId: string, make?: string, model?: string, year?: number }): Promise<Vehicle> {
    const query = `
      INSERT INTO vehicles (
        user_id, vin, make, model, year,
        engine, transmission, trim_level, drive_type, fuel_type,
        nickname, color, license_plate, odometer_reading,
        purchase_price, purchase_date, insurance_cost, insurance_interval,
        registration_cost, registration_interval, tco_enabled
      )
      VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21)
      RETURNING *
    `;

    const values = [
      data.userId,
      (data.vin && data.vin.trim().length > 0) ? data.vin.trim() : null,
      data.make,
      data.model,
      data.year,
      data.engine,
      data.transmission,
      data.trimLevel,
      data.driveType,
      data.fuelType,
      data.nickname,
      data.color,
      data.licensePlate,
      data.odometerReading || 0,
      data.purchasePrice ?? null,
      data.purchaseDate ?? null,
      data.insuranceCost ?? null,
      data.insuranceInterval ?? null,
      data.registrationCost ?? null,
      data.registrationInterval ?? null,
      data.tcoEnabled ?? false
    ];

    const result = await this.pool.query(query, values);
    return this.mapRow(result.rows[0]);
  }

  async findByUserId(userId: string): Promise<Vehicle[]> {
    const query = `
      SELECT * FROM vehicles
      WHERE user_id = $1 AND is_active = true
      ORDER BY created_at DESC
    `;

    const result = await this.pool.query(query, [userId]);
    return result.rows.map(row => this.mapRow(row));
  }

  async countByUserId(userId: string): Promise<number> {
    const query = `
      SELECT COUNT(*) as count FROM vehicles
      WHERE user_id = $1 AND is_active = true
    `;

    const result = await this.pool.query(query, [userId]);
    return parseInt(result.rows[0].count, 10);
  }

  async findById(id: string): Promise<Vehicle | null> {
    const query = 'SELECT * FROM vehicles WHERE id = $1';
    const result = await this.pool.query(query, [id]);
    
    if (result.rows.length === 0) {
      return null;
    }
    
    return this.mapRow(result.rows[0]);
  }

  async findByUserAndVIN(userId: string, vin: string): Promise<Vehicle | null> {
    const query = 'SELECT * FROM vehicles WHERE user_id = $1 AND vin = $2';
    const result = await this.pool.query(query, [userId, vin]);
    
    if (result.rows.length === 0) {
      return null;
    }
    
    return this.mapRow(result.rows[0]);
  }

  async update(id: string, data: Partial<Vehicle>): Promise<Vehicle | null> {
    const fields = [];
    const values = [];
    let paramCount = 1;

    // Build dynamic update query
    if (data.vin !== undefined) {
      fields.push(`vin = $${paramCount++}`);
      values.push(data.vin && data.vin.trim().length > 0 ? data.vin.trim() : null);
    }
    if (data.year !== undefined) {
      fields.push(`year = $${paramCount++}`);
      values.push(data.year);
    }
    if (data.make !== undefined) {
      fields.push(`make = $${paramCount++}`);
      values.push(data.make);
    }
    if (data.model !== undefined) {
      fields.push(`model = $${paramCount++}`);
      values.push(data.model);
    }
    if (data.engine !== undefined) {
      fields.push(`engine = $${paramCount++}`);
      values.push(data.engine);
    }
    if (data.transmission !== undefined) {
      fields.push(`transmission = $${paramCount++}`);
      values.push(data.transmission);
    }
    if (data.trimLevel !== undefined) {
      fields.push(`trim_level = $${paramCount++}`);
      values.push(data.trimLevel);
    }
    if (data.driveType !== undefined) {
      fields.push(`drive_type = $${paramCount++}`);
      values.push(data.driveType);
    }
    if (data.fuelType !== undefined) {
      fields.push(`fuel_type = $${paramCount++}`);
      values.push(data.fuelType);
    }
    if (data.nickname !== undefined) {
      fields.push(`nickname = $${paramCount++}`);
      values.push(data.nickname);
    }
    if (data.color !== undefined) {
      fields.push(`color = $${paramCount++}`);
      values.push(data.color);
    }
    if (data.licensePlate !== undefined) {
      fields.push(`license_plate = $${paramCount++}`);
      values.push(data.licensePlate);
    }
    if (data.odometerReading !== undefined) {
      fields.push(`odometer_reading = $${paramCount++}`);
      values.push(data.odometerReading);
    }
    // TCO fields
    if (data.purchasePrice !== undefined) {
      fields.push(`purchase_price = $${paramCount++}`);
      values.push(data.purchasePrice);
    }
    if (data.purchaseDate !== undefined) {
      fields.push(`purchase_date = $${paramCount++}`);
      values.push(data.purchaseDate);
    }
    if (data.insuranceCost !== undefined) {
      fields.push(`insurance_cost = $${paramCount++}`);
      values.push(data.insuranceCost);
    }
    if (data.insuranceInterval !== undefined) {
      fields.push(`insurance_interval = $${paramCount++}`);
      values.push(data.insuranceInterval);
    }
    if (data.registrationCost !== undefined) {
      fields.push(`registration_cost = $${paramCount++}`);
      values.push(data.registrationCost);
    }
    if (data.registrationInterval !== undefined) {
      fields.push(`registration_interval = $${paramCount++}`);
      values.push(data.registrationInterval);
    }
    if (data.tcoEnabled !== undefined) {
      fields.push(`tco_enabled = $${paramCount++}`);
      values.push(data.tcoEnabled);
    }

    if (fields.length === 0) {
      return this.findById(id);
    }

    values.push(id);
    const query = `
      UPDATE vehicles
      SET ${fields.join(', ')}
      WHERE id = $${paramCount}
      RETURNING *
    `;

    const result = await this.pool.query(query, values);
    
    if (result.rows.length === 0) {
      return null;
    }
    
    return this.mapRow(result.rows[0]);
  }

  async batchInsert(
    vehicles: Array<CreateVehicleRequest & { userId: string, make?: string, model?: string, year?: number }>,
    client?: any
  ): Promise<Vehicle[]> {
    if (vehicles.length === 0) {
      return [];
    }

    // Multi-value INSERT for performance (avoids N round-trips)
    const queryClient = client || this.pool;
    const placeholders: string[] = [];
    const values: any[] = [];
    let paramCount = 1;

    vehicles.forEach((vehicle) => {
      const vehicleParams = [
        vehicle.userId,
        (vehicle.vin && vehicle.vin.trim().length > 0) ? vehicle.vin.trim() : null,
        vehicle.make,
        vehicle.model,
        vehicle.year,
        vehicle.engine,
        vehicle.transmission,
        vehicle.trimLevel,
        vehicle.driveType,
        vehicle.fuelType,
        vehicle.nickname,
        vehicle.color,
        vehicle.licensePlate,
        vehicle.odometerReading || 0,
        vehicle.purchasePrice ?? null,
        vehicle.purchaseDate ?? null,
        vehicle.insuranceCost ?? null,
        vehicle.insuranceInterval ?? null,
        vehicle.registrationCost ?? null,
        vehicle.registrationInterval ?? null,
        vehicle.tcoEnabled ?? false
      ];

      const placeholder = `($${paramCount++}, $${paramCount++}, $${paramCount++}, $${paramCount++}, $${paramCount++}, $${paramCount++}, $${paramCount++}, $${paramCount++}, $${paramCount++}, $${paramCount++}, $${paramCount++}, $${paramCount++}, $${paramCount++}, $${paramCount++}, $${paramCount++}, $${paramCount++}, $${paramCount++}, $${paramCount++}, $${paramCount++}, $${paramCount++}, $${paramCount++})`;
      placeholders.push(placeholder);
      values.push(...vehicleParams);
    });

    const query = `
      INSERT INTO vehicles (
        user_id, vin, make, model, year,
        engine, transmission, trim_level, drive_type, fuel_type,
        nickname, color, license_plate, odometer_reading,
        purchase_price, purchase_date, insurance_cost, insurance_interval,
        registration_cost, registration_interval, tco_enabled
      )
      VALUES ${placeholders.join(', ')}
      RETURNING *
    `;

    const result = await queryClient.query(query, values);
    return result.rows.map((row: any) => this.mapRow(row));
  }

  async softDelete(id: string): Promise<boolean> {
    const query = `
      UPDATE vehicles
      SET is_active = false, deleted_at = NOW()
      WHERE id = $1
    `;

    const result = await this.pool.query(query, [id]);
    return (result.rowCount ?? 0) > 0;
  }

  async updateImageMeta(id: string, userId: string, meta: VehicleImageMeta | null): Promise<Vehicle | null> {
    if (meta === null) {
      const query = `
        UPDATE vehicles SET
          image_storage_bucket = NULL,
          image_storage_key = NULL,
          image_file_name = NULL,
          image_content_type = NULL,
          image_file_size = NULL,
          updated_at = NOW()
        WHERE id = $1 AND user_id = $2
        RETURNING *
      `;
      const result = await this.pool.query(query, [id, userId]);
      return result.rows[0] ? this.mapRow(result.rows[0]) : null;
    }

    const query = `
      UPDATE vehicles SET
        image_storage_bucket = $1,
        image_storage_key = $2,
        image_file_name = $3,
        image_content_type = $4,
        image_file_size = $5,
        updated_at = NOW()
      WHERE id = $6 AND user_id = $7
      RETURNING *
    `;
    const result = await this.pool.query(query, [
      meta.imageStorageBucket,
      meta.imageStorageKey,
      meta.imageFileName,
      meta.imageContentType,
      meta.imageFileSize,
      id,
      userId
    ]);
    return result.rows[0] ? this.mapRow(result.rows[0]) : null;
  }

  private mapRow(row: any): Vehicle {
    return {
      id: row.id,
      userId: row.user_id,
      vin: row.vin,
      make: row.make,
      model: row.model,
      year: row.year,
      engine: row.engine,
      transmission: row.transmission,
      trimLevel: row.trim_level,
      driveType: row.drive_type,
      fuelType: row.fuel_type,
      nickname: row.nickname,
      color: row.color,
      licensePlate: row.license_plate,
      odometerReading: row.odometer_reading,
      isActive: row.is_active,
      deletedAt: row.deleted_at,
      createdAt: row.created_at,
      updatedAt: row.updated_at,
      imageStorageBucket: row.image_storage_bucket,
      imageStorageKey: row.image_storage_key,
      imageFileName: row.image_file_name,
      imageContentType: row.image_content_type,
      imageFileSize: row.image_file_size,
      // TCO fields
      purchasePrice: row.purchase_price ? Number(row.purchase_price) : undefined,
      purchaseDate: row.purchase_date,
      insuranceCost: row.insurance_cost ? Number(row.insurance_cost) : undefined,
      insuranceInterval: row.insurance_interval as CostInterval | undefined,
      registrationCost: row.registration_cost ? Number(row.registration_cost) : undefined,
      registrationInterval: row.registration_interval as CostInterval | undefined,
      tcoEnabled: row.tco_enabled,
    };
  }
}
