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

import org.wso2.carbon.identity.application.common.model.Scope;
import org.wso2.carbon.identity.core.migrate.MigrationClientException;
import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil;

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 java.util.UUID;

public class APIResourceDAO {

    private static final String CREATE_API_RESOURCE = "INSERT INTO API_RESOURCE (ID, NAME, IDENTIFIER, DESCRIPTION, " +
            "TYPE, REQUIRES_AUTHORIZATION, TENANT_ID) VALUES (?, ?, ?, ?, ?, ?, ?)";
    private static final String CREATE_SYSTEM_API_RESOURCE = "INSERT INTO API_RESOURCE (ID, NAME, IDENTIFIER, " +
            "DESCRIPTION, TYPE, REQUIRES_AUTHORIZATION) VALUES (?, ?, ?, ?, ?, ?)";
    private static final String GET_API_RESOURCE_BY_IDENTIFIER = "SELECT ID FROM API_RESOURCE WHERE IDENTIFIER = ? " +
            "AND TENANT_ID = ?";
    private static final String GET_SYSTEM_API_RESOURCE_IDENTIFIER = "SELECT IDENTIFIER FROM API_RESOURCE WHERE " +
            "TENANT_ID IS NULL";
    private static final String DELETE_API_RESOURCE_BY_IDENTIFIER = "DELETE FROM API_RESOURCE WHERE IDENTIFIER = ? " +
            "AND TENANT_ID = ?";
    private static final String GET_SCOPE_IDS_BY_API_ID = "SELECT ID FROM SCOPE WHERE API_ID = ?";

    /**
     * Create API resource.
     *
     * @param name                  Name of the API resource.
     * @param identifier            Identifier of the API resource.
     * @param tenantId              Tenant ID.
     * @param description           Description of the API resource.
     * @param type                  Type of the API resource.
     * @param requiresAuthorization Whether the API resource requires authorization.
     * @throws MigrationClientException If an error occurs while creating the API resource.
     */
    public void createAPIResource(String id, String name, String identifier, Integer tenantId, String description,
                                  String type, boolean requiresAuthorization) throws MigrationClientException {

        try (Connection connection = IdentityDatabaseUtil.getDBConnection(false)) {
            String sql;
            if (tenantId != null) {
                sql = CREATE_API_RESOURCE;
            } else {
                sql = CREATE_SYSTEM_API_RESOURCE;
            }
            try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
                preparedStatement.setString(1, id);
                preparedStatement.setString(2, name);
                preparedStatement.setString(3, identifier);
                preparedStatement.setString(4, description);
                preparedStatement.setString(5, type);
                preparedStatement.setBoolean(6, requiresAuthorization);
                if (tenantId != null) {
                    preparedStatement.setInt(7, tenantId);
                }
                preparedStatement.execute();
            }
        } catch (SQLException e) {
            throw new MigrationClientException("Error while creating API resource.", e);
        }
    }

    /**
     * Get API resource ID by identifier.
     *
     * @param identifier Identifier of the API resource.
     * @return API resource ID.
     * @throws MigrationClientException If an error occurs while retrieving API resource ID.
     */
    public String getAPIResourceIDByIdentifier(String identifier, int tenantId) throws MigrationClientException {

        try (Connection connection = IdentityDatabaseUtil.getDBConnection(false)) {
            try (PreparedStatement preparedStatement = connection.prepareStatement(GET_API_RESOURCE_BY_IDENTIFIER)) {
                preparedStatement.setString(1, identifier);
                preparedStatement.setInt(2, tenantId);
                try (ResultSet resultSet = preparedStatement.executeQuery()) {
                    if (resultSet.next()) {
                        return resultSet.getString("ID");
                    }
                    return null;
                }
            }
        } catch (SQLException e) {
            throw new MigrationClientException("Error while retrieving API resource ID.", e);
        }
    }

    public List<String> getSystemAPIResourceIdentifiers() throws MigrationClientException {

        try (Connection connection = IdentityDatabaseUtil.getDBConnection(false)) {
            try (PreparedStatement preparedStatement = connection.prepareStatement(GET_SYSTEM_API_RESOURCE_IDENTIFIER)) {
                try (ResultSet resultSet = preparedStatement.executeQuery()) {
                    List<String> apiResourceIdentifiers = new ArrayList<>();
                    while (resultSet.next()) {
                        apiResourceIdentifiers.add(resultSet.getString("IDENTIFIER"));
                    }
                    return apiResourceIdentifiers;
                }
            }
        } catch (SQLException e) {
            throw new MigrationClientException("Error while retrieving API resource ID.", e);
        }
    }
    /**
     * Delete API resource by identifier.
     *
     * @param identifier Identifier of the API resource.
     * @throws MigrationClientException If an error occurs while deleting API resource.
     */
    public void deleteAPIResourceByIdentifier(String identifier, int tenantId) throws MigrationClientException {

        try (Connection connection = IdentityDatabaseUtil.getDBConnection(false)) {
            try (PreparedStatement preparedStatement = connection.prepareStatement(DELETE_API_RESOURCE_BY_IDENTIFIER)) {
                preparedStatement.setString(1, identifier);
                preparedStatement.setInt(2, tenantId);
                preparedStatement.execute();
            }
        } catch (SQLException e) {
            throw new MigrationClientException("Error while deleting API resource.", e);
        }
    }

    /**
     * Get scope IDs by API ID.
     *
     * @param apiId API ID.
     * @return List of scopes.
     * @throws MigrationClientException If an error occurs while retrieving scopes.
     */
    public List<String> getScopeIDsByAPIId(String apiId) throws MigrationClientException {

        try (Connection connection = IdentityDatabaseUtil.getDBConnection(false)) {
            try (PreparedStatement preparedStatement = connection.prepareStatement(GET_SCOPE_IDS_BY_API_ID)) {
                preparedStatement.setString(1, apiId);
                try (ResultSet resultSet = preparedStatement.executeQuery()) {
                    List<String> scopes = new ArrayList<>();
                    while (resultSet.next()) {
                        scopes.add(resultSet.getString("ID"));
                    }
                    return scopes;
                }
            }
        } catch (SQLException e) {
            throw new MigrationClientException("Error while retrieving scopes.", e);
        }
    }
}
