import { getObjectId } from '@/shared/utils/commonHelper';
import { ApiError } from '@/shared/utils/errors';
import { PaginateOptions } from '@/shared/utils/plugins/paginate/paginate';
import { defaultStatus } from '@/shared/utils/responseCode/httpStatusAlias';
import responseCodes from '@/shared/utils/responseCode/responseCode';
import { Types } from 'mongoose';
import {
  IUnitJobDoc,
  IUnitJobFilter,
  NewCreatedUnitJob,
  UpdateUnitJobBody,
} from './unit-job.interface';
import UnitJob from './unit-job.model';

const { ProjectResponseCodes } = responseCodes;

export const createUnitJob = async (
  data: NewCreatedUnitJob,
): Promise<IUnitJobDoc | null> => {
  let unitJob: IUnitJobDoc | null;

  try {
    unitJob = await UnitJob.create(data);
  } catch (_error) {
    throw new ApiError(
      defaultStatus.OK,
      'Failed to create unit job',
      true,
      '',
      ProjectResponseCodes.PROJECT_ERROR,
    );
  }

  return unitJob;
};

export const updateUnitJob = async (
  id: Types.ObjectId | string,
  updateData: UpdateUnitJobBody,
): Promise<IUnitJobDoc | null> => {
  let unitJob: IUnitJobDoc | null;

  try {
    const query =
      id instanceof Types.ObjectId || Types.ObjectId.isValid(id)
        ? { _id: id instanceof Types.ObjectId ? id : new Types.ObjectId(id) }
        : { jobId: id };

    unitJob = await UnitJob.findOneAndUpdate(query, updateData, {
      new: true,
      runValidators: true,
    });
  } catch (_error) {
    throw new ApiError(
      defaultStatus.OK,
      'Failed to update unit job',
      true,
      '',
      ProjectResponseCodes.PROJECT_ERROR,
    );
  }

  if (!unitJob)
    throw new ApiError(
      defaultStatus.OK,
      'Unit job not found',
      true,
      '',
      ProjectResponseCodes.PROJECT_NOT_FOUND,
    );

  return unitJob;
};

export const getUnitJobsByProjectId = async (
  projectId: Types.ObjectId,
  options: PaginateOptions = {},
  rowFilter: IUnitJobFilter = {},
) => {
  const { status, createdBy, jobId, search, ...baseFilters } = rowFilter;

  const merged = {
    ...baseFilters,
    ...(search && {
      $or: [
        { fileName: { $regex: search, $options: 'i' } },
        { status: { $regex: search, $options: 'i' } },
      ],
    }),
    ...(projectId && { project: getObjectId(projectId) }),
    ...(createdBy && { createdBy: getObjectId(createdBy) }),
    ...(status && status !== 'all' && { status }),
    ...(jobId && { jobId }),
  };

  const filter = Object.fromEntries(
    Object.entries(merged).filter(([, v]) => v != null),
  );

  return UnitJob.paginate(filter, options);
};
