import httpStatus from 'http-status';
import PropertyUsage from './propertyUsage.model';
import { IPropertyFilter, IPropertyUsage } from '../property.interfaces';
import ApiError from '@/shared/utils/errors/ApiError';
import { PaginateOptions } from '@/shared/utils/plugins/paginate/paginate';
import { FilterQuery } from 'mongoose';
import responseCodes from '@/shared/utils/responseCode/responseCode';
import { defaultStatus } from '@/shared/utils/responseCode/httpStatusAlias';
import { safeDeleteById } from '@/shared/utils/guard/ref-guard';

const { PropertyUsageResponseCodes } = responseCodes;

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

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

  if (existing)
    throw new ApiError(
      defaultStatus.BAD_REQUEST,
      'Property usage with this name already exists.',
      true,
      '',
      PropertyUsageResponseCodes.PROPERTY_USAGE_ALREADY_EXISTS,
    );

  return await PropertyUsage.create(body);
};

export const getById = async (id: string): Promise<IPropertyUsage> => {
  const usage = await PropertyUsage.findById(id);
  if (!usage)
    throw new ApiError(httpStatus.NOT_FOUND, 'PropertyUsage not found');

  return usage;
};

export const update = async (
  id: string,
  body: Partial<IPropertyUsage>,
): Promise<IPropertyUsage> => {
  if (body.name) {
    const existing = await PropertyUsage.findOne({
      _id: { $ne: id },
      name: body.name.toLowerCase().trim(),
    });

    if (existing)
      throw new ApiError(
        defaultStatus.BAD_REQUEST,
        'Property usage with this name already exists.',
        true,
        '',
        PropertyUsageResponseCodes.PROPERTY_USAGE_ALREADY_EXISTS,
      );

    // Ensure name is stored consistently
    body.name = body.name.toLowerCase().trim();
  }

  const usage = await PropertyUsage.findByIdAndUpdate(id, body, {
    new: true,
    runValidators: true,
  });

  if (!usage)
    throw new ApiError(httpStatus.NOT_FOUND, 'PropertyUsage not found');

  return usage;
};

export const remove = async (id: string): Promise<boolean> => {
 await safeDeleteById(PropertyUsage, id, PropertyUsageResponseCodes.PROPERTY_USAGE_IN_USE);

  return true;
};

export const list = (
  query: Record<string, unknown>,
): Promise<IPropertyUsage[]> => PropertyUsage.find(query);

export const queryPropertyUsage = async (
  filter: IPropertyFilter = {},
  options: PaginateOptions = {},
) => {
  const { search, ...restFilter } = filter;
  let queryFilter: FilterQuery<IPropertyUsage> = {
    ...restFilter,
  };

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

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