import { Injectable } from "@nestjs/common"
import { failureResponse, successResponse } from "src/common/response/response"
import { code } from "src/common/response/response.code"
import { messageKey } from "src/constants/message-keys"
import { ConfigService } from "@nestjs/config"
import { isEmpty } from "class-validator"
import { errorMessage, successMessage } from "src/utils/helpers"
import { CreateVehicleMaintenanceDto } from "../dto/create-vehicle-maintenance.dto"
import { UpdateVehicleMaintenanceDto } from "../dto/update-vehicle-maintenance.dto"
import { FindAllVehicleMaintenanceDto } from "../dto/find-all-vehicle-maintenance.dto"
import { VehicleMaintenanceRepository } from "../repositories/vehicle-maintenance.repository"

@Injectable()
export class VehicleMaintenanceService {
  constructor(
    private readonly vehicleMaintenanceRepository: VehicleMaintenanceRepository,
    private readonly configService: ConfigService,
  ) {}

  async create(
    createDto: CreateVehicleMaintenanceDto,
    maintenanceFile?: Express.Multer.File,
  ) {
    try {
      // Process and save document_file path
      if (maintenanceFile) {
        const relativePath = maintenanceFile.path
          .replace(/\\/g, "/")
          .replace(/^public\//, "")

        createDto.document_file = relativePath
      }

      if (!createDto.status) {
        createDto.status = "scheduled"
      }

      const saved = await this.vehicleMaintenanceRepository.save(createDto)

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.data_add, {
          ":data": "Vehicle Maintenance",
        }),
        saved,
      )
    } catch (error) {
      return failureResponse(code.ERROR, messageKey.something_went_wrong)
    }
  }

  async findAll(query: FindAllVehicleMaintenanceDto) {
    try {
      const defaultPagination = {
        take: this.configService.get("APP.pagination.take"),
        skip: this.configService.get("APP.pagination.skip"),
      }

      const limit = query.limit || defaultPagination.take
      const skip = query.skip || defaultPagination.skip

      const filters: any = {}

      if (query.fleet_id) {
        filters["fleet_id"] = query.fleet_id
      }

      const validSortColumns = [
        "created_at",
        "updated_at",
        "maintenance_type",
        "maintenance_date",
        "cost",
        "performed_by",
        "status",
        "next_scheduled_maintenance",
      ] as const

      const sortBy =
        (query.sortBy as (typeof validSortColumns)[number]) || "created_at"
      const sortOrder = query.sortOrder || "DESC"

      const params: any = {
        take: limit,
        skip: skip,
        where: filters,
        orderBy: {
          [validSortColumns.includes(sortBy) ? sortBy : "created_at"]:
            sortOrder,
        },
      }

      if (query.search) {
        const search = query.search
        params.search = {
          maintenance_type: search,
          description: search,
          performed_by: search,
          status: search,
        }
      }

      const maintenances =
        await this.vehicleMaintenanceRepository.getByParams(params)

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.data_retrieve, {
          ":data": "Vehicle Maintenances",
        }),
        maintenances,
      )
    } catch (error) {
      return failureResponse(code.ERROR, messageKey.something_went_wrong)
    }
  }

  async findOne(id: number) {
    try {
      const maintenance = await this.vehicleMaintenanceRepository.getByParams({
        where: { id },
        findOne: true,
      })

      if (isEmpty(maintenance)) {
        return failureResponse(
          code.DATA_NOT_FOUND,
          errorMessage(messageKey.data_not_found, {
            ":data": "Vehicle Maintenance",
          }),
        )
      }

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.data_retrieve, {
          ":data": "Vehicle Maintenance",
        }),
        maintenance,
      )
    } catch (error) {
      return failureResponse(code.ERROR, messageKey.something_went_wrong)
    }
  }

  async update(
    id: number,
    updateDto: UpdateVehicleMaintenanceDto,
    maintenanceFile?: Express.Multer.File,
  ) {
    try {
      const maintenance = await this.vehicleMaintenanceRepository.getByParams({
        where: { id },
        findOne: true,
      })

      if (isEmpty(maintenance)) {
        return failureResponse(
          code.DATA_NOT_FOUND,
          errorMessage(messageKey.data_not_found, {
            ":data": "Vehicle Maintenance",
          }),
        )
      }

      if (maintenanceFile) {
        const relativePath = maintenanceFile.path
          .replace(/\\/g, "/")
          .replace(/^public\//, "")

        updateDto.document_file = relativePath
      }

      await this.vehicleMaintenanceRepository.save({
        id,
        ...updateDto,
      })

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.data_update, {
          ":data": "Vehicle Maintenance",
        }),
        maintenance,
      )
    } catch (error) {
      return failureResponse(code.ERROR, messageKey.something_went_wrong)
    }
  }

  async remove(id: number) {
    try {
      const maintenance = await this.vehicleMaintenanceRepository.getByParams({
        where: { id },
        findOne: true,
      })

      if (isEmpty(maintenance)) {
        return failureResponse(
          code.DATA_NOT_FOUND,
          errorMessage(messageKey.data_not_found, {
            ":data": "Vehicle Maintenance",
          }),
        )
      }

      await this.vehicleMaintenanceRepository.remove({ id })

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.data_removed, {
          ":data": "Vehicle Maintenance",
        }),
        maintenance,
      )
    } catch (error) {
      return failureResponse(code.ERROR, messageKey.something_went_wrong)
    }
  }

  async removeDocument(id: number) {
    try {
      const maintenance = await this.vehicleMaintenanceRepository.getByParams({
        where: { id },
        findOne: true,
      })

      if (isEmpty(maintenance)) {
        return failureResponse(
          code.DATA_NOT_FOUND,
          errorMessage(messageKey.data_not_found, {
            ":data": "Vehicle Maintenance",
          }),
        )
      }

      await this.vehicleMaintenanceRepository.save({
        id,
        document_file: null,
      })

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.data_removed, {
          ":data": "Vehicle Maintenance",
        }),
      )
    } catch (error) {
      return failureResponse(code.ERROR, messageKey.something_went_wrong)
    }
  }
}
