/**
 * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com).
 *
 * 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.v700.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wso2.carbon.identity.application.common.model.IdPGroup;
import org.wso2.carbon.identity.core.migrate.MigrationClientException;
import org.wso2.carbon.is.migration.internal.ISMigrationServiceDataHolder;
import org.wso2.carbon.is.migration.service.v700.dao.IdPDAO;
import org.wso2.carbon.is.migration.service.v700.dao.OrganizationDAO;
import org.wso2.carbon.is.migration.service.v700.dao.RoleV2DAO;
import org.wso2.carbon.is.migration.service.v700.model.IdPRole;
import org.wso2.carbon.user.api.Tenant;
import org.wso2.carbon.user.api.UserStoreException;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import static org.wso2.carbon.is.migration.service.v700.util.Utils.getUMDataSource;

public class IdPRoleToLocalRoleMappingsMigrationService {

    private static final Logger LOG = LoggerFactory.getLogger(IdPRoleToLocalRoleMappingsMigrationService.class);
    private static final RoleV2DAO roleV2DAO = new RoleV2DAO();
    private static final OrganizationDAO organizationDAO = new OrganizationDAO();
    private static final IdPDAO idPDAO = new IdPDAO();

    public void execute() throws MigrationClientException {

        LOG.info("......... Started IDP Role to local role Migration .........");
        try {
            Tenant[] tenants = ISMigrationServiceDataHolder.getRealmService().getTenantManager().getAllTenants();
            List<Tenant> tenantList = Arrays.stream(tenants).collect(Collectors.toList());
            Tenant superTenant = new Tenant();
            superTenant.setId(-1234);
            tenantList.add(superTenant);
            Connection connection = getUMDataSource().getConnection();
            for (Tenant tenant : tenantList) {
                List<IdPRole> idPRoles = idPDAO.getIdPRoles(tenant.getId());
                for (IdPRole idPRole : idPRoles) {
                    IdPGroup existingIdPGroup = idPDAO.getIdPGroup(tenant.getId(), idPRole.getIdPId(), idPRole.getRole());
                    if (existingIdPGroup == null) {
                        IdPGroup idPGroup = idPDAO.addIdPGroup(tenant.getId(), idPRole.getIdPId(), idPRole.getRole());
                        String mappedLocalRole = idPDAO.getLocalRoleMappedToIdPRole(tenant.getId(), idPRole.getId());
                        if (idPGroup == null) {
                            throw new MigrationClientException("Error while adding IdP group.");
                        }
                        if (mappedLocalRole != null) {
                            String orgId = organizationDAO.getOrganizationIdByName(connection, tenant.getDomain());
                            if (orgId == null) {
                                throw new MigrationClientException("Error while retrieving organization id.");
                            }
                            boolean isRoleExist = roleV2DAO.isRoleExist(tenant.getId(), mappedLocalRole, orgId, "organization");
                            if (isRoleExist) {
                                int roleId = roleV2DAO.getRoleID(tenant.getId(), mappedLocalRole, orgId, "organization");
                                idPDAO.addIdPGroupToRoleAssignment(connection, roleId, idPGroup.getIdpGroupId(),
                                        tenant.getId());
                            }
                        }
                    }
                }
            }
        } catch (UserStoreException e) {
            throw new MigrationClientException("Error while retrieving tenants.", e);
        } catch (SQLException e) {
            throw new MigrationClientException("Error while retrieving connection.", e);
        }
    }
}
