const jwt = require("jsonwebtoken");
const AppError = require("./appError");
const { STATUS_CODE } = require("./utility");
const { User } = require("../models");
const { SERVER_ERROR } = require("./errorMessage");

module.exports = (options = { required: true }) => {
    const required = options.required ?? true;

    return async (req, res, next) => {
        const authHeader = req.headers.authorization;
        if (!authHeader || !authHeader.startsWith("Bearer ")) {
            if (!required) {
                return next();
            }
            return next(new AppError("Invalid authorization header", STATUS_CODE.UNAUTHORIZED));
        }

        const token = authHeader.split(" ")[1];
        if (!token) {
            if (!required) {
                return next();
            }
            return next(new AppError("Authorization token not found", STATUS_CODE.UNAUTHORIZED));
        }

        try {
            const payload = jwt.verify(token, process.env.JWT_SECRET);
            const user = await User.findOne({ where: { user_id: payload.user_id, status: true } });
            if (!user) {
                return next(new AppError("Invalid token", STATUS_CODE.UNAUTHORIZED));
            }

            req.auth = {
                ...user.toJSON(),
                getUser: async () => {
                    const user = await User.findOne({ where: { user_id: payload.user_id, status: true } });
                    if (!user) {
                        throw new AppError(SERVER_ERROR, STATUS_CODE.INTERNAL_SERVER_ERROR);
                    }
                    return user;
                }
            };

            next();
        } catch (error) {
            console.log(error);
            next(new AppError(error.name, STATUS_CODE.UNAUTHORIZED));
        }
    };
}
