import { Injectable } from "@nestjs/common"
import { InjectRepository } from "@nestjs/typeorm"
import { Repository } from "typeorm"
import { BaseAbstractRepository } from "../../../common/repository/base.repository"
import { FleetManagement } from "../entities/fleet-management.entity"
import { FindAllFleetManagementDto } from "../dto/find-all-fleet-management.dto"

@Injectable()
export class FleetManagementRepository extends BaseAbstractRepository<FleetManagement> {
  constructor(
    @InjectRepository(FleetManagement)
    private readonly fleetManagementRepository: Repository<FleetManagement>,
  ) {
    super(fleetManagementRepository)
  }

  async findAllWithDriverDetails(query: FindAllFleetManagementDto) {
    const {
      limit,
      skip,
      sortBy,
      sortOrder,
      search,
      vehicle_manufacture_id,
      vehicle_model_id,
      vehicle_status_id,
      vehicle_type_id,
      vehicle_ownership,
      assigned_dispatcher_id,
    } = query

    const validSortColumns = [
      "id",
      "car_code",
      "year",
      "color",
      "registration_number",
      "vin_number",
      "odo_reader",
      "vehicle_status_id",
      "created_at",
      "updated_at",
    ]

    let sortColumn = "fleet.created_at"
    const order: "ASC" | "DESC" = sortOrder === "ASC" ? "ASC" : "DESC"

    if (sortBy && validSortColumns.includes(sortBy)) {
      sortColumn = `fleet.${sortBy}`
    }

    const qb = this.fleetManagementRepository
      .createQueryBuilder("fleet")
      .leftJoinAndSelect("fleet.vehicle_manufacture", "vehicleManufacture")
      .leftJoinAndSelect("fleet.vehicleModel", "vehicleModel")
      .leftJoinAndSelect("fleet.vehicle_type", "vehicleType")
      .leftJoinAndSelect("fleet.vehicle_status", "vehicleStatus")
      .leftJoinAndSelect("fleet.assignedDriver", "assignedDriver")
      .leftJoinAndSelect("fleet.assigned_dispatcher", "assignedDispatcher")
      .leftJoinAndSelect("assignedDriver.reporting_to", "reportingTo")
      .leftJoinAndSelect("fleet.state_details", "state")
      .leftJoinAndSelect("fleet.vehicle_location", "vehicleLocation")
      .leftJoinAndSelect("fleet.vehicle_city_location", "vehicleCityLocation")
      .leftJoinAndSelect("fleet.vehicleInsurances", "vehicleInsurances")
      .leftJoinAndSelect("fleet.vehicleMaintenances", "vehicleMaintenances")

    // Add select columns explicitly
    qb.select([
      "fleet.id",
      "fleet.car_code",
      "fleet.year",
      "fleet.color",
      "fleet.passenger_capacity",
      "fleet.registration_number",
      "fleet.registration_start_date",
      "fleet.registration_expiry_date",
      "fleet.vin_number",
      "fleet.odo_reader",
      "fleet.unit",
      "fleet.vehicle_description",
      "fleet.vehicle_ownership",
      "fleet.created_at",
      "fleet.updated_at",

      "vehicleManufacture.id",
      "vehicleManufacture.name",

      "vehicleModel.id",
      "vehicleModel.name",

      "vehicleType.id",
      "vehicleType.name",

      "vehicleStatus.id",
      "vehicleStatus.name",

      "assignedDriver.id",
      "assignedDriver.first_name",
      "assignedDriver.last_name",
      "assignedDriver.email",
      "assignedDriver.country_code",
      "assignedDriver.phone_number",

      "reportingTo.id",
      "reportingTo.first_name",
      "reportingTo.last_name",
      "reportingTo.email",
      "reportingTo.phone_number",

      "assignedDispatcher.id",
      "assignedDispatcher.first_name",
      "assignedDispatcher.last_name",
      "assignedDispatcher.email",
      "assignedDispatcher.country_code",
      "assignedDispatcher.phone_number",

      "state.id",
      "state.name",

      "vehicleLocation.id",
      "vehicleLocation.name",

      "vehicleCityLocation.id",
      "vehicleCityLocation.name",

      "vehicleInsurances.id",
      "vehicleInsurances.end_date",

      "vehicleMaintenances.id",
      "vehicleMaintenances.next_scheduled_maintenance",
    ])

    if (search) {
      qb.andWhere(
        "(fleet.car_code ILIKE :search OR fleet.registration_number ILIKE :search OR fleet.vin_number ILIKE :search)",
        { search: `%${search}%` },
      )
    }

    if (vehicle_manufacture_id) {
      qb.andWhere("fleet.vehicle_manufacture_id = :vehicle_manufacture_id", {
        vehicle_manufacture_id,
      })
    }

    if (vehicle_type_id) {
      qb.andWhere("fleet.vehicle_type_id = :vehicle_type_id", {
        vehicle_type_id,
      })
    }

    if (vehicle_model_id) {
      qb.andWhere("fleet.vehicle_model_id = :vehicle_model_id", {
        vehicle_model_id,
      })
    }

    if (vehicle_status_id) {
      qb.andWhere("fleet.vehicle_status_id = :vehicle_status_id", {
        vehicle_status_id,
      })
    }

    if (vehicle_ownership) {
      qb.andWhere("fleet.vehicle_ownership = :vehicle_ownership", {
        vehicle_ownership,
      })
    }

    if (assigned_dispatcher_id) {
      qb.andWhere("fleet.assigned_dispatcher_id = :assigned_dispatcher_id", {
        assigned_dispatcher_id,
      })
    }

    qb.orderBy(sortColumn, order).take(limit).skip(skip)

    const [data, count] = await qb.getManyAndCount()

    return { data, count }
  }
}
