"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getEscalationTargets = getEscalationTargets;
exports.getAllEscalationChains = getAllEscalationChains;
exports.addEscalationChain = addEscalationChain;
exports.removeEscalationChain = removeEscalationChain;
exports.replaceEscalationTargets = replaceEscalationTargets;
exports.canEscalateTo = canEscalateTo;
exports.listDistinctRoles = listDistinctRoles;
exports.listRolesWithDetails = listRolesWithDetails;
exports.createRole = createRole;
exports.deleteRole = deleteRole;
const db_1 = require("../../lib/db");
const user_1 = require("../user");
const sql_1 = require("./sql");
/**
 * Get the roles a given source role can escalate to.
 */
async function getEscalationTargets(sourceRole) {
    const pool = (0, db_1.getPool)();
    const { rows } = await pool.query(sql_1.GET_ESCALATION_TARGETS, [sourceRole]);
    return rows.map((r) => r.target_role);
}
/**
 * Get all escalation chain pairs.
 */
async function getAllEscalationChains() {
    const pool = (0, db_1.getPool)();
    const { rows } = await pool.query(sql_1.GET_ALL_ESCALATION_CHAINS);
    return rows;
}
/**
 * Add a single escalation chain entry.
 */
async function addEscalationChain(sourceRole, targetRole) {
    const pool = (0, db_1.getPool)();
    await pool.query(sql_1.ENSURE_ROLE_EXISTS, [sourceRole]);
    await pool.query(sql_1.ENSURE_ROLE_EXISTS, [targetRole]);
    await pool.query(sql_1.INSERT_ESCALATION_CHAIN, [sourceRole, targetRole]);
}
/**
 * Remove a single escalation chain entry.
 */
async function removeEscalationChain(sourceRole, targetRole) {
    const pool = (0, db_1.getPool)();
    const { rowCount } = await pool.query(sql_1.DELETE_ESCALATION_CHAIN, [sourceRole, targetRole]);
    return (rowCount ?? 0) > 0;
}
/**
 * Replace all escalation targets for a source role.
 */
async function replaceEscalationTargets(sourceRole, targets) {
    const pool = (0, db_1.getPool)();
    const client = await pool.connect();
    try {
        await client.query('BEGIN');
        await client.query(sql_1.ENSURE_ROLE_EXISTS, [sourceRole]);
        for (const target of targets) {
            await client.query(sql_1.ENSURE_ROLE_EXISTS, [target]);
        }
        await client.query(sql_1.DELETE_ESCALATION_CHAINS_BY_SOURCE, [sourceRole]);
        for (const target of targets) {
            await client.query(sql_1.INSERT_ESCALATION_CHAIN, [sourceRole, target]);
        }
        await client.query('COMMIT');
    }
    catch (err) {
        await client.query('ROLLBACK');
        throw err;
    }
    finally {
        client.release();
    }
}
/**
 * Check whether a user can escalate from sourceRole to targetRole.
 * Superadmins can escalate to any role.
 * Others must hold the sourceRole AND the chain must exist.
 */
async function canEscalateTo(userId, sourceRole, targetRole) {
    if (await (0, user_1.isSuperAdmin)(userId))
        return true;
    if (!(await (0, user_1.hasRole)(userId, sourceRole)))
        return false;
    const pool = (0, db_1.getPool)();
    const { rows } = await pool.query(sql_1.CHECK_ESCALATION_CHAIN_EXISTS, [sourceRole, targetRole]);
    return rows.length > 0;
}
/**
 * List all distinct role names known to the system.
 * lt_roles is the canonical source — all other tables reference it via FK.
 */
async function listDistinctRoles() {
    const pool = (0, db_1.getPool)();
    const { rows } = await pool.query(sql_1.LIST_ROLES);
    return rows.map((r) => r.role);
}
/**
 * List all roles with usage counts (users, escalation chains, workflows).
 */
async function listRolesWithDetails() {
    const pool = (0, db_1.getPool)();
    const { rows } = await pool.query(sql_1.LIST_ROLES_WITH_DETAILS);
    return rows;
}
/**
 * Create a standalone role entry.
 */
async function createRole(role) {
    const pool = (0, db_1.getPool)();
    await pool.query(sql_1.ENSURE_ROLE_EXISTS, [role]);
}
/**
 * Delete a role. Returns an error message if the role is referenced.
 */
async function deleteRole(role) {
    const pool = (0, db_1.getPool)();
    const { rows: userRefs } = await pool.query(sql_1.COUNT_USER_ROLE_REFS, [role]);
    if (userRefs[0].cnt > 0) {
        return { deleted: false, error: `Role is assigned to ${userRefs[0].cnt} user(s). Remove those assignments first.` };
    }
    const { rows: chainRefs } = await pool.query(sql_1.COUNT_CHAIN_REFS, [role]);
    if (chainRefs[0].cnt > 0) {
        return { deleted: false, error: `Role is referenced in ${chainRefs[0].cnt} escalation chain(s). Remove those chains first.` };
    }
    const { rows: wfRefs } = await pool.query(sql_1.COUNT_WORKFLOW_REFS, [role]);
    if (wfRefs[0].cnt > 0) {
        return { deleted: false, error: `Role is used by ${wfRefs[0].cnt} workflow config(s). Remove those references first.` };
    }
    const { rows: escRefs } = await pool.query(sql_1.COUNT_ACTIVE_ESCALATION_REFS, [role]);
    if (escRefs[0].cnt > 0) {
        return { deleted: false, error: `Role has ${escRefs[0].cnt} active escalation(s). Resolve them first.` };
    }
    const { rowCount } = await pool.query(sql_1.DELETE_ROLE, [role]);
    return { deleted: (rowCount ?? 0) > 0 };
}
