import { Injectable } from "@nestjs/common"
import { isEmpty } from "lodash"
import { ConfigService } from "@nestjs/config"
import { CustomerTreatmentPlanRepository } from "../repositories/customer_treatment_plan.repository"
import { CustomerTreatmentImagesRepository } from "../repositories/customer_treatment_images.repository"
import { CustomerRepository } from "../../customers/repositories/customers.repository"
import { CreateCustomerTreatmentPlanDto } from "../dto/create-customer-treatment-plan.dto"
import { UpdateCustomerTreatmentPlanDto } from "../dto/update-customer-treatment-plan.dto"
import { failureResponse, successResponse } from "src/common/response/response"
import { code } from "src/common/response/response.code"
import { messageKey } from "src/constants/message-keys"
import { fileStoreLocation } from "src/common/file-upload/file-store-location"

@Injectable()
export class CustomerTreatmentPlanService {
  constructor(
    private readonly configService: ConfigService,
    private readonly customerRepository: CustomerRepository,
    private readonly customerPlanRepository: CustomerTreatmentPlanRepository,
    private readonly imageRepository: CustomerTreatmentImagesRepository,
  ) {}

  async create(
    dto: CreateCustomerTreatmentPlanDto,
    files: { images?: Express.Multer.File[] },
  ) {
    const customer = await this.customerRepository.getByParams({
      where: { id: dto.customer_id },
      findOne: true,
    })

    if (isEmpty(customer)) {
      return failureResponse(code.DATA_NOT_FOUND, messageKey.customer_not_found)
    }

    const savedPlan = await this.customerPlanRepository.save({
      customer_id: dto.customer_id,
      comments: dto.comments,
    })

    if (files?.images?.length) {
      const imageRecords = files.images.map((file) => ({
        treatment_plan_id: savedPlan.id,
        plan_image: `${fileStoreLocation.customer_treatment_plan}/${file.filename}`,
      })) as any
      await this.imageRepository.save(imageRecords)
    }

    return successResponse(
      code.SUCCESS,
      messageKey.customer_treatment_plan_added,
      savedPlan,
    )
  }

  async findAll(
    limit?: number,
    skip?: number,
    search?: string,
    sortBy?: string,
    sortOrder?: string,
    customer_id?: number,
  ) {
    const validSortColumns = [
      "id",
      "customer_id",
      "comments",
      "created_at",
      "updated_at",
    ]

    const defaultPagination = {
      take: this.configService.get<number>("APP.pagination.take"),
      skip: this.configService.get<number>("APP.pagination.skip"),
    }

    const sortColumn = validSortColumns.includes(sortBy || "")
      ? sortBy
      : "created_at"
    const order: "ASC" | "DESC" = sortOrder === "ASC" ? "ASC" : "DESC"

    const whereConditions: any = {}

    if (customer_id) {
      whereConditions.customer_id = customer_id
    }

    if (search) {
      whereConditions.comments = { ilike: `%${search}%` }
    }

    const queryParams: any = {
      where: whereConditions,
      take: limit || defaultPagination.take,
      skip: skip || defaultPagination.skip,
      orderBy: { [sortColumn]: order },
      relations: [
        "customer:id,customer_name,country_code,phone_number,email",
        "images",
      ],
    }

    const result = (await this.customerPlanRepository.getByParams(
      queryParams,
    )) as any

    if (isEmpty(result)) {
      return failureResponse(
        code.SUCCESS,
        messageKey.customer_treatment_plan_not_found,
      )
    }

    return successResponse(
      code.SUCCESS,
      messageKey.customer_treatment_plan_retrieved,
      result,
    )
  }

  async findOne(id: number) {
    const plan = (await this.customerPlanRepository.getByParams({
      where: { id },
      relations: [
        "customer:id,customer_name,country_code,phone_number,email",
        "images",
      ],
      findOne: true,
    })) as any

    if (isEmpty(plan)) {
      return failureResponse(
        code.DATA_NOT_FOUND,
        messageKey.customer_treatment_plan_not_found,
      )
    }

    return successResponse(code.SUCCESS, messageKey.data_retrieve, plan)
  }

  async update(
    id: number,
    dto: UpdateCustomerTreatmentPlanDto,
    files?: { images?: Express.Multer.File[] },
  ) {
    const existing = (await this.customerPlanRepository.getByParams({
      where: { id },
      findOne: true,
    })) as any

    if (isEmpty(existing)) {
      return failureResponse(
        code.DATA_NOT_FOUND,
        messageKey.customer_treatment_plan_not_found,
      )
    }

    const updated = await this.customerPlanRepository.save(
      { ...existing, ...dto },
      { id },
    )

    if (files?.images?.length) {
      const imageRecords = files.images.map((file) => ({
        treatment_plan_id: id,
        plan_image: `${fileStoreLocation.customer_treatment_plan}/${file.filename}`,
      })) as any

      await this.imageRepository.save(imageRecords)
    }

    return successResponse(
      code.SUCCESS,
      messageKey.customer_treatment_plan_updated,
      updated,
    )
  }

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

    if (isEmpty(existing)) {
      return failureResponse(
        code.DATA_NOT_FOUND,
        messageKey.customer_treatment_plan_not_found,
      )
    }

    await this.customerPlanRepository.remove({ id })

    return successResponse(code.SUCCESS, messageKey.data_removed)
  }
}
