"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.debugRoleScopeMapping = exports.validateAllRoleMappings = exports.compareRoleAndScopeAbilities = exports.createRoleTestParams = exports.createStandardTestCases = exports.extractRolePermissions = exports.validateRoleInheritance = void 0;
/* eslint-disable no-console */
const ability_1 = require("@casl/ability");
const projectMemberRole_1 = require("../types/projectMemberRole");
const projectMemberAbility_1 = require("./projectMemberAbility");
const roleToScopeMapping_1 = require("./roleToScopeMapping");
const scopeAbilityBuilder_1 = require("./scopeAbilityBuilder");
/**
 * Test utilities for role to scope mapping validation
 * These functions are only used for testing migration compatibility
 */
/**
 * Validates that a role properly inherits permissions from lower roles
 */
const validateRoleInheritance = () => {
    const errors = [];
    const roleOrder = [
        projectMemberRole_1.ProjectMemberRole.VIEWER,
        projectMemberRole_1.ProjectMemberRole.INTERACTIVE_VIEWER,
        projectMemberRole_1.ProjectMemberRole.EDITOR,
        projectMemberRole_1.ProjectMemberRole.DEVELOPER,
        projectMemberRole_1.ProjectMemberRole.ADMIN,
    ];
    for (let i = 1; i < roleOrder.length; i += 1) {
        const currentRole = roleOrder[i];
        const previousRole = roleOrder[i - 1];
        const currentScopes = new Set((0, roleToScopeMapping_1.getAllScopesForRole)(currentRole));
        const previousScopes = (0, roleToScopeMapping_1.getAllScopesForRole)(previousRole);
        // Check that all previous scopes are included in current role
        for (const scope of previousScopes) {
            if (!currentScopes.has(scope)) {
                errors.push(`Role ${currentRole} is missing inherited scope: ${scope} from ${previousRole}`);
            }
        }
    }
    return {
        valid: errors.length === 0,
        errors,
    };
};
exports.validateRoleInheritance = validateRoleInheritance;
/**
 * Extracts the actual permissions granted by a role builder for analysis and comparison
 * This is useful for debugging and validating that our scope mappings are correct
 */
const extractRolePermissions = (role) => {
    const builder = new ability_1.AbilityBuilder(ability_1.Ability);
    const testMember = {
        role,
        projectUuid: 'test-project-uuid',
        userUuid: 'test-user-uuid',
    };
    // Build the ability using the role-based system
    projectMemberAbility_1.projectMemberAbilities[role](testMember, builder);
    const ability = builder.build();
    // Extract the rules for analysis
    return {
        rules: ability.rules.map((rule) => ({
            action: rule.action,
            subject: rule.subject,
            conditions: rule.conditions,
            inverted: rule.inverted,
            reason: rule.reason,
        })),
        rawAbility: ability,
    };
};
exports.extractRolePermissions = extractRolePermissions;
/**
 * Helper function to create standardized test cases for role compatibility testing
 */
const createStandardTestCases = () => [
    // View permissions
    {
        action: 'view',
        subject: 'Dashboard',
        resource: {
            organizationUuid: 'org-uuid-test',
            projectUuid: 'test-project-uuid',
            inheritsFromOrgOrProject: true,
        },
    },
    {
        action: 'view',
        subject: 'SavedChart',
        resource: {
            organizationUuid: 'org-uuid-test',
            projectUuid: 'test-project-uuid',
            inheritsFromOrgOrProject: true,
        },
    },
    {
        action: 'view',
        subject: 'Space',
        resource: {
            organizationUuid: 'org-uuid-test',
            projectUuid: 'test-project-uuid',
            inheritsFromOrgOrProject: true,
        },
    },
    {
        action: 'view',
        subject: 'Project',
        resource: { projectUuid: 'test-project-uuid' },
    },
    // Create permissions
    {
        action: 'create',
        subject: 'Space',
        resource: {
            organizationUuid: 'org-uuid-test',
            projectUuid: 'test-project-uuid',
        },
    },
    {
        action: 'create',
        subject: 'DashboardComments',
        resource: { projectUuid: 'test-project-uuid' },
    },
    {
        action: 'create',
        subject: 'ScheduledDeliveries',
        resource: { projectUuid: 'test-project-uuid' },
    },
    // Manage permissions (varies by role level)
    {
        action: 'manage',
        subject: 'Space',
        resource: {
            organizationUuid: 'org-uuid-test',
            projectUuid: 'test-project-uuid',
            inheritsFromOrgOrProject: true,
        },
    },
    {
        action: 'manage',
        subject: 'Job',
        resource: {},
    },
    {
        action: 'manage',
        subject: 'PinnedItems',
        resource: {
            organizationUuid: 'org-uuid-test',
            projectUuid: 'test-project-uuid',
        },
    },
    {
        action: 'manage',
        subject: 'Explore',
        resource: { projectUuid: 'test-project-uuid' },
    },
    // Higher-level permissions (developer+ only)
    {
        action: 'manage',
        subject: 'Project',
        resource: { projectUuid: 'test-project-uuid' },
    },
    {
        action: 'manage',
        subject: 'Validation',
        resource: { projectUuid: 'test-project-uuid' },
    },
    {
        action: 'manage',
        subject: 'VirtualView',
        resource: { projectUuid: 'test-project-uuid' },
    },
    {
        action: 'manage',
        subject: 'CustomSql',
        resource: { projectUuid: 'test-project-uuid' },
    },
    {
        action: 'manage',
        subject: 'CustomFields',
        resource: { projectUuid: 'test-project-uuid' },
    },
    {
        action: 'view',
        subject: 'CompiledSql',
        resource: { projectUuid: 'test-project-uuid' },
    },
    {
        action: 'manage',
        subject: 'CustomSqlTableCalculations',
        resource: { projectUuid: 'test-project-uuid' },
    },
    // Admin-only permissions
    {
        action: 'delete',
        subject: 'Project',
        resource: { projectUuid: 'test-project-uuid' },
    },
    {
        action: 'view',
        subject: 'Analytics',
        resource: { projectUuid: 'test-project-uuid' },
    },
];
exports.createStandardTestCases = createStandardTestCases;
/**
 * Helper function to create test parameters for role compatibility testing
 */
const createRoleTestParams = (role, options = {}) => {
    const { isEnterprise = false, projectUuid = 'test-project-uuid', userUuid = 'test-user-uuid', organizationUuid = 'test-org-uuid', } = options;
    const scopes = isEnterprise
        ? (0, roleToScopeMapping_1.getAllScopesForRole)(role)
        : (0, roleToScopeMapping_1.getNonEnterpriseScopesForRole)(role);
    const scopeBuilderParams = {
        userUuid,
        scopes,
        isEnterprise,
        organizationRole: 'editor',
        permissionsConfig: {
            pat: {
                enabled: false,
                allowedOrgRoles: [],
            },
        },
    };
    return {
        role,
        scopes,
        projectMember: {
            role,
            projectUuid,
            userUuid,
        },
        scopeOrgBuilderParams: {
            ...scopeBuilderParams,
            organizationUuid,
        },
        scopeProjectBuilderParams: {
            ...scopeBuilderParams,
            projectUuid,
        },
    };
};
exports.createRoleTestParams = createRoleTestParams;
/**
 * Compares role-based and scope-based abilities for a specific set of test cases
 * Returns detailed results showing which permissions match or differ
 */
