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

import io.delphi.qa.auto.awsmfrw.common_baby.IsaCommonMethods;
import io.delphi.qa.auto.awsmfrw.common_baby.delphi.aws.EnAwsSecrets;
import io.delphi.qa.auto.awsmfrw.common_baby.delphi.aws.ICanFetchAwsSecret;
import io.delphi.qa.auto.awsmfrw.managers.helpers.db.SnowflakeClient;
import io.delphi.qa.auto.awsmfrw.models.db.snowflake.EnDelphiDbSqlSfRlsDspIdItems;
import io.delphi.qa.auto.awsmfrw.models.db.sql.dsl.InterfaceDslSqlQuery;
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 org.testng.collections.Lists;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public interface SfRlsInterface extends ICanFetchAwsSecret {

  String TABLES = "tables";
  String INSERT = "insert";
  String QUERY_PARAMS_MAP = "query_params_map";
  String DSP_IDS = "dsp_ids";
  String QUERY = "query";
  String VIEWS = "views";
  Map<String, String> SNOWFLAKE_SECRET =
      ICanFetchAwsSecret.pullAwsSecret(EnAwsSecrets.DELPHI_TEST_AUTOMATION_SNOWFLAKE);

  default void buildQuery(InterfaceDslSqlQuery sqlQueryPattern, String... sqlQueryParamsLocator) {
    String s =
        sqlQueryParamsLocator.length > 0
            ? IsaCommonMethods.resolvePattern(
                sqlQueryPattern.queryText(),
                (HashMap<String, String>) DelphiDataContainer.getResource(sqlQueryParamsLocator[0]))
            : sqlQueryPattern.queryText();
    DelphiDataContainer.saveResource(QUERY, s);
  }

  default void countEntities(SnowflakeClient snowflakeClient, String resultLocator) {
    DelphiDataContainer.saveResource(
        resultLocator,
        snowflakeClient.awsmCustomQuery((String) DelphiDataContainer.getResource(QUERY)));
  }

  default void createIdMap(final EnDelphiDbSqlSfRlsDspIdItems idItem) {
    DelphiDataContainer.saveResource(
        QUERY_PARAMS_MAP,
        new HashMap<String, String>() {
          {
            put(
                idItem.get(),
                String.join("','", (List<String>) DelphiDataContainer.getResource(DSP_IDS)));
          }
        });
  }

  default void genDspId2UserMapping(String dspName, String... dspIds) {
    DelphiDataContainer.saveResource(
        INSERT,
        Arrays.stream(dspIds)
            .map(
                o ->
                    new MlSn_DspIdToUserMapping()
                        .withDspName(dspName)
                        .withDspId(o)
                        .withUserName(SNOWFLAKE_SECRET.get("user")))
            .collect(Collectors.toList()));
  }

  default void genDspSuperUser(String dspName) {
    DelphiDataContainer.saveResource(
        INSERT,
        Lists.newArrayList(
            new MlSn_DspSuperUser()
                .withDspName(dspName)
                .withUserName(SNOWFLAKE_SECRET.get("user"))));
  }

  default void genParentRepOwner2UserMapping(String dspName, String... parentRepOwnerKeys) {
    DelphiDataContainer.saveResource(
        INSERT,
        Arrays.stream(parentRepOwnerKeys)
            .map(
                o ->
                    new MlSn_ParentRepOwnerToUserMapping()
                        .withDspName(dspName)
                        .withParentRepOwnerKey(o)
                        .withUserName(SNOWFLAKE_SECRET.get("user")))
            .collect(Collectors.toList()));
  }

  default Map<String, String> overwriteSecret(Map<String, String> updateMap) {
    return ICanFetchAwsSecret.pullAwsSecret(EnAwsSecrets.DELPHI_TEST_AUTOMATION_SNOWFLAKE)
        .entrySet()
        .stream()
        .filter(
            secretEntry -> {
              updateMap.forEach(
                  (key, value) -> {
                    if (secretEntry.getKey().equals(key)) secretEntry.setValue(value);
                  });
              return true;
            })
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
  }
}
