import { Injectable } from "@nestjs/common"
import { CreateSubscriptionPlanDto } from "./dto/create-subscription-plan.dto"
import { UpdateSubscriptionPlanDto } from "./dto/update-subscription-plan.dto"
import { SubscriptionPlanFilterDto } from "./dto/subscription-plan-filter.dto"
import { successResponse, failureResponse } from "src/common/response/response"
import { code } from "src/common/response/response.code"
import {
  successMessage,
  errorMessage,
  validationMessage,
} from "src/utils/helpers"
import { messageKey } from "src/constants/message-keys"
import { isEmpty } from "class-validator"
import { SubscriptionPlanRepository } from "./repository/subscription-plan.repository"

@Injectable()
export class SubscriptionPlanService {
  constructor(
    private readonly subscriptionPlanRepository: SubscriptionPlanRepository,
  ) {}

  async create(createDto: CreateSubscriptionPlanDto) {
    try {
      const isExist = await this.subscriptionPlanRepository.getByParams({
        where: { name: createDto.name },
        findOne: true,
      })

      if (isExist) {
        return failureResponse(
          code.SUCCESS,
          validationMessage(messageKey.already_exist, {
            ":data": "Subscription Plan",
          }),
        )
      }

      if (createDto.features && typeof createDto.features !== "string") {
        createDto.features = JSON.stringify(createDto.features)
      }

      await this.subscriptionPlanRepository.save(createDto)

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.data_add, { ":data": "Subscription Plan" }),
      )
    } catch (error) {
      return failureResponse(
        code.ERROR,
        errorMessage(messageKey.validation_error, {
          ":data": "Subscription Plan",
        }),
      )
    }
  }

  async findAll(filterDto: SubscriptionPlanFilterDto) {
    try {
      const { take, skip, search } = filterDto

      const params: any = {
        orderBy: { sort_order: "ASC" },
      }

      if (!isEmpty(take)) {
        params.take = take
        params.skip = skip
      }

      if (!isEmpty(search)) {
        params["search"] = {
          name: search,
        }
      }

      const result: any =
        await this.subscriptionPlanRepository.getByParams(params)

      if (isEmpty(result)) {
        return failureResponse(
          code.SUCCESS,
          errorMessage(messageKey.data_not_found, {
            ":data": "Subscription Plan",
          }),
        )
      }

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.data_retrieve, {
          ":data": "Subscription Plan",
        }),
        result,
      )
    } catch (error) {
      return failureResponse(
        code.ERROR,
        errorMessage(messageKey.validation_error, {
          ":data": "Subscription Plan",
        }),
      )
    }
  }

  async findOne(id: number) {
    try {
      const plan: any = await this.subscriptionPlanRepository.getByParams({
        where: { id },
        findOne: true,
      })

      if (!plan) {
        return failureResponse(
          code.SUCCESS,
          errorMessage(messageKey.data_not_found, {
            ":data": "Subscription Plan",
          }),
        )
      }

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.detail_found, {
          ":data": "Subscription Plan",
        }),
        plan,
      )
    } catch (error) {
      return failureResponse(
        code.ERROR,
        errorMessage(messageKey.validation_error, {
          ":data": "Subscription Plan",
        }),
      )
    }
  }

  async update(id: number, updateDto: UpdateSubscriptionPlanDto) {
    try {
      const plan = await this.subscriptionPlanRepository.getByParams({
        where: { id },
        findOne: true,
      })

      if (!plan) {
        return failureResponse(
          code.SUCCESS,
          errorMessage(messageKey.data_not_found, {
            ":data": "Subscription Plan",
          }),
        )
      }

      if (updateDto.name) {
        const isExist = await this.subscriptionPlanRepository.getByParams({
          where: { name: updateDto.name, id: { not: id } },
          findOne: true,
        })

        if (isExist) {
          return failureResponse(
            code.SUCCESS,
            validationMessage(messageKey.already_exist, {
              ":data": "Subscription Plan",
            }),
          )
        }
      }

      if (updateDto.features && typeof updateDto.features !== "string") {
        updateDto.features = JSON.stringify(updateDto.features)
      }

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

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.data_update, {
          ":data": "Subscription Plan",
        }),
      )
    } catch (error) {
      return failureResponse(
        code.ERROR,
        errorMessage(messageKey.validation_error, {
          ":data": "Subscription Plan",
        }),
      )
    }
  }

  async findAllActive() {
    try {
      const result: any = await this.subscriptionPlanRepository.getByParams({
        where: { is_active: 1 },
        orderBy: { sort_order: "ASC" },
      })

      if (isEmpty(result)) {
        return failureResponse(
          code.SUCCESS,
          errorMessage(messageKey.data_not_found, {
            ":data": "Subscription Plan",
          }),
        )
      }

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.data_retrieve, {
          ":data": "Subscription Plan",
        }),
        result,
      )
    } catch (error) {
      return failureResponse(
        code.ERROR,
        errorMessage(messageKey.validation_error, {
          ":data": "Subscription Plan",
        }),
      )
    }
  }

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

      if (!plan) {
        return failureResponse(
          code.SUCCESS,
          errorMessage(messageKey.data_not_found, {
            ":data": "Subscription Plan",
          }),
        )
      }

      await this.subscriptionPlanRepository.remove({ id })

      return successResponse(
        code.SUCCESS,
        successMessage(messageKey.data_removed, {
          ":data": "Subscription Plan",
        }),
      )
    } catch (error) {
      return failureResponse(
        code.ERROR,
        errorMessage(messageKey.validation_error, {
          ":data": "Subscription Plan",
        }),
      )
    }
  }
}
