import type { FastifyInstance, FastifyPluginAsync } from 'fastify';
import fp from 'fastify-plugin';
import { ZodError } from 'zod';

interface ErrorResponseBody {
  readonly error: string;
  readonly statusCode: number;
}

const errorHandlerPlugin: FastifyPluginAsync = async (fastify: FastifyInstance) => {
  fastify.setErrorHandler((error: unknown, _request, reply) => {
    const fastifyError = error as { statusCode?: number; message?: string };
    const statusCode = fastifyError.statusCode ?? 500;

    if (error instanceof ZodError) {
      const message = error.issues
        .map((e) => `${e.path.join('.')}: ${e.message}`)
        .join('; ');

      const body: ErrorResponseBody = {
        error: `Validation error: ${message}`,
        statusCode: 400,
      };

      return reply.status(400).send(body);
    }

    const body: ErrorResponseBody = {
      error: statusCode >= 500 ? 'Internal Server Error' : (fastifyError.message ?? 'Unknown error'),
      statusCode,
    };

    if (statusCode >= 500) {
      fastify.log.error(error);
    }

    return reply.status(statusCode).send(body);
  });

  fastify.setNotFoundHandler((_request, reply) => {
    const body: ErrorResponseBody = {
      error: 'Not Found',
      statusCode: 404,
    };
    return reply.status(404).send(body);
  });
};

export default fp(errorHandlerPlugin, { name: 'error-handler' });
