import { Injectable } from "@nestjs/common"
import { failureResponse } from "src/common/response/response"
import { isEmpty } from "src/utils/helpers"
import { messageKey } from "src/constants/message-keys"
import { BusinessVerticalRepository } from "../repositories/business-verticals.repository"
import { CreateBusinessVerticalDto } from "../dto/create-business-verticals.dto"
import { FindAllBusinessVerticalDto } from "../dto/find-all-business-verticals.dto"
import { BusinessVertical } from "../entities/business-verticals.entity"
import { UpdateBusinessVerticalDto } from "../dto/update-business-verticals.dto"

@Injectable()
export class BusinessVerticalsService {
  constructor(
    private readonly businessVerticalRepository: BusinessVerticalRepository,
  ) {}

  // Check if a Business Vertical exists
  async checkBusinessVerticalExist(name: string) {
    const businessVertical: any =
      await this.businessVerticalRepository.getByParams({
        whereLower: { name: name },
        findOne: true,
      })

    return businessVertical
  }

  async createBusinessVertical(
    createBusinessVerticalDto: CreateBusinessVerticalDto,
  ) {
    const isBusinessVerticalExist = await this.checkBusinessVerticalExist(
      createBusinessVerticalDto.name,
    )

    if (!isEmpty(isBusinessVerticalExist)) {
      return failureResponse(400, messageKey.already_exist)
    }

    try {
      const result = await this.businessVerticalRepository.save({
        name: createBusinessVerticalDto.name,
      })
      return result
    } catch (error) {
      return failureResponse(500, messageKey.something_went_wrong)
    }
  }

  async findAllBusinessVerticals(params: FindAllBusinessVerticalDto) {
    const validSortColumns = ["id", "name", "created_at", "updated_at"]

    if (params.sortBy && !validSortColumns.includes(params.sortBy)) {
      return failureResponse(400, messageKey.invalid)
    }

    const businessVerticals =
      (await this.businessVerticalRepository.getByParams({
        search: {
          name: params.search,
        },
        take: Number(params.limit),
        skip: Number(params.skip),
        orderBy: params.sortBy
          ? { [params.sortBy]: params.sortOrder || "ASC" }
          : { created_at: "DESC" },
        relations: ["team_members:id,first_name,last_name"],
      })) as any

    const verticalsWithCount = businessVerticals.data.map((vertical) => ({
      ...vertical,
      member_count: vertical.team_members ? vertical.team_members.length : 0,
    }))

    return {
      count: businessVerticals.count,
      data: verticalsWithCount,
    }
  }

  async findOneBusinessVertical(id: number): Promise<BusinessVertical> {
    const businessVertical = (await this.businessVerticalRepository.getByParams(
      {
        where: { id },
        findOne: true,
      },
    )) as BusinessVertical

    if (!businessVertical) {
      throw new Error(messageKey.data_not_found)
    }

    return businessVertical
  }

  async updateBusinessVertical(
    id: number,
    updateBusinessVerticalDto: UpdateBusinessVerticalDto,
  ) {
    const businessVertical = (await this.businessVerticalRepository.getByParams(
      {
        where: { id },
        findOne: true,
      },
    )) as BusinessVertical

    if (!businessVertical) {
      return failureResponse(404, messageKey.data_not_found)
    }

    const isBusinessVerticalExist = await this.checkBusinessVerticalExist(
      updateBusinessVerticalDto.name,
    )

    if (
      !isEmpty(isBusinessVerticalExist) &&
      isBusinessVerticalExist.id !== id &&
      isBusinessVerticalExist.name === updateBusinessVerticalDto.name
    ) {
      return failureResponse(400, messageKey.already_exist)
    }

    Object.assign(businessVertical, updateBusinessVerticalDto)
    return await this.businessVerticalRepository.save(businessVertical)
  }

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

    if (isEmpty(businessVertical)) {
      return failureResponse(404, messageKey.data_not_found)
    }
    await this.businessVerticalRepository.remove({ id })

    return { success: true, code: 200, message: messageKey.data_removed }
  }

  async getBusinessVerticalsDropdown() {
    try {
      const result = await this.businessVerticalRepository.getByParams({
        select: ["id", "name"],
        orderBy: { name: "ASC" },
        findOne: false,
      })

      return result
    } catch (error) {
      return failureResponse(500, messageKey.something_went_wrong)
    }
  }
}
