class ErrorHandler extends Error {
  statusCode: number;

  constructor(message: string, statusCode: number) {
    super(message);
    this.statusCode = statusCode;
    Error.captureStackTrace(this, this.constructor);
  }
}

interface Request {}
interface Response {
  status: (code: number) => Response;
  json: (body: any) => Response;
}
type NextFunction = (err?: any) => void;

interface ErrorObject {
  message: string;
}

interface CustomError extends Error {
  statusCode?: number;
  code?: number | string;
  keyValue?: Record<string, unknown>;
  errors?: Record<string, ErrorObject> | any;
  error?: Record<string, ErrorObject> | any;
  path?: string;
  value?:string;
}

export const errorMiddleware = (
  err: CustomError,
  req: Request,
  res: Response,
  next: NextFunction
): Response => {
   err.message = err.message || "Internal Server Error";
  err.statusCode = err.statusCode || 500;

  // Handle postgreDB duplicate key error
  if (err.code === 11000) {
    const keys = Object.keys(err.keyValue ?? {});
    const message = keys.length
      ? `Duplicate ${keys.join(", ")} Entered`
      : "Duplicate field value entered";
    err = new ErrorHandler(message, 400); // ✅ overwrite, not redeclare
  }

  // Handle JWT error
  if (err.name === "JsonWebTokenError") {
    const message = `JSON Web Token is invalid, try again!`;
    err = new ErrorHandler(message, 400);
  }

  // Handle JWT expired
  if (err.name === "TokenExpiredError") {
    const message = `JSON Web Token has expired, try again!`;
    err = new ErrorHandler(message, 400);
  }

  // Handle Postgrey CastError (e.g., invalid ObjectId)
  if (err.name === "CastError") {
    const message = `Invalid ${err.path}: ${err.value}`;
    err = new ErrorHandler(message, 400);
  }

  // Handle validation errors (like postgres required fields, etc.)
  const errorMessage: string = err.errors
    ? Object.values((err as any).error)
        .map((error: any) => error.message)
        .join(" ")
    : err.message;

  const status = err.statusCode ?? 500;

  return res.status(status).json({
    success: false,
    message: errorMessage,
  });
};

export default ErrorHandler;
