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 { CreateVehicleInsuranceDto } from "../dto/create-vehicle-insurance.dto"
import { VehicleInsuranceRepository } from "../repositories/vehicle-insurance.repository"
import { ConfigService } from "@nestjs/config"
import { errorMessage, successMessage } from "src/utils/helpers"
import { FindAllVehicleInsuranceDto } from "../dto/find-all-vehicle-insurance.dto"
import { isEmpty } from "class-validator"
import { UpdateVehicleInsuranceDto } from "../dto/update-vehicle-insurance.dto"
import { VehicleInsurance } from "../entities/vehicle-insurance.entity"

@Injectable()
export class VehicleInsuranceService {
  constructor(
    private readonly vehicleInsuranceRepository: VehicleInsuranceRepository,
    private readonly configService: ConfigService,
  ) {}

  async checkVehicleInsuranceExists(policy_number: string, excludeId?: number) {
    const whereLikeCondition = {
      policy_number: policy_number,
    }

    const whereCondition: any = {}
    if (excludeId) {
      whereCondition["id"] = {
        not: excludeId,
      }
    }

    const vehicleModel = await this.vehicleInsuranceRepository.getByParams({
      where: whereCondition,
      whereLower: whereLikeCondition,
      findOne: true,
    })

    return !isEmpty(vehicleModel)
  }

  async create(
    createVehicleInsuranceDto: CreateVehicleInsuranceDto,
    insuranceFile?: Express.Multer.File,
  ) {
    try {
      // const existingInsurance = await this.checkVehicleInsuranceExists(
      //   createVehicleInsuranceDto.policy_number,
      // )

      // if (existingInsurance) {
      //   return failureResponse(code.VALIDATION, messageKey.already_exist)
      // }

      // Process and save document_file path
      if (insuranceFile) {
        const relativePath = insuranceFile.path
          .replace(/\\/g, "/")
          .replace(/^public\//, "")

        createVehicleInsuranceDto.document_file = relativePath
      }

      if (createVehicleInsuranceDto.is_active_policy === "true") {
        createVehicleInsuranceDto.status = "active"
      } else {
        createVehicleInsuranceDto.status = "inactive"
      }

      const vehicleInsuranceEntity = new VehicleInsurance()
      vehicleInsuranceEntity.is_active_policy =
        createVehicleInsuranceDto?.is_active_policy === "true"
      Object.assign(vehicleInsuranceEntity, createVehicleInsuranceDto)

      const savedInsurance = await this.vehicleInsuranceRepository.save(
        vehicleInsuranceEntity,
      )

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

  async findAll(query: FindAllVehicleInsuranceDto) {
    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",
      "policy_number",
      "insurance_provider",
      "coverage_type",
      "start_date",
      "end_date",
      "status",
      "is_active_policy",
    ] 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 = {
        policy_number: search,
        insurance_provider: search,
        coverage_type: search,
        status: search,
      }
    }

    const vehicleInsurances =
      await this.vehicleInsuranceRepository.getByParams(params)

    return successResponse(
      code.SUCCESS,
      successMessage(messageKey.data_retrieve, {
        ":data": "Vehicle Insurances",
      }),
      vehicleInsurances,
    )
  }

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

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

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

  async update(
    id: number,
    updateVehicleInsuranceDto: UpdateVehicleInsuranceDto,
    insuranceFile?: Express.Multer.File,
  ) {
    try {
      const vehicleInsurance: any =
        await this.vehicleInsuranceRepository.getByParams({
          where: { id },
          findOne: true,
        })

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

      // const existingInsurance = await this.checkVehicleInsuranceExists(
      //   updateVehicleInsuranceDto.policy_number,
      //   id,
      // )

      // if (existingInsurance) {
      //   return failureResponse(code.VALIDATION, messageKey.already_exist)
      // }

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

        updateVehicleInsuranceDto.document_file = relativePath
      }

      if (updateVehicleInsuranceDto.is_active_policy === "true") {
        updateVehicleInsuranceDto.status = "active"
      } else {
        updateVehicleInsuranceDto.status = "inactive"
      }

      await this.vehicleInsuranceRepository.save({
        id,
        ...updateVehicleInsuranceDto,
        is_active_policy: updateVehicleInsuranceDto.is_active_policy === "true",
      })

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

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

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

      await this.vehicleInsuranceRepository.remove({ id })

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

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

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

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

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