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

import Country from '@/modules/master/location/country/country.model.js';
import ApiError from '@/shared/utils/errors/ApiError.js';
import { ICountry } from '@/modules/master/location/location.interfaces.js';
import pick from '@/shared/utils/pick.js';
import { defaultStatus } from '@/shared/utils/responseCode/httpStatusAlias';
import responseCodes from '@/shared/utils/responseCode/responseCode';
import { safeDeleteById } from '@/shared/utils/guard/ref-guard';

const { CountryResponseCodes } = responseCodes;

export const create = async (data: Partial<ICountry>): Promise<ICountry> => {

  const existing = await Country.findOne({
    name: data.name.toLowerCase().trim(),
    'loc.coordinates': data.loc.coordinates,
  });

  if (existing) 
    throw new ApiError(
      defaultStatus.BAD_REQUEST,
      'Country with this name and coordinates already exists.',
      true,
      '',
      CountryResponseCodes.COUNTRY_ALREADY_EXISTS,
    );
  

  const nameExists = await Country.findOne({
    name: data.name,
  });

  if (nameExists) 
    throw new ApiError(
      defaultStatus.BAD_REQUEST,
      'Country with this name already exists.',
      true,
      '',
      CountryResponseCodes.COUNTRY_NAME_ALREADY_EXISTS,
    );
  

  return await Country.create(data);
};

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

export const update = async (
  id: string,
  data: Partial<ICountry>,
): Promise<ICountry> => {
  // Normalize name if provided
  const name = data.name?.toLowerCase().trim();

  // Check if another country with the same name exists (excluding current)
  if (name) {
    const nameExists = await Country.findOne({
      _id: { $ne: id },
      name,
    });

    if (nameExists) 
      throw new ApiError(
        defaultStatus.BAD_REQUEST,
        'Another country with this name already exists.',
        true,
        '',
        CountryResponseCodes.COUNTRY_NAME_ALREADY_EXISTS,
      );
    
  }

  // Check if another country with the same name and coordinates exists (excluding current)
  if (name && data.loc?.coordinates) {
    const existing = await Country.findOne({
      _id: { $ne: id },
      name,
      'loc.coordinates': data.loc.coordinates,
    });

    if (existing) 
      throw new ApiError(
        defaultStatus.BAD_REQUEST,
        'Another country with this name and coordinates already exists.',
        true,
        '',
        CountryResponseCodes.COUNTRY_ALREADY_EXISTS,
      );
    
  }

  const country = await Country.findByIdAndUpdate(id, data, {
    new: true,
    runValidators: true,
  });

  if (!country) throw new ApiError(httpStatus.NOT_FOUND, 'Country not found');
  return country;
};

export const remove = async (id: string): Promise<boolean> => {
 await safeDeleteById(Country, id, CountryResponseCodes.COUNTRY_IN_USE);

  return true;
};

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

  const options = pick(query, [
    'sortBy',
    'limit',
    'page',
    'populate',
    'fields',
  ]);
  let queryFilter: FilterQuery<ICountry> = {};

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

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