import httpStatus from 'http-status';
import { FilterQuery } from 'mongoose';

import PropertySize from '@/modules/master/property/propertySize/propertySize.model';
import { IPropertyFilter, IPropertySize } from '../property.interfaces';
import ApiError from '@/shared/utils/errors/ApiError';
import { PaginateOptions } from '@/shared/utils/plugins/paginate/paginate';
import responseCodes from '@/shared/utils/responseCode/responseCode';
import { defaultStatus } from '@/shared/utils/responseCode/httpStatusAlias';
import { safeDeleteById } from '@/shared/utils/guard/ref-guard';

const { PropertySizeResponseCodes } = responseCodes;

export const create = async (body: IPropertySize): Promise<IPropertySize> => {
  const { name } = body;

  const existing = await PropertySize.findOne({
    name: name?.toLowerCase().trim(),
  });

  if (existing)
    throw new ApiError(
      defaultStatus.BAD_REQUEST,
      'Property size with this name already exists.',
      true,
      '',
      PropertySizeResponseCodes.PROPERTY_SIZE_ALREADY_EXISTS,
    );

  return await PropertySize.create(body);
};

export const getById = async (id: string): Promise<IPropertySize> => {
  const size = await PropertySize.findById(id);
  if (!size) throw new ApiError(httpStatus.NOT_FOUND, 'PropertySize not found');
  return size;
};

export const update = async (
  id: string,
  body: Partial<IPropertySize>,
): Promise<IPropertySize> => {
  const { name } = body;

  if (name) {
    const existing = await PropertySize.findOne({
      _id: { $ne: id },
      name: name?.toLowerCase().trim(),
    });

    if (existing)
      throw new ApiError(
        defaultStatus.BAD_REQUEST,
        'Property size with this name already exists.',
        true,
        '',
        PropertySizeResponseCodes.PROPERTY_SIZE_ALREADY_EXISTS,
      );
  }

  const size = await PropertySize.findByIdAndUpdate(id, body, {
    new: true,
    runValidators: true,
  });
  if (!size) throw new ApiError(httpStatus.NOT_FOUND, 'PropertySize not found');
  return size;
};

export const remove = async (id: string): Promise<boolean> => {
 await safeDeleteById(PropertySize, id, PropertySizeResponseCodes.PROPERTY_SIZE_IN_USE);
  return true;
};

export const queryPropertySize = async (
  filter: IPropertyFilter = {},
  options: PaginateOptions = {},
) => {
  const { search, ...restFilter } = filter;

  const queryFilter: FilterQuery<IPropertySize> = {
    ...restFilter,
  };

  if (search) 
    queryFilter.$or = [{ name: { $regex: search, $options: 'i' } }];
  

  return await PropertySize.paginate(queryFilter, options);
};
