import httpStatus from 'http-status';

import Configuration from '@/modules/master/property/configuration/configuration.model';
import { IConfiguration, IPropertyFilter } from '../property.interfaces';
import ApiError from '@/shared/utils/errors/ApiError';
import { PaginateOptions } from '@/shared/utils/plugins/paginate/paginate';
import { FilterQuery } from 'mongoose';
import { getObjectId, parseSafeIds } from '@/shared/utils/commonHelper';
import responseCodes from '@/shared/utils/responseCode/responseCode';
import { defaultStatus } from '@/shared/utils/responseCode/httpStatusAlias';
import { safeDeleteById } from '@/shared/utils/guard/ref-guard';

const { ConfigurationResponseCodes } = responseCodes;

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

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

  if (existing)
    throw new ApiError(
      defaultStatus.BAD_REQUEST,
      'Configuration with this name already exists.',
      true,
      '',
      ConfigurationResponseCodes.CONFIGURATION_ALREADY_EXISTS,
    );

  return await Configuration.create(body);
};

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

export const update = async (
  id: string,
  body: Partial<IConfiguration>,
): Promise<IConfiguration> => {
  const configuration = await Configuration.findByIdAndUpdate(id, body, {
    new: true,
    runValidators: true,
  });
  if (!configuration)
    throw new ApiError(httpStatus.NOT_FOUND, 'Configuration not found');
  return configuration;
};

export const remove = async (id: string): Promise<boolean> => {
  await safeDeleteById(
    Configuration,
    id,
    ConfigurationResponseCodes.CONFIGURATION_IN_USE,
  );
  return true;
};

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

export const queryConfiguration = async (
  filter: IPropertyFilter = {},
  options: PaginateOptions = {},
) => {
  const queryFilter: FilterQuery<IConfiguration> = {
    ...(filter.categoryId && { category: parseSafeIds(filter.categoryId), }),
  };

  // Handle subCategoryId (single, comma-separated, or array)
  if (filter.subCategoryId) {
    let subCategoryIds: string[] = [];

    if (Array.isArray(filter.subCategoryId))
      subCategoryIds = filter.subCategoryId;
    else if (typeof filter.subCategoryId === 'string')
      // Support comma-separated string
      subCategoryIds = filter.subCategoryId.split(',').map((id) => id.trim());
    else subCategoryIds = [filter.subCategoryId.toString()];

    if (subCategoryIds.length === 1)
      queryFilter.subCategory = getObjectId(subCategoryIds[0]);
    else queryFilter.subCategory = { $in: subCategoryIds.map(getObjectId) };
  }

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

  const configuration = await Configuration.paginate(queryFilter, options);
  return configuration;
};
