/**
 * FuelLog Service
 * ERP Construccion - Modulo Activos (MAE-015)
 *
 * Logica de negocio para registro de combustible y calculo de rendimiento.
 */

import { Repository, DataSource } from 'typeorm';
import { FuelLog } from '../entities/fuel-log.entity';
import { Asset } from '../entities/asset.entity';

// DTOs
export interface CreateFuelLogDto {
  assetId: string;
  logDate: Date;
  logTime?: string;
  projectId?: string;
  location?: string;
  fuelType: string;
  quantityLiters: number;
  unitPrice: number;
  odometerReading?: number;
  hoursReading?: number;
  vendorName?: string;
  invoiceNumber?: string;
  operatorId?: string;
  operatorName?: string;
  notes?: string;
}

export interface FuelLogFilters {
  assetId?: string;
  projectId?: string;
  fuelType?: string;
  fromDate?: Date;
  toDate?: Date;
}

export interface FuelStatistics {
  totalLiters: number;
  totalCost: number;
  avgLitersPer100km: number;
  avgLitersPerHour: number;
  logsCount: number;
}

export class FuelLogService {
  private fuelLogRepository: Repository<FuelLog>;
  private assetRepository: Repository<Asset>;

  constructor(dataSource: DataSource) {
    this.fuelLogRepository = dataSource.getRepository(FuelLog);
    this.assetRepository = dataSource.getRepository(Asset);
  }

  /**
   * Create a new fuel log entry
   */
  async create(tenantId: string, dto: CreateFuelLogDto, userId?: string): Promise<FuelLog> {
    // Calculate total cost
    const totalCost = dto.quantityLiters * dto.unitPrice;

    // Get last fuel log for efficiency calculation
    const lastLog = await this.fuelLogRepository.findOne({
      where: { tenantId, assetId: dto.assetId },
      order: { logDate: 'DESC', createdAt: 'DESC' },
    });

    let kilometersSinceLast: number | undefined;
    let hoursSinceLast: number | undefined;
    let litersPer100km: number | undefined;
    let litersPerHour: number | undefined;

    if (lastLog) {
      if (dto.odometerReading && lastLog.odometerReading) {
        kilometersSinceLast = dto.odometerReading - Number(lastLog.odometerReading);
        if (kilometersSinceLast > 0 && dto.quantityLiters > 0) {
          litersPer100km = (dto.quantityLiters / kilometersSinceLast) * 100;
        }
      }

      if (dto.hoursReading && lastLog.hoursReading) {
        hoursSinceLast = dto.hoursReading - Number(lastLog.hoursReading);
        if (hoursSinceLast > 0 && dto.quantityLiters > 0) {
          litersPerHour = dto.quantityLiters / hoursSinceLast;
        }
      }
    }

    const fuelLog = this.fuelLogRepository.create({
      tenantId,
      assetId: dto.assetId,
      logDate: dto.logDate,
      logTime: dto.logTime,
      projectId: dto.projectId,
      location: dto.location,
      fuelType: dto.fuelType,
      quantityLiters: dto.quantityLiters,
      unitPrice: dto.unitPrice,
      totalCost,
      odometerReading: dto.odometerReading,
      hoursReading: dto.hoursReading,
      kilometersSinceLast,
      hoursSinceLast,
      litersPer100km,
      litersPerHour,
      vendorName: dto.vendorName,
      invoiceNumber: dto.invoiceNumber,
      operatorId: dto.operatorId,
      operatorName: dto.operatorName,
      notes: dto.notes,
      createdBy: userId,
    });

    const savedLog = await this.fuelLogRepository.save(fuelLog);

    // Update asset current readings if provided
    if (dto.odometerReading || dto.hoursReading) {
      await this.assetRepository.update(
        { id: dto.assetId, tenantId },
        {
          currentKilometers: dto.odometerReading,
          currentHours: dto.hoursReading,
          lastUsageUpdate: new Date(),
        }
      );
    }

    return savedLog;
  }

  /**
   * Find fuel log by ID
   */
  async findById(tenantId: string, id: string): Promise<FuelLog | null> {
    return this.fuelLogRepository.findOne({
      where: { id, tenantId },
      relations: ['asset'],
    });
  }

  /**
   * List fuel logs with filters
   */
  async findAll(
    tenantId: string,
    filters: FuelLogFilters = {},
    pagination = { page: 1, limit: 20 }
  ) {
    const queryBuilder = this.fuelLogRepository.createQueryBuilder('fl')
      .leftJoinAndSelect('fl.asset', 'asset')
      .where('fl.tenant_id = :tenantId', { tenantId });

    if (filters.assetId) {
      queryBuilder.andWhere('fl.asset_id = :assetId', { assetId: filters.assetId });
    }
    if (filters.projectId) {
      queryBuilder.andWhere('fl.project_id = :projectId', { projectId: filters.projectId });
    }
    if (filters.fuelType) {
      queryBuilder.andWhere('fl.fuel_type = :fuelType', { fuelType: filters.fuelType });
    }
    if (filters.fromDate) {
      queryBuilder.andWhere('fl.log_date >= :fromDate', { fromDate: filters.fromDate });
    }
    if (filters.toDate) {
      queryBuilder.andWhere('fl.log_date <= :toDate', { toDate: filters.toDate });
    }

    const skip = (pagination.page - 1) * pagination.limit;

    const [data, total] = await queryBuilder
      .orderBy('fl.log_date', 'DESC')
      .addOrderBy('fl.created_at', 'DESC')
      .skip(skip)
      .take(pagination.limit)
      .getManyAndCount();

    return {
      data,
      total,
      page: pagination.page,
      limit: pagination.limit,
      totalPages: Math.ceil(total / pagination.limit),
    };
  }

  /**
   * Get fuel statistics for an asset
   */
  async getAssetStatistics(
    tenantId: string,
    assetId: string,
    fromDate?: Date,
    toDate?: Date
  ): Promise<FuelStatistics> {
    const queryBuilder = this.fuelLogRepository.createQueryBuilder('fl')
      .where('fl.tenant_id = :tenantId', { tenantId })
      .andWhere('fl.asset_id = :assetId', { assetId });

    if (fromDate) {
      queryBuilder.andWhere('fl.log_date >= :fromDate', { fromDate });
    }
    if (toDate) {
      queryBuilder.andWhere('fl.log_date <= :toDate', { toDate });
    }

    const result = await queryBuilder
      .select('SUM(fl.quantity_liters)', 'totalLiters')
      .addSelect('SUM(fl.total_cost)', 'totalCost')
      .addSelect('AVG(fl.liters_per_100km)', 'avgLitersPer100km')
      .addSelect('AVG(fl.liters_per_hour)', 'avgLitersPerHour')
      .addSelect('COUNT(*)', 'logsCount')
      .getRawOne();

    return {
      totalLiters: parseFloat(result?.totalLiters) || 0,
      totalCost: parseFloat(result?.totalCost) || 0,
      avgLitersPer100km: parseFloat(result?.avgLitersPer100km) || 0,
      avgLitersPerHour: parseFloat(result?.avgLitersPerHour) || 0,
      logsCount: parseInt(result?.logsCount, 10) || 0,
    };
  }

  /**
   * Delete fuel log entry
   */
  async delete(tenantId: string, id: string): Promise<boolean> {
    const result = await this.fuelLogRepository.delete({ id, tenantId });
    return (result.affected ?? 0) > 0;
  }
}
