import { getPrismaClient } from '../db/prisma.js';
import { createLogger } from '@4runr/shared';
import { authenticator } from 'otplib';
import { openMfaSecret } from '../crypto/mfa-storage.js';
const logger = createLogger('Gateway:Auth:MFA');
async function isAdmin(userId) {
    try {
        const prisma = await getPrismaClient();
        const user = await prisma.user.findUnique({
            where: { id: userId },
            include: {
                roles: {
                    include: {
                        role: true
                    }
                }
            }
        });
        if (!user)
            return false;
        return user.roles.some(ur => ur.role.name === 'admin');
    }
    catch (error) {
        logger.error('Error checking admin role', { error, userId });
        return false;
    }
}
async function verifyMFA(userId, token) {
    try {
        const prisma = await getPrismaClient();
        const user = await prisma.user.findUnique({
            where: { id: userId }
        });
        if (!user || !user.mfaEnabled || !user.mfaSecret) {
            return false;
        }
        const secret = openMfaSecret(user.mfaSecret);
        if (!secret) {
            return false;
        }
        const isValid = authenticator.verify({ token, secret });
        if (isValid) {
            await prisma.user.update({
                where: { id: userId },
                data: { mfaVerifiedAt: new Date() }
            });
        }
        return isValid;
    }
    catch (error) {
        logger.error('Error verifying MFA', { error, userId });
        return false;
    }
}
export async function requireMFA(request, reply) {
    const auth = request.auth || request.user;
    if (!auth || !auth.sub) {
        reply.status(401).send({
            error: 'unauthorized',
            message: 'Authentication required'
        });
        return;
    }
    const userId = auth.sub;
    const isAdminUser = await isAdmin(userId);
    if (!isAdminUser) {
        return;
    }
    const prisma = await getPrismaClient();
    const user = await prisma.user.findUnique({
        where: { id: userId }
    });
    if (!user || !user.mfaEnabled) {
        logger.warn('Admin user without MFA', { userId });
        return;
    }
    const mfaToken = request.headers['x-mfa-token'];
    if (!mfaToken) {
        reply.status(403).send({
            error: 'mfa_required',
            message: 'MFA token required for admin access',
            mfaRequired: true
        });
        return;
    }
    const isValid = await verifyMFA(userId, mfaToken);
    if (!isValid) {
        reply.status(403).send({
            error: 'mfa_invalid',
            message: 'Invalid MFA token'
        });
        return;
    }
    request.mfaVerified = true;
}
//# sourceMappingURL=mfa.js.map