/*
 * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com).
 *
 * WSO2 LLC. licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.wso2.carbon.is.migration.service.v710.dao;

import org.apache.commons.lang.StringUtils;
import org.wso2.carbon.identity.core.migrate.MigrationClientException;
import org.wso2.carbon.identity.organization.management.service.model.BasicOrganization;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.SUPER_ORG_ID;
import static org.wso2.carbon.is.migration.service.v700.util.Utils.getUMDataSource;

/**
 * DAO for organization related operations.
 */
public class OrganizationDAO {

    private static final String GET_SUPER_TENANT_ID = "SELECT UM_ID FROM UM_ORG WHERE UM_ORG_NAME='Super'";
    private static final String GET_ORG_ID_BY_NAME = "SELECT UM_ORG_UUID FROM UM_TENANT WHERE UM_DOMAIN_NAME = ?";
    private static final String GET_TENANT_DOMAIN_FROM_ORGANIZATION_UUID = "SELECT UM_DOMAIN_NAME FROM UM_TENANT " +
            "WHERE UM_ORG_UUID = ?";
    private static final String GET_CHILD_ORGANIZATIONS = "SELECT UM_ORG.UM_ID, UM_ORG.UM_ORG_NAME, " +
            "UM_ORG.UM_CREATED_TIME FROM UM_ORG JOIN UM_ORG_HIERARCHY ON UM_ORG.UM_ID = UM_ORG_HIERARCHY.UM_ID " +
            "WHERE UM_ORG_HIERARCHY.UM_PARENT_ID = ? AND UM_ORG_HIERARCHY.DEPTH = 1";
    private static final String UM_ORG_UUID_COLUMN = "UM_ORG_UUID";
    private static final String UM_ID_COLUMN = "UM_ID";
    private static final String UM_DOMAIN_NAME_COLUMN = "UM_DOMAIN_NAME";
    private static final String UM_ORG_NAME_COLUMN = "UM_ORG_NAME";
    private static final String UM_CREATED_TIME_COLUMN = "UM_CREATED_TIME";

    /**
     * Get organization id by tenant domain.
     *
     * @param tenantDomain organization name.
     * @return organization id.
     * @throws MigrationClientException if error occurred while retrieving organization id.
     */
    public String resolveOrganizationId(String tenantDomain) throws MigrationClientException {

        try (Connection connection = getUMDataSource().getConnection()) {
            if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equalsIgnoreCase(tenantDomain)) {
                return SUPER_ORG_ID;
            }
            try (PreparedStatement prepStmt = connection.prepareStatement(GET_ORG_ID_BY_NAME)) {
                prepStmt.setString(1, tenantDomain);
                ResultSet resultSet = prepStmt.executeQuery();
                if (resultSet.next()) {
                    return resultSet.getString(UM_ORG_UUID_COLUMN);
                }
            } catch (SQLException e) {
                throw new MigrationClientException("Error while retrieving organization id", e);
            }
            return null;
        } catch (SQLException e) {
            throw new MigrationClientException("Error while retrieving connection.", e);
        }
    }

    public String resolveTenantDomain(String organizationId) throws MigrationClientException {

        if (StringUtils.equals(organizationId, SUPER_ORG_ID)) {
            return MultitenantConstants.SUPER_TENANT_DOMAIN_NAME;
        }
        try (Connection connection = getUMDataSource().getConnection()) {
            try (PreparedStatement prepStmt = connection.prepareStatement(GET_TENANT_DOMAIN_FROM_ORGANIZATION_UUID)) {
                prepStmt.setString(1, organizationId);
                ResultSet resultSet = prepStmt.executeQuery();
                if (resultSet.next()) {
                    return resultSet.getString(UM_DOMAIN_NAME_COLUMN);
                }
            } catch (SQLException e) {
                throw new MigrationClientException("Error while retrieving tenant domain", e);
            }
            return null;
        } catch (SQLException e) {
            throw new MigrationClientException("Error while retrieving connection.", e);
        }
    }

    public List<BasicOrganization> getChildOrganizations(String parentOrganizationId) throws MigrationClientException{

        try (Connection connection = getUMDataSource().getConnection()) {
            try (PreparedStatement prepStmt = connection.prepareStatement(GET_CHILD_ORGANIZATIONS)) {
                prepStmt.setString(1, parentOrganizationId);
                ResultSet resultSet = prepStmt.executeQuery();
                List<BasicOrganization> childOrganizations = new ArrayList<>();
                while (resultSet.next()) {
                    BasicOrganization childOrganization = new BasicOrganization();
                    childOrganization.setId(resultSet.getString(UM_ID_COLUMN));
                    childOrganization.setName(resultSet.getString(UM_ORG_NAME_COLUMN));
                    childOrganization.setCreated(resultSet.getString(UM_CREATED_TIME_COLUMN));
                    childOrganizations.add(childOrganization);
                }
                return childOrganizations;
            } catch (SQLException e) {
                throw new MigrationClientException("Error while retrieving child organizations.", e);
            }
        } catch (SQLException e) {
            throw new MigrationClientException("Error while retrieving connection.", e);
        }
    }
}
