package io.delphi.qa.auto.awsmfrw.managers.helpers.db.snowflake;

import io.delphi.qa.auto.awsmfrw.managers.helpers.db.SnowflakeClient;
import io.delphi.qa.auto.awsmfrw.models.db.BsSqlTable;
import io.delphi.qa.auto.awsmfrw.models.db.sql.dsl.DslSql;
import io.delphi.qa.auto.awsmfrw.models.db.sql.dsl.DslSqlSelect;
import io.delphi.qa.auto.awsmfrw.models.db.sql.snowflake._delphi_exploration.sys.MlSn_DspIdToParentRepOwnerMapping;
import io.delphi.qa.auto.awsmfrw.models.db.sql.snowflake._delphi_exploration.sys.MlSn_DspIdToUserMapping;
import io.delphi.qa.auto.awsmfrw.models.db.sql.snowflake._delphi_exploration.sys.MlSn_DspSuperUser;
import io.delphi.qa.auto.awsmfrw.models.db.sql.snowflake._delphi_exploration.sys.MlSn_ParentRepOwnerToUserMapping;
import io.delphi.qa.auto.awsmfrw.suppliers.DelphiDataContainer;
import io.qameta.allure.Step;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static io.delphi.qa.auto.awsmfrw.common_baby.IsaConstants.envConfig;

public interface SfRlsAdminInterface extends SfRlsInterface {

  default void cleanSysTables() {
    List<MlSn_ParentRepOwnerToUserMapping> parentRepOwnerToUserMappings =
        getAdminClient()
            .awsmSelect(
                new MlSn_ParentRepOwnerToUserMapping(),
                String.format("USER_NAME = '%s'", getAdminSecret().get("user")));
    parentRepOwnerToUserMappings.stream()
        .filter(Objects::nonNull)
        .forEach(
            o ->
                getAdminClient()
                    .awsmDelete(
                        o, String.format("USER_NAME = '%s'", getAdminSecret().get("user"))));
    List<MlSn_DspIdToUserMapping> dspIdToUserMappings =
        getAdminClient()
            .awsmSelect(
                new MlSn_DspIdToUserMapping(),
                String.format("USER_NAME = '%s'", getAdminSecret().get("user")));
    dspIdToUserMappings.stream()
        .filter(Objects::nonNull)
        .forEach(
            o ->
                getAdminClient()
                    .awsmDelete(
                        o, String.format("USER_NAME = '%s'", getAdminSecret().get("user"))));
    List<MlSn_DspSuperUser> dspSuperUsers =
        getAdminClient()
            .awsmSelect(
                new MlSn_DspSuperUser(),
                String.format("USER_NAME = '%s'", getAdminSecret().get("user")));
    dspSuperUsers.stream()
        .filter(Objects::nonNull)
        .forEach(
            o ->
                getAdminClient()
                    .awsmDelete(
                        o, String.format("USER_NAME = '%s'", getAdminSecret().get("user"))));
  }

  default void countTables() {
    countEntities(getAdminClient(), SfRlsInterface.TABLES);
  }

  default void createDspIds(String... dspIds) {
    DelphiDataContainer.saveResource(DSP_IDS, Arrays.stream(dspIds).collect(Collectors.toList()));
  }

  default void executeQuery() {
    countEntities(getAdminClient(), SfRlsInterface.DSP_IDS);
  }

  default void extendDspIds(String... dspIds) {
    DelphiDataContainer.saveResource(
        DSP_IDS,
        Stream.concat(
                ((List<String>) DelphiDataContainer.getResource(DSP_IDS)).stream(),
                Arrays.stream(dspIds))
            .collect(Collectors.toList()));
  }

  @Step("Init client")
  SnowflakeClient getAdminClient();

  Map<String, String> getAdminSecret();

  default <T extends BsSqlTable<T>> void insertCase() {
    DelphiDataContainer.saveResource(
        INSERT, getAdminClient().awsmInsert((List<T>) DelphiDataContainer.getResource(INSERT)));
  }

  default void queryDspIds(String dspName, String... parentRepOwner) {
    DslSqlSelect sqlSelectBase =
        DslSql.select().columns("dsp_id").from(new MlSn_DspIdToParentRepOwnerMapping().locator());
    if (parentRepOwner.length > 0)
      sqlSelectBase
          .where(
              String.format("parent_rep_owner_key  in ('%s')", String.join("','", parentRepOwner)))
          .and(String.format("dsp_name in ('%s')", dspName));
    DelphiDataContainer.saveResource(
        DSP_IDS, getAdminClient().awsmCustomQuery(sqlSelectBase.limit(envConfig.dspLimit()).queryText()));
  }
}
