"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.authenticate = authenticate;
exports.requireAdminRole = requireAdminRole;
exports.optionalAuth = optionalAuth;
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
const client_1 = require("@prisma/client");
const database_1 = require("../../../config/database");
const env_1 = require("../../../config/env");
const roles_1 = require("../../../utils/roles");
/**
 * Authenticate user via V2 JWT access token
 * Verifies token and checks user status in Prisma database
 */
async function authenticate(request, reply) {
    const authHeader = request.headers.authorization;
    const queryToken = request.query?.token;
    // Support both Authorization header and ?token= query param (for <img>/<video> src)
    let token = null;
    if (authHeader?.startsWith('Bearer ')) {
        token = authHeader.substring(7);
    }
    else if (queryToken) {
        token = queryToken;
    }
    if (!token) {
        return reply.status(401).send({
            error: 'Authentication required',
            code: 'AUTH_REQUIRED'
        });
    }
    // Verify JWT with V2 access secret
    let payload;
    try {
        payload = jsonwebtoken_1.default.verify(token, env_1.env.JWT_ACCESS_SECRET, { algorithms: ['HS256'] });
    }
    catch (error) {
        return reply.status(401).send({
            error: 'Invalid or expired token',
            code: 'INVALID_TOKEN'
        });
    }
    // Verify user still exists and is active
    const user = await database_1.prisma.user.findUnique({
        where: { id: payload.id },
        select: {
            id: true,
            email: true,
            role: true,
            roles: true,
            status: true,
            expiresAt: true,
        },
    });
    if (!user) {
        return reply.status(401).send({
            error: 'User not found',
            code: 'USER_NOT_FOUND'
        });
    }
    if (user.status !== client_1.UserStatus.ACTIVE) {
        return reply.status(403).send({
            error: `Account is ${user.status.toLowerCase()}`,
            code: 'ACCOUNT_INACTIVE'
        });
    }
    // Check expiration if set
    if (user.expiresAt && user.expiresAt < new Date()) {
        return reply.status(403).send({
            error: 'Account has expired',
            code: 'ACCOUNT_EXPIRED'
        });
    }
    // Attach user to request
    const userRoles = (0, roles_1.getUserRoles)(user);
    request.user = {
        id: user.id,
        email: user.email,
        role: user.role,
        roles: userRoles,
    };
}
/**
 * Require admin role (SUPER_ADMIN, INFLUENCE_ADMIN, or MAP_ADMIN)
 * Also checks auth, so no need to use authenticate() separately
 */
async function requireAdminRole(request, reply) {
    // First authenticate
    await authenticate(request, reply);
    // If authenticate sent a response, stop here
    if (reply.sent) {
        return;
    }
    // Check admin role using multi-role utility
    if (!request.user || !(0, roles_1.hasAnyRole)(request.user, roles_1.MEDIA_ROLES)) {
        return reply.status(403).send({
            error: 'Admin access required',
            code: 'ADMIN_REQUIRED'
        });
    }
}
/**
 * Optional authentication - attach user if token present, but don't require it
 * Used for public endpoints that want to know if user is logged in
 */
async function optionalAuth(request, _reply) {
    const authHeader = request.headers.authorization;
    const queryToken = request.query?.token;
    let token = null;
    if (authHeader?.startsWith('Bearer ')) {
        token = authHeader.substring(7);
    }
    else if (queryToken) {
        token = queryToken;
    }
    if (!token) {
        return;
    }
    try {
        const payload = jsonwebtoken_1.default.verify(token, env_1.env.JWT_ACCESS_SECRET, { algorithms: ['HS256'] });
        // Verify user exists and is active
        const user = await database_1.prisma.user.findUnique({
            where: { id: payload.id },
            select: {
                id: true,
                email: true,
                role: true,
                roles: true,
                status: true,
            },
        });
        if (user && user.status === client_1.UserStatus.ACTIVE) {
            const userRoles = (0, roles_1.getUserRoles)(user);
            request.user = {
                id: user.id,
                email: user.email,
                role: user.role,
                roles: userRoles,
            };
        }
    }
    catch {
        // Invalid token, just ignore and continue without user
    }
}
//# sourceMappingURL=auth.js.map