import { IErrorExtra_Response_DTO, IError_Response_DTO } from "@shared/contexts";
import { Request, Response } from "express";
import { UseCaseError } from "../../application";
import { InfrastructureError } from "../InfrastructureError";
import { ProblemDocument, ProblemDocumentExtension } from "./ProblemDocument";

export const generateExpressError = (
  req: Request,
  res: Response,
  statusCode: number,
  message?: string,
  error?: Error | InfrastructureError
): Response<IError_Response_DTO> => {
  const context = {
    user: res.locals.user || undefined,
    params: req.params || undefined,
    query: req.query || undefined,
    body: req.body || undefined,
  };

  const extension = new ProblemDocumentExtension({
    context,
    extra: error ? { ..._extractExtraInfoFromError(error) } : {},
  });

  const jsonPayload = new ProblemDocument(
    {
      status: statusCode,
      detail: message,
      instance: req.baseUrl,
    },
    extension
  );

  return res.status(statusCode).json(jsonPayload).send();
};

function _extractExtraInfoFromError(error: Error | InfrastructureError): IErrorExtra_Response_DTO {
  const useCaseError = error as UseCaseError;

  const payload = Array.isArray(useCaseError.payload)
    ? useCaseError.payload
    : [useCaseError.payload];

  const errors = payload.map((item) => {
    if (item.path) {
      return item.path
        ? {
            [String(item.path)]: item.message || useCaseError.message,
          }
        : {};
    } else {
      return item;
    }
  });

  return {
    errors,
  };
}
