import { z } from 'zod';
import { globalOptionsZod } from '../../../../Command.js';
import GraphCommand from '../../../base/GraphCommand.js';
import commands from '../../commands.js';
import request from '../../../../request.js';
import { validation } from '../../../../utils/validation.js';
import { entraAdministrativeUnit } from '../../../../utils/entraAdministrativeUnit.js';
import { entraApp } from '../../../../utils/entraApp.js';
import { entraServicePrincipal } from '../../../../utils/entraServicePrincipal.js';
import { entraGroup } from '../../../../utils/entraGroup.js';
import { roleDefinition } from '../../../../utils/roleDefinition.js';
import { entraUser } from '../../../../utils/entraUser.js';
export const options = z.strictObject({
    ...globalOptionsZod.shape,
    roleDefinitionId: z.uuid().optional(),
    roleDefinitionName: z.string().optional(),
    principal: z.string().refine(principal => validation.isValidGuid(principal) || validation.isValidUserPrincipalName(principal) || validation.isValidMailNickname(principal), {
        error: e => `'${e.input}' is not a valid GUID, UPN or group mail nickname.`
    }),
    userId: z.uuid().optional(),
    userName: z.string().refine(upn => validation.isValidUserPrincipalName(upn), {
        error: e => `'${e.input}' is not a valid UPN.`
    }).optional(),
    administrativeUnitId: z.uuid().optional(),
    administrativeUnitName: z.string().optional(),
    applicationId: z.uuid().optional(),
    applicationObjectId: z.uuid().optional(),
    applicationName: z.string().optional(),
    servicePrincipalId: z.uuid().optional(),
    servicePrincipalName: z.string().optional(),
    groupId: z.uuid().optional(),
    groupName: z.string().optional()
});
class EntraRoleAssignmentAddCommand extends GraphCommand {
    get name() {
        return commands.ROLEASSIGNMENT_ADD;
    }
    get description() {
        return 'Assigns a Entra ID role to a user and specifies the scope for which the user has been granted access';
    }
    get schema() {
        return options;
    }
    getRefinedSchema(schema) {
        return schema
            .refine(options => [options.roleDefinitionId, options.roleDefinitionName].filter(o => o !== undefined).length === 1, {
            error: 'Specify either roleDefinitionId or roleDefinitionName',
            params: {
                customCode: 'optionSet',
                options: ['roleDefinitionId', 'roleDefinitionName']
            }
        })
            .refine(options => Object.values([
            options.userId, options.userName, options.administrativeUnitId, options.administrativeUnitName, options.applicationId, options.applicationObjectId, options.applicationName,
            options.servicePrincipalId, options.servicePrincipalName, options.groupId, options.groupName
        ]).filter(v => typeof v !== 'undefined').length < 2, {
            message: 'Provide value for only one of the following parameters: userId, userName, administrativeUnitId, administrativeUnitName, applicationId, applicationObjectId, applicationName, servicePrincipalId, servicePrincipalName, groupId or groupName',
            params: {
                customCode: 'optionSet',
                options: ['userId', 'userName', 'administrativeUnitId', 'administrativeUnitName', 'applicationId', 'applicationObjectId', 'applicationName', 'servicePrincipalId', 'servicePrincipalName', 'groupId', 'groupName']
            }
        });
    }
    async commandAction(logger, args) {
        try {
            const roleDefinitionId = await this.getRoleDefinitionId(args.options, logger);
            const data = {
                roleDefinitionId: roleDefinitionId,
                principalId: await this.getPrincipalId(args.options, logger),
                directoryScopeId: await this.getDirectoryScopeId(args.options)
            };
            const requestOptions = {
                url: `${this.resource}/v1.0/roleManagement/directory/roleAssignments`,
                headers: {
                    accept: 'application/json;odata.metadata=none'
                },
                responseType: 'json',
                data: data
            };
            const response = await request.post(requestOptions);
            await logger.log(response);
        }
        catch (err) {
            this.handleRejectedODataJsonPromise(err);
        }
    }
    async getRoleDefinitionId(options, logger) {
        if (options.roleDefinitionId) {
            return options.roleDefinitionId;
        }
        if (this.verbose) {
            await logger.logToStderr(`Retrieving role definition by its name '${options.roleDefinitionName}'`);
        }
        const role = await roleDefinition.getRoleDefinitionByDisplayName(options.roleDefinitionName);
        return role.id;
    }
    async getPrincipalId(options, logger) {
        if (validation.isValidGuid(options.principal)) {
            return options.principal;
        }
        if (validation.isValidUserPrincipalName(options.principal)) {
            if (this.verbose) {
                await logger.logToStderr(`Retrieving user id by UPN '${options.principal}'`);
            }
            return await entraUser.getUserIdByUpn(options.principal);
        }
        if (this.verbose) {
            await logger.logToStderr(`Retrieving group id by mail nickname '${options.principal}'`);
        }
        return await entraGroup.getGroupIdByMailNickname(options.principal);
    }
    async getDirectoryScopeId(options) {
        let prefix = '/';
        let resourceId = '';
        if (options.userId || options.userName) {
            resourceId = options.userId || await entraUser.getUserIdByUpn(options.userName);
        }
        else if (options.administrativeUnitId || options.administrativeUnitName) {
            prefix = '/administrativeUnits/';
            resourceId = options.administrativeUnitId || (await entraAdministrativeUnit.getAdministrativeUnitByDisplayName(options.administrativeUnitName, "id")).id;
        }
        else if (options.applicationId || options.applicationObjectId || options.applicationName) {
            resourceId = options.applicationObjectId;
            if (options.applicationId) {
                resourceId = (await entraApp.getAppRegistrationByAppId(options.applicationId, ["id"])).id;
            }
            else if (options.applicationName) {
                resourceId = (await entraApp.getAppRegistrationByAppName(options.applicationName, ["id"])).id;
            }
        }
        else if (options.servicePrincipalId || options.servicePrincipalName) {
            resourceId = options.servicePrincipalId || (await entraServicePrincipal.getServicePrincipalByAppName(options.servicePrincipalName, "id")).id;
        }
        else if (options.groupId || options.groupName) {
            resourceId = options.groupId || (await entraGroup.getGroupIdByDisplayName(options.groupName));
        }
        return `${prefix}${resourceId}`;
    }
}
export default new EntraRoleAssignmentAddCommand();
//# sourceMappingURL=roleassignment-add.js.map