import { Injectable } from "@nestjs/common"
import {
  errorMessage,
  isEmpty,
  successMessage,
  validationMessage,
} from "src/utils/helpers"
import { failureResponse, successResponse } from "src/common/response/response"
import { code } from "src/common/response/response.code"
import { messageKey } from "src/constants/message-keys"
import { TripTypeRepository } from "../../trips/repositories/trip-type.repository"
import { ConfigService } from "@nestjs/config"
import { MeetAndGreetPricingRepository } from "../repositories/meet-greet-pricing.repository"
import { PricingPlanRepository } from "../../plans/repositories/plan.repository"
import { CreateMeetAndGreetPricingDto } from "../dto/create-meet-greet-pricing.dto"
import { MeetAndGreetPricing } from "../entities/meet-greet-pricing.entity"
import { UpdateMeetAndGreetPricingDto } from "../dto/update-meet-greet-pricing.dto"
import { MeetAndGreetPricingFilterDto } from "../dto/filter-meet-greet-pricing.dto"

@Injectable()
export class MeetAndGreetPricingService {
  constructor(
    private readonly meetAndGreetPricingRepository: MeetAndGreetPricingRepository,
    private readonly planRepository: PricingPlanRepository,
    private readonly tripTypeRepository: TripTypeRepository,
    private readonly configService: ConfigService,
  ) {}

  async create(createDto: CreateMeetAndGreetPricingDto) {
    const whereCondition: any = {
      plan_id: createDto.plan_id,
      service_type_id: createDto.service_type_id,
    }

    const isExist = await this.meetAndGreetPricingRepository.getByParams({
      where: whereCondition,
      findOne: true,
    })

    if (!isEmpty(isExist)) {
      return failureResponse(
        code.VALIDATION,
        validationMessage(messageKey.already_exist, {
          ":data": "Meet & Greet pricing",
        }),
      )
    }

    const isPlanExist = await this.planRepository.getByParams({
      where: { id: createDto.plan_id },
      findOne: true,
    })

    if (isEmpty(isPlanExist)) {
      return failureResponse(
        code.DATA_NOT_FOUND,
        errorMessage(messageKey.data_not_found, { ":data": "Plan" }),
      )
    }

    const isServiceTypeExist = await this.tripTypeRepository.getByParams({
      where: { id: createDto.service_type_id },
      findOne: true,
    })

    if (isEmpty(isServiceTypeExist)) {
      return failureResponse(
        code.DATA_NOT_FOUND,
        errorMessage(messageKey.data_not_found, { ":data": "Service Type" }),
      )
    }

    const meetAndGreetPricing = new MeetAndGreetPricing()
    Object.assign(meetAndGreetPricing, createDto)

    await this.meetAndGreetPricingRepository.save(meetAndGreetPricing)

    return successResponse(
      code.SUCCESS,
      successMessage(messageKey.data_add, { ":data": "Meet & Greet Pricing" }),
    )
  }

  async findAll(id: number, filterDto: MeetAndGreetPricingFilterDto) {
    const { search, service_type_id } = filterDto

    const queryParams: any = {
      // take: Number(limit) || defaultPagination.take,
      // skip: Number(skip) || defaultPagination.skip,
      orderBy: { created_at: "DESC" },
      where: { plan_id: id },
      relations: ["plan:id,name", "service_type:id,name"],
    }

    if (search) {
      queryParams.search = { service_type: search }
    }

    if (service_type_id) {
      queryParams.where.service_type_id = service_type_id
    }

    const meetAndGreetPricing =
      await this.meetAndGreetPricingRepository.getByParams(queryParams)

    return successResponse(
      code.SUCCESS,
      successMessage(messageKey.data_retrieve, {
        ":data": "Meet & Greet Pricing",
      }),
      meetAndGreetPricing,
    )
  }

  async findOne(id: number) {
    const record = await this.meetAndGreetPricingRepository.getByParams({
      where: { id },
      relations: ["plan:id,name", "service_type:id,name"],
      findOne: true,
    })

    if (isEmpty(record)) {
      return failureResponse(
        code.DATA_NOT_FOUND,
        errorMessage(messageKey.data_not_found, {
          ":data": "Meet & Greet Pricing",
        }),
      )
    }

    return successResponse(
      code.SUCCESS,
      successMessage(messageKey.data_retrieve, {
        ":data": "Meet & Greet Pricing",
      }),
      record,
    )
  }

  async update(id: number, updateDto: UpdateMeetAndGreetPricingDto) {
    const whereCondition: any = {
      plan_id: updateDto.plan_id,
      service_type_id: updateDto.service_type_id,
    }

    const isExist = await this.meetAndGreetPricingRepository.getByParams({
      where: whereCondition,
      whereNotIn: { id: [id] },
      findOne: true,
    })

    if (!isEmpty(isExist)) {
      return failureResponse(
        code.VALIDATION,
        validationMessage(messageKey.already_exist, {
          ":data": "Meet & Greet pricing",
        }),
      )
    }

    const isPlanExist = await this.planRepository.getByParams({
      where: { id: updateDto.plan_id },
      findOne: true,
    })

    if (isEmpty(isPlanExist)) {
      return failureResponse(
        code.DATA_NOT_FOUND,
        errorMessage(messageKey.data_not_found, { ":data": "Plan" }),
      )
    }

    const isServiceTypeExist = await this.tripTypeRepository.getByParams({
      where: { id: updateDto.service_type_id },
      findOne: true,
    })

    if (isEmpty(isServiceTypeExist)) {
      return failureResponse(
        code.DATA_NOT_FOUND,
        errorMessage(messageKey.data_not_found, { ":data": "Service Type" }),
      )
    }

    const meetAndGreetPricing = new MeetAndGreetPricing()
    Object.assign(meetAndGreetPricing, updateDto)

    await this.meetAndGreetPricingRepository.save(meetAndGreetPricing, { id })

    return successResponse(
      code.SUCCESS,
      successMessage(messageKey.data_update, {
        ":data": "Meet & Greet Pricing",
      }),
    )
  }

  async remove(id: number) {
    const isExist = await this.meetAndGreetPricingRepository.getByParams({
      where: { id },
      findOne: true,
    })

    if (isEmpty(isExist)) {
      return failureResponse(
        code.DATA_NOT_FOUND,
        errorMessage(messageKey.data_not_found, {
          ":data": "Meet & Greet Pricing",
        }),
      )
    }

    await this.meetAndGreetPricingRepository.remove({ id })

    return successResponse(
      code.SUCCESS,
      successMessage(messageKey.data_removed, {
        ":data": "Meet & Greet Pricing",
      }),
    )
  }
}
