// Centralized error-handling middleware for the /api routes.
//
// The original app.js had a partial handler that only recognized
// UnauthorizedError and, for every other error, neither responded nor
// called next() — leaving API requests to hang. This middleware
// guarantees every API error produces a JSON response with an
// appropriate status code, and never leaks stack traces to clients
// outside development.

// Custom error type controllers can throw to set a specific status.
class ApiError extends Error {
    constructor(statusCode, message) {
        super(message);
        this.statusCode = statusCode;
        this.name = 'ApiError';
    }
}

// 404 for unknown /api paths, forwarded into the error handler below.
const notFoundHandler = (req, res, next) => {
    next(new ApiError(404, `Not found: ${req.method} ${req.originalUrl}`));
};

// Express identifies error middleware by its four-parameter signature.
// eslint-disable-next-line no-unused-vars
const errorHandler = (err, req, res, next) => {
    let statusCode = err.statusCode || 500;
    let message = err.message || 'Internal Server Error';

    // JWT middleware (express-jwt style) errors
    if (err.name === 'UnauthorizedError') {
        statusCode = 401;
        message = err.name + ': ' + err.message;
    }

    // Mongoose validation failures are client errors, not server faults.
    if (err.name === 'ValidationError') {
        statusCode = 400;
    }

    // Malformed ObjectId or similar cast problems
    if (err.name === 'CastError') {
        statusCode = 400;
        message = 'Malformed request parameter';
    }

    if (statusCode === 500) {
        // Log unexpected errors server side; clients get a generic message.
        console.error(err);
        if (process.env.NODE_ENV !== 'development') {
            message = 'Internal Server Error';
        }
    }

    return res.status(statusCode).json({ message });
};

module.exports = { ApiError, notFoundHandler, errorHandler };
