/*
 * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). All Rights Reserved.
 *
 * This software is the property of WSO2 LLC. and its suppliers, if any.
 * Dissemination of any information or reproduction of any material contained
 * herein in any form is strictly forbidden, unless permitted by WSO2 expressly.
 * You may not alter or remove any copyright or other notice from copies of this content.
 */

package org.wso2.carbon.is.migration.service.v610.migrator;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.identity.core.migrate.MigrationClientException;
import org.wso2.carbon.is.migration.service.Migrator;
import org.wso2.carbon.is.migration.service.v610.dao.OAuthAppDAO;
import org.wso2.carbon.is.migration.service.v610.model.OAuthApp;
import org.wso2.carbon.is.migration.service.v700.constant.MigratorConstants;
import org.wso2.carbon.is.migration.util.Utility;
import org.wso2.carbon.user.api.Tenant;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import static org.wso2.carbon.is.migration.util.Constant.MIGRATION_LOG;

/**
 * This class is to handle the migration of removing UMA grant from OAuth applications.
 */
public class UMAGrantMigrator extends Migrator {

    private static final Logger LOG = LoggerFactory.getLogger(UMAGrantMigrator.class);

    private static final OAuthAppDAO oAuthAppDao = new OAuthAppDAO();
    private static final String UMA_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:uma-ticket";

    @Override
    public void dryRun() throws MigrationClientException {

        LOG.info("Dry run capability not implemented in {} migrator.", this.getClass().getName());
    }

    @Override
    public void migrate() throws MigrationClientException {

        boolean removeUMAGrantFromApps = (Boolean) getMigratorConfig().getParameters()
                .get(MigratorConstants.REMOVE_UMA_GRANT_FROM_APPS);
        if (!removeUMAGrantFromApps) {
            LOG.info(MIGRATION_LOG + "Migrator for removing UMA grant from OAuth applications is disabled.");
            return;
        }

        LOG.info(MIGRATION_LOG + "Starting the migration of removing UMA grant from OAuth applications.");
        removeUMAGrantTypeFromOAuthApps(MultitenantConstants.SUPER_TENANT_ID);
        Set<Tenant> tenants = Utility.getTenants();
        for (Tenant tenant : tenants) {
            removeUMAGrantTypeFromOAuthApps(tenant.getId());
        }
        LOG.info(MIGRATION_LOG + "Migration of removing UMA grant from OAuth applications is completed.");
    }

    /**
     * Remove UMA grant type from OAuth applications.
     *
     * @param tenantId Tenant Id.
     * @throws MigrationClientException If an error occurs while removing UMA grant type from OAuth applications.
     */
    public void removeUMAGrantTypeFromOAuthApps(int tenantId) throws MigrationClientException {

        LOG.info(MIGRATION_LOG + "Removing UMA grant from OAuth applications in tenant: " + tenantId);
        List<OAuthApp> oAuthApps = oAuthAppDao.getOAuthConsumerAppsWithGrants(tenantId);
        if (CollectionUtils.isNotEmpty(oAuthApps)) {
            for (OAuthApp oAuthApp : oAuthApps) {
                String grantTypes = oAuthApp.getGrantTypes();
                if (StringUtils.isBlank(grantTypes)) {
                    continue;
                }
                List<String> grantTypeList = new ArrayList<>(Arrays.asList(grantTypes.split(" ")));
                boolean updateRequired = grantTypeList.remove(UMA_GRANT_TYPE);
                if (updateRequired) {
                    String updatedGrantTypeString = String.join(" ", grantTypeList);
                    oAuthApp.setGrantTypes(updatedGrantTypeString);
                    oAuthAppDao.updateOAuthConsumerAppGrants(updatedGrantTypeString, oAuthApp.getOauthAppId());
                }
            }
        }
        LOG.info(MIGRATION_LOG + "Removing UMA grant from OAuth applications in tenant: " + tenantId +
                " is completed.");
    }
}
