"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.usersRouter = void 0;
const express_1 = require("express");
const zod_1 = require("zod");
const client_1 = require("@prisma/client");
const users_service_1 = require("./users.service");
const users_schemas_1 = require("./users.schemas");
const validate_1 = require("../../middleware/validate");
const auth_middleware_1 = require("../../middleware/auth.middleware");
const rbac_middleware_1 = require("../../middleware/rbac.middleware");
const roles_1 = require("../../utils/roles");
const database_1 = require("../../config/database");
const email_service_1 = require("../../services/email.service");
const env_1 = require("../../config/env");
const logger_1 = require("../../utils/logger");
const provisioning_service_1 = require("../../services/user-provisioning/provisioning.service");
/** Check if user can manage other users (SUPER_ADMIN or canManageUsers permission) */
function canManageUsers(user) {
    const roles = (0, roles_1.getUserRoles)(user);
    if (roles.includes(client_1.UserRole.SUPER_ADMIN))
        return true;
    return !!user.permissions?.canManageUsers;
}
/** Middleware: require user management permission */
function requireUserManagement(req, res, next) {
    if (!req.user) {
        res.status(401).json({ error: { message: 'Authentication required', code: 'AUTH_REQUIRED' } });
        return;
    }
    if (!canManageUsers(req.user)) {
        res.status(403).json({ error: { message: 'Insufficient permissions', code: 'FORBIDDEN' } });
        return;
    }
    next();
}
const router = (0, express_1.Router)();
exports.usersRouter = router;
// All user routes require authentication
router.use(auth_middleware_1.authenticate);
// GET /api/users — list users (any admin)
router.get('/', (0, rbac_middleware_1.requireRole)(...roles_1.ADMIN_ROLES), (0, validate_1.validate)(users_schemas_1.listUsersSchema, 'query'), async (req, res, next) => {
    try {
        const result = await users_service_1.usersService.findAll(req.query);
        res.json(result);
    }
    catch (err) {
        next(err);
    }
});
// GET /api/users/:id — get user (admin or self)
router.get('/:id', async (req, res, next) => {
    try {
        const id = req.params.id;
        const isAdminUser = (0, roles_1.hasAnyRole)(req.user, roles_1.ADMIN_ROLES);
        const isSelf = req.user.id === id;
        if (!isAdminUser && !isSelf) {
            res.status(403).json({ error: { message: 'Insufficient permissions', code: 'FORBIDDEN' } });
            return;
        }
        const user = await users_service_1.usersService.findById(id);
        res.json(user);
    }
    catch (err) {
        next(err);
    }
});
// POST /api/users — create user (SUPER_ADMIN or canManageUsers)
router.post('/', requireUserManagement, (0, validate_1.validate)(users_schemas_1.createUserSchema), async (req, res, next) => {
    try {
        const user = await users_service_1.usersService.create(req.body);
        res.status(201).json(user);
    }
    catch (err) {
        next(err);
    }
});
// PUT /api/users/:id — update user (admin or self, role changes require user management perm)
router.put('/:id', async (req, res, next) => {
    try {
        const id = req.params.id;
        const isAdminUser = (0, roles_1.hasAnyRole)(req.user, roles_1.ADMIN_ROLES);
        const isSelf = req.user.id === id;
        const canManage = canManageUsers(req.user);
        if (!isAdminUser && !isSelf) {
            res.status(403).json({ error: { message: 'Insufficient permissions', code: 'FORBIDDEN' } });
            return;
        }
        // Only users with management permission can change role, roles, or status
        if (!canManage) {
            delete req.body.role;
            delete req.body.roles;
            delete req.body.status;
            delete req.body.permissions;
        }
        const parsed = users_schemas_1.updateUserSchema.parse(req.body);
        const user = await users_service_1.usersService.update(id, parsed);
        res.json(user);
    }
    catch (err) {
        next(err);
    }
});
// POST /api/users/:id/approve — approve pending user (SUPER_ADMIN or canManageUsers)
router.post('/:id/approve', requireUserManagement, async (req, res, next) => {
    try {
        const id = req.params.id;
        const user = await database_1.prisma.user.findUnique({ where: { id } });
        if (!user) {
            res.status(404).json({ error: { message: 'User not found', code: 'USER_NOT_FOUND' } });
            return;
        }
        if (user.status !== client_1.UserStatus.PENDING_APPROVAL) {
            res.status(400).json({ error: { message: 'User is not pending approval', code: 'INVALID_STATUS' } });
            return;
        }
        await database_1.prisma.user.update({
            where: { id },
            data: { status: client_1.UserStatus.ACTIVE },
        });
        // Send approval notification email
        const adminUrl = env_1.env.ADMIN_URL || 'http://localhost:3000';
        await email_service_1.emailService.sendAccountApprovedEmail({
            recipientEmail: user.email,
            recipientName: user.name || 'there',
            loginUrl: `${adminUrl}/login`,
        }).catch(err => logger_1.logger.error('Failed to send approval email:', err));
        // Fire-and-forget: provision approved user to eager services
        provisioning_service_1.userProvisioningService.onUserCreated({
            id: user.id, email: user.email, name: user.name, role: user.role,
            roles: user.roles, status: 'ACTIVE', permissions: user.permissions,
        }).catch(err => logger_1.logger.warn('User provisioning hook (approve) failed:', err));
        res.json({ message: 'User approved', userId: id });
    }
    catch (err) {
        next(err);
    }
});
// POST /api/users/:id/reject — reject pending user (SUPER_ADMIN or canManageUsers)
const rejectSchema = zod_1.z.object({
    reason: zod_1.z.string().max(500).optional(),
});
router.post('/:id/reject', requireUserManagement, (0, validate_1.validate)(rejectSchema), async (req, res, next) => {
    try {
        const id = req.params.id;
        const user = await database_1.prisma.user.findUnique({ where: { id } });
        if (!user) {
            res.status(404).json({ error: { message: 'User not found', code: 'USER_NOT_FOUND' } });
            return;
        }
        if (user.status !== client_1.UserStatus.PENDING_APPROVAL) {
            res.status(400).json({ error: { message: 'User is not pending approval', code: 'INVALID_STATUS' } });
            return;
        }
        await database_1.prisma.user.update({
            where: { id },
            data: { status: client_1.UserStatus.INACTIVE },
        });
        res.json({ message: 'User rejected', userId: id });
    }
    catch (err) {
        next(err);
    }
});
// GET /api/users/:id/contact — get linked Contact for a user (any admin)
router.get('/:id/contact', (0, rbac_middleware_1.requireRole)(...roles_1.ADMIN_ROLES), async (req, res, next) => {
    try {
        const id = req.params.id;
        const contact = await database_1.prisma.contact.findFirst({
            where: { userId: id, mergedIntoId: null },
            select: {
                id: true, displayName: true, email: true, phone: true,
                tags: true, supportLevel: true, primarySource: true,
                profileToken: true, coverPhotoPath: true,
            },
        });
        res.json({ contact: contact || null });
    }
    catch (err) {
        next(err);
    }
});
// DELETE /api/users/:id — delete user (SUPER_ADMIN or canManageUsers)
router.delete('/:id', requireUserManagement, async (req, res, next) => {
    try {
        const id = req.params.id;
        await users_service_1.usersService.delete(id);
        res.status(204).send();
    }
    catch (err) {
        next(err);
    }
});
//# sourceMappingURL=users.routes.js.map