var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { PermissionProviderBase, } from '@memberjunction/core';
import { RegisterClass, UUIDsEqual } from '@memberjunction/global';
/**
 * Wraps `MJ: AI Skill Permissions` behind the unified {@link PermissionProviderBase} contract —
 * the closed-by-default, explicit-grants view that powers the Sharing Center and audit.
 *
 * This is the skill sibling of `AIAgentPermissionProvider`. AISkillPermission rows grant either a
 * User (via UserID) or a Role (via RoleID) — never both; the server entity enforces this. Action
 * mapping:
 * - CanView → `Read`
 * - CanRun  → `Execute`  (request/activate the skill at agent runtime)
 * - CanEdit → `Update`
 * - CanDelete → `Delete`
 *
 * User+Role grants for the same user are OR-aggregated (any grant of an action suffices).
 *
 * `resourceType` is `"AI Skills"`. `resourceId` is the skill ID. NOTE: this provider reports only
 * explicit grants; the open-by-default runtime behavior (no rows → View+Run for everyone) lives in
 * `AISkillPermissionHelper` — see guides/UNIFIED_PERMISSIONS_GUIDE.md for why the two paths differ.
 */
let AISkillPermissionProvider = class AISkillPermissionProvider extends PermissionProviderBase {
    constructor() {
        super(...arguments);
        this.DomainName = 'AI Skill Permissions';
        this.Description = 'User- or role-level permissions on AI skills. Actions: View (Read), Run (Execute), Edit (Update), Delete.';
        this.SupportedGranteeTypes = ['User', 'Role'];
        this.SupportedActions = ['Read', 'Execute', 'Update', 'Delete'];
        this.SupportsDeny = false;
    }
    GetResourceTypes() {
        return ['AI Skills'];
    }
    async CheckPermission(user, _resourceType, resourceId, action) {
        if (!resourceId) {
            return {
                Allowed: false,
                DomainName: this.DomainName,
                Reason: 'AI Skill permissions require a specific skill ID',
            };
        }
        const rows = await this.fetchPermissionsForSkill(resourceId);
        const actions = this.actionsForUser(user, rows);
        const allowed = actions.includes(action);
        return {
            Allowed: allowed,
            DomainName: this.DomainName,
            Reason: allowed
                ? `User has ${action} via user or role grant on skill '${resourceId}'`
                : `User has no ${action} permission on skill '${resourceId}'`,
        };
    }
    async GetEffectivePermissions(user, _resourceType, resourceId) {
        const rows = await this.fetchPermissionsForSkill(resourceId);
        const actions = this.actionsForUser(user, rows);
        if (actions.length === 0)
            return [];
        const nameMap = await this.bulkLookupNames('MJ: AI Skills', [resourceId]);
        return [this.buildNormalizedPermission({
                resourceType: 'AI Skills', resourceId, resourceName: nameMap.get(resourceId),
                granteeType: 'User', granteeId: user.ID, granteeName: user.Name, actions,
            })];
    }
    async GetUserResources(user, resourceType) {
        if (resourceType && resourceType !== 'AI Skills')
            return [];
        const userRoleIds = (user.UserRoles ?? []).map((ur) => ur.RoleID);
        const userFilter = `UserID='${user.ID}'`;
        const roleFilter = userRoleIds.length ? `RoleID IN (${userRoleIds.map((r) => `'${r}'`).join(',')})` : null;
        const combinedFilter = roleFilter ? `(${userFilter}) OR (${roleFilter})` : userFilter;
        const rows = await this.fetchRows('MJ: AI Skill Permissions', combinedFilter, ['ID', 'SkillID', 'RoleID', 'UserID', 'CanView', 'CanRun', 'CanEdit', 'CanDelete'], 'GetUserResources');
        // Group by skill and aggregate actions.
        const bySkill = new Map();
        for (const row of rows) {
            const bucket = bySkill.get(row.SkillID) ?? { actions: new Set(), sourceIds: [] };
            for (const a of this.rowActions(row))
                bucket.actions.add(a);
            bucket.sourceIds.push(row.ID);
            bySkill.set(row.SkillID, bucket);
        }
        if (bySkill.size === 0)
            return [];
        const nameMap = await this.bulkLookupNames('MJ: AI Skills', Array.from(bySkill.keys()));
        const results = [];
        for (const [skillId, { actions, sourceIds }] of bySkill) {
            if (actions.size === 0)
                continue;
            results.push(this.buildNormalizedPermission({
                resourceType: 'AI Skills', resourceId: skillId, resourceName: nameMap.get(skillId),
                granteeType: 'User', granteeId: user.ID, granteeName: user.Name,
                actions: Array.from(actions),
                sourceRecordId: sourceIds.length === 1 ? sourceIds[0] : undefined,
            }));
        }
        return results;
    }
    async GetResourcePermissions(resourceType, resourceId) {
        if (resourceType !== 'AI Skills')
            return [];
        const rows = await this.fetchRows('MJ: AI Skill Permissions', `SkillID='${resourceId}'`, ['ID', 'SkillID', 'RoleID', 'UserID', 'Role', 'User', 'CanView', 'CanRun', 'CanEdit', 'CanDelete'], 'GetResourcePermissions');
        if (rows.length === 0)
            return [];
        const nameMap = await this.bulkLookupNames('MJ: AI Skills', [resourceId]);
        const resourceName = nameMap.get(resourceId);
        const results = [];
        for (const row of rows) {
            const actions = this.rowActions(row);
            if (actions.length === 0)
                continue;
            const isUser = row.UserID != null;
            results.push(this.buildNormalizedPermission({
                resourceType: 'AI Skills', resourceId, resourceName,
                granteeType: isUser ? 'User' : 'Role',
                granteeId: isUser ? row.UserID : row.RoleID,
                granteeName: isUser ? row.User ?? undefined : row.Role ?? undefined,
                actions,
                sourceRecordId: row.ID,
            }));
        }
        return results;
    }
    async fetchPermissionsForSkill(skillId) {
        return this.fetchRows('MJ: AI Skill Permissions', `SkillID='${skillId}'`, ['ID', 'SkillID', 'RoleID', 'UserID', 'CanView', 'CanRun', 'CanEdit', 'CanDelete'], 'fetchPermissionsForSkill');
    }
    actionsForUser(user, rows) {
        const set = new Set();
        for (const row of rows) {
            const matches = (row.UserID && UUIDsEqual(row.UserID, user.ID)) ||
                (row.RoleID && user.UserRoles?.some((ur) => UUIDsEqual(ur.RoleID, row.RoleID)));
            if (!matches)
                continue;
            for (const a of this.rowActions(row))
                set.add(a);
        }
        return Array.from(set);
    }
    rowActions(row) {
        return this.boolsToActions({
            Read: row.CanView,
            Execute: row.CanRun,
            Update: row.CanEdit,
            Delete: row.CanDelete,
        });
    }
};
AISkillPermissionProvider = __decorate([
    RegisterClass(PermissionProviderBase, 'MJAISkillPermissionProvider')
], AISkillPermissionProvider);
export { AISkillPermissionProvider };
//# sourceMappingURL=AISkillPermissionProvider.js.map