/*
 * 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.v700.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wso2.carbon.identity.core.migrate.MigrationClientException;
import org.wso2.carbon.is.migration.service.v700.V700Migration;
import org.wso2.carbon.is.migration.service.v700.dao.OrganizationDAO;
import org.wso2.carbon.is.migration.util.Constant;
import org.wso2.carbon.user.api.Tenant;

import java.sql.Connection;
import java.util.Set;
import java.util.UUID;

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

/**
 * Migrator implementation for migrating tenants to organizations.
 */
public class AssociateTenantToOrgService {

    private static final Logger LOG = LoggerFactory.getLogger(V700Migration.class);
    private final OrganizationDAO organizationDAO = new OrganizationDAO();

    public void execute() throws MigrationClientException {

        try {
            Connection connection = getUMDataSource().getConnection();
            connection.setAutoCommit(false);
            Set<Tenant> tenants = organizationDAO.getTenantsWithoutOrganization(connection);
            LOG.info("Started migrating tenants to organizations.");
            for (Tenant tenant : tenants) {
                migrateTenant(connection, tenant);
            }
            connection.commit();
            LOG.info("Completed migrating tenants to organizations.");
        } catch (Exception e) {
            throw new MigrationClientException("Error while migrating tenants to organizations.", e);
        }
    }

    /**
     * Migrate a tenant to an organization.
     *
     * @param tenant Tenant to be migrated.
     * @throws MigrationClientException If an error occurs while migrating the tenant.
     */
    private void migrateTenant(Connection connection, Tenant tenant) throws MigrationClientException {

        LOG.info(Constant.MIGRATION_LOG + "Started migrating tenant: " + tenant.getDomain());
        try {
            String orgId = UUID.randomUUID().toString();
            String orgName = tenant.getDomain();
            String orgDescription = "Organization for tenant: " + tenant.getDomain();
            String status = tenant.isActive() ? "ACTIVE" : "INACTIVE";
            String orgType = "TENANT";
            try {
                organizationDAO.insertOrganizationDetails(connection, orgId, orgName, orgDescription, null, status, orgType);
                organizationDAO.insertOrganizationHierarchy(connection, orgId, orgId, 0);
                organizationDAO.insertOrganizationUUIDToTenant(connection, orgId, tenant.getDomain());
            } catch (MigrationClientException e) {
                // Rollback the migration.
                organizationDAO.deleteOrganizationHierarchy(connection, orgId, orgId);
                organizationDAO.deleteOrganizationDetails(connection, orgId);
                organizationDAO.deleteOrganizationUUIDFromTenant(connection, tenant.getDomain());
            }
            LOG.info(Constant.MIGRATION_LOG + "Completed migrating tenant: " + tenant.getDomain());
        } catch (Exception e) {
            throw new MigrationClientException("Error while migrating tenant: " + tenant.getDomain(), e);
        }
    }
}