const compareRoleAndScopeAbilities = (role, testCases, options = {}) => {
    const { isEnterprise = false } = options;
    const testParams = (0, exports.createRoleTestParams)(role, { isEnterprise });
    // Build role-based ability
    const roleBuilder = new ability_1.AbilityBuilder(ability_1.Ability);
    projectMemberAbility_1.projectMemberAbilities[role](testParams.projectMember, roleBuilder);
    const roleAbility = roleBuilder.build();
    // Build Project-based scope-based ability
    const scopeBuilder = new ability_1.AbilityBuilder(ability_1.Ability);
    (0, scopeAbilityBuilder_1.buildAbilityFromScopes)(testParams.scopeProjectBuilderParams, scopeBuilder);
    const scopeAbility = scopeBuilder.build();
    const results = testCases.map((testCase) => {
        const subjectWithResource = (0, ability_1.subject)(testCase.subject, testCase.resource);
        const roleResult = roleAbility.can(testCase.action, subjectWithResource);
        const scopeResult = scopeAbility.can(testCase.action, subjectWithResource);
        return {
            ...testCase,
            roleResult,
            scopeResult,
            match: roleResult === scopeResult,
        };
    });
    const summary = {
        total: results.length,
        matches: results.filter((r) => r.match).length,
        mismatches: results.filter((r) => !r.match),
        allMatch: results.every((r) => r.match),
    };
    return {
        role,
        scopes: testParams.scopes,
        results,
        summary,
    };
};
exports.compareRoleAndScopeAbilities = compareRoleAndScopeAbilities;
/**
 * Runs a comprehensive comparison of all roles against standard test cases
 */
const validateAllRoleMappings = (options = {}) => {
    const roles = [
        projectMemberRole_1.ProjectMemberRole.VIEWER,
        projectMemberRole_1.ProjectMemberRole.INTERACTIVE_VIEWER,
        projectMemberRole_1.ProjectMemberRole.EDITOR,
        projectMemberRole_1.ProjectMemberRole.DEVELOPER,
        projectMemberRole_1.ProjectMemberRole.ADMIN,
    ];
    const testCases = (0, exports.createStandardTestCases)();
    const results = roles.map((role) => (0, exports.compareRoleAndScopeAbilities)(role, testCases, options));
    const overallSummary = {
        rolesValidated: results.length,
        successfulRoles: results
            .filter((r) => r.summary.allMatch)
            .map((r) => r.role),
        failedRoles: results
            .filter((r) => !r.summary.allMatch)
            .map((r) => ({
            role: r.role,
            mismatches: r.summary.mismatches.length,
        })),
        totalTestCases: results.reduce((sum, r) => sum + r.summary.total, 0),
        totalMatches: results.reduce((sum, r) => sum + r.summary.matches, 0),
    };
    return {
        roleResults: results,
        overallSummary,
        allRolesValid: overallSummary.failedRoles.length === 0,
    };
};
exports.validateAllRoleMappings = validateAllRoleMappings;
/**
 * Debug utility to show what scopes are missing or extra for a specific role
 */
const debugRoleScopeMapping = (role) => {
    const testCases = (0, exports.createStandardTestCases)();
    const comparison = (0, exports.compareRoleAndScopeAbilities)(role, testCases);
    const mismatches = comparison.results.filter((r) => !r.match);
    console.debug(`\n=== Debug: ${role} Role Scope Mapping ===`);
    console.debug(`Scopes assigned: ${comparison.scopes.length}`);
    console.debug(`Test cases: ${comparison.summary.total}`);
    console.debug(`Matches: ${comparison.summary.matches}`);
    console.debug(`Mismatches: ${mismatches.length}`);
    if (mismatches.length > 0) {
        console.debug('\n--- Mismatched Permissions ---');
        mismatches.forEach((mismatch) => {
            console.debug(`${mismatch.action}:${mismatch.subject}`);
            console.debug(`  Role-based: ${mismatch.roleResult}`);
            console.debug(`  Scope-based: ${mismatch.scopeResult}`);
            console.debug(`  Resource:`, mismatch.resource);
            console.debug('');
        });
    }
    console.debug(`\nAssigned Scopes:`);
    comparison.scopes.forEach((scope) => console.debug(`  - ${scope}`));
    return comparison;
};
exports.debugRoleScopeMapping = debugRoleScopeMapping;
//# sourceMappingURL=roleToScopeMapping.testUtils.js.map