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

import Area from '@/modules/master/location/area/area.model.js';
import ApiError from '@/shared/utils/errors/ApiError.js';
import { IArea } from '@/modules/master/location/location.interfaces.js'; 
import pick from '@/shared/utils/pick.js';
import { getObjectId } 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 { AreaResponseCodes } = responseCodes;

export const create = async (data: Partial<IArea>): Promise<IArea> => {
  const { name, city, loc } = data;

  const existing = await Area.findOne({
    name,
    city,
    'loc.coordinates': loc?.coordinates,
  });

  if (existing)
    throw new ApiError(
      defaultStatus.BAD_REQUEST,
      'Area with this name and coordinates already exists.',
      true,
      '',
      AreaResponseCodes.AREA_ALREADY_EXISTS,
    );

  return await Area.create(data);
};

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

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

export const remove = async (id: string): Promise<boolean> => {
 await safeDeleteById(Area, id, AreaResponseCodes.AREA_IN_USE);
  return true;
};

export const list = async (query: Record<string, unknown>) => {
  const filter = pick(query, ['search', 'city']);

  const options = pick(query, [
    'sortBy',
    'limit',
    'page',
    'populate',
    'fields',
  ]);
  let queryFilter: FilterQuery<IArea> = {
    ...filter.city && { city: getObjectId(filter.city) },
  };

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

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

