"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.requireAdmin = exports.requireStaff = exports.requireAuth = exports.optionalAuth = void 0;
const drizzle_orm_1 = require("drizzle-orm");
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
const index_js_1 = require("../db/index.js");
const schema_js_1 = require("../db/schema.js");
const authSerializers_js_1 = require("../services/authSerializers.js");
const authSecurity_js_1 = require("../services/authSecurity.js");
const apiResponse_js_1 = require("../utils/apiResponse.js");
const getBearerToken = (authorization) => {
    if (!authorization)
        return null;
    const [scheme, token] = authorization.split(" ");
    if (scheme !== "Bearer" || !token)
        return null;
    return token;
};
const optionalAuth = async (req, res, next) => {
    const token = getBearerToken(req.headers.authorization);
    if (!token)
        return next();
    try {
        const payload = (0, authSecurity_js_1.verifyAuthToken)(token);
        const id = Number(payload.sub);
        if (!Number.isInteger(id) || id <= 0) {
            return (0, apiResponse_js_1.sendError)(res, 401, "INVALID_TOKEN", "Invalid authentication token.");
        }
        if (payload.actorType === "customer") {
            const [customer] = await index_js_1.db.select().from(schema_js_1.customers).where((0, drizzle_orm_1.eq)(schema_js_1.customers.id, id)).limit(1);
            if (!customer)
                return (0, apiResponse_js_1.sendError)(res, 401, "INVALID_TOKEN", "Invalid authentication token.");
            req.auth = { actorType: "customer", customer: (0, authSerializers_js_1.toPublicCustomer)(customer) };
            return next();
        }
        if (payload.actorType === "staff") {
            const [staff] = await index_js_1.db.select().from(schema_js_1.staffUsers).where((0, drizzle_orm_1.eq)(schema_js_1.staffUsers.id, id)).limit(1);
            if (!staff || !staff.isActive)
                return (0, apiResponse_js_1.sendError)(res, 401, "INVALID_TOKEN", "Invalid authentication token.");
            req.auth = { actorType: "staff", staff: (0, authSerializers_js_1.toPublicStaffUser)(staff) };
            return next();
        }
        return (0, apiResponse_js_1.sendError)(res, 401, "INVALID_TOKEN", "Invalid authentication token.");
    }
    catch (error) {
        if (error instanceof jsonwebtoken_1.default.TokenExpiredError) {
            return (0, apiResponse_js_1.sendError)(res, 401, "TOKEN_EXPIRED", "Authentication token expired.");
        }
        return (0, apiResponse_js_1.sendError)(res, 401, "INVALID_TOKEN", "Invalid authentication token.");
    }
};
exports.optionalAuth = optionalAuth;
const requireAuth = async (req, res, next) => {
    await (0, exports.optionalAuth)(req, res, () => {
        if (!req.auth)
            return (0, apiResponse_js_1.sendError)(res, 401, "UNAUTHENTICATED", "Authentication required.");
        next();
    });
};
exports.requireAuth = requireAuth;
const requireStaff = async (req, res, next) => {
    await (0, exports.requireAuth)(req, res, () => {
        if (req.auth?.actorType !== "staff") {
            return (0, apiResponse_js_1.sendError)(res, 403, "FORBIDDEN", "Staff access required.");
        }
        next();
    });
};
exports.requireStaff = requireStaff;
const requireAdmin = async (req, res, next) => {
    await (0, exports.requireStaff)(req, res, () => {
        if (req.auth?.actorType !== "staff" || req.auth.staff.role !== "admin") {
            return (0, apiResponse_js_1.sendError)(res, 403, "FORBIDDEN", "Admin access required.");
        }
        next();
    });
};
exports.requireAdmin = requireAdmin;
//# sourceMappingURL=authMiddleware.js.map