import type { NextFunction, Request, Response } from "express";
import { ZodError } from "zod";

export class AppError extends Error {
  status: number;
  details?: unknown;

  constructor(status: number, message: string, details?: unknown) {
    super(message);
    this.status = status;
    this.details = details;
  }
}

export function asyncHandler(
  fn: (req: Request, res: Response, next: NextFunction) => Promise<unknown>,
) {
  return (req: Request, res: Response, next: NextFunction) => {
    fn(req, res, next).catch(next);
  };
}

export function errorHandler(err: unknown, _req: Request, res: Response, _next: NextFunction) {
  if (err instanceof AppError) {
    return res.status(err.status).json({ error: err.message, details: err.details });
  }
  if (err instanceof ZodError) {
    const first =
      err.issues[0]?.message && err.issues[0]?.path?.length
        ? `${err.issues[0].path.join(".")}: ${err.issues[0].message}`
        : err.issues[0]?.message;
    return res.status(400).json({
      error: first || "Validation failed",
      details: err.flatten(),
    });
  }
  console.error(err);
  return res.status(500).json({ error: "Internal server error" });
}
