package io.delphi.qa.auto.awsmfrw.tests.slz.postgres;

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.models.*;
import io.delphi.qa.auto.awsmfrw.models.aws.lm.WpSlzUnitOfWork;
import io.delphi.qa.auto.awsmfrw.models.db.sql.pg.MAIN.PUBLIC.*;
import io.delphi.qa.auto.awsmfrw.suppliers.DelphiDataContainer;
import io.delphi.qa.auto.awsmfrw.tests.slz.BsSlzTest;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.util.*;
import java.util.stream.Collectors;

public class Postgres_UnitTest extends BsSlzTest {

  private static MlFw_ReportWrapper WP_REPORT;
  private static WpSlzUnitOfWork WP_SLZ_UNIT_OF_WORK;
  private final Map<String, String> secretMap =
      fetchAwsSecret(EnAwsSecrets.DELPHI_SLZ_STORAGE_PG_PROXY_USER);

  static {
    WP_REPORT =
        new MlFw_ReportWrapper()
            .withDsp(EnDelphiDspItems.APPLE)
            .withLicensor(EnDelphiLicensorItems.THEORCHARD)
            .withReport(EnDelphiReportItems.AM_SHAZAM)
            .withVersion(EnDelphiReportVersionItems.v1_2)
            .withDate(DT_NOW.minusDays(35));
    WP_SLZ_UNIT_OF_WORK = DelphiDataContainer.genNewMlWpUnitOfWork(WP_REPORT);
    System.setProperty("delphi.env.run.type.isLogAll", "false");
  }

  @Override
  public String genTestRunId() {
    return IsaCommonMethods.testRunId();
  }

  @BeforeMethod(alwaysRun = true)
  public void preM_setUp() {
    Set<MlPg_UnitOfWork> mlPgUnitOfWorks =
        delphi
            .db()
            .postgres(secretMap)
            .awsmSelect(
                new MlPg_UnitOfWork(),
                String.format("unit_of_work_code ~ '%s'", WP_SLZ_UNIT_OF_WORK.getUowCode()));
    ensureRecordsNotInTables_ContentFailureLog_DisassembleContentStatus_ContentStatus_UnitOfWork(
        mlPgUnitOfWorks);
  }

  @Test
  public void tc_delete() {
    MlPg_UnitOfWork uow = DelphiDataContainer.genMlPgUnitOfWork(WP_SLZ_UNIT_OF_WORK, 0);
    Set<MlPg_UnitOfWork> uows =
        delphi.db().postgres(secretMap).awsmInsert(Collections.singleton(uow));
    int affectedRows = delphi.db().postgres(secretMap).awsmDelete(uows, null);
    Assert.assertTrue(affectedRows > 0);
  }

  @Test
  public void tc_delete_all() {
    Set<MlPg_UnitOfWork> mlPgUnitOfWorks =
        delphi.db().postgres(secretMap).awsmSelect(new MlPg_UnitOfWork(), null);
    Set<MlPg_ContentFailureLog> mlPgContentFailureLogs =
        delphi.db().postgres(secretMap).awsmSelect(new MlPg_ContentFailureLog(), null);
    clearTableRecords(mlPgContentFailureLogs, null);
    Set<MlPg_DisassembleContentStatus> mlPgDisassembleContentStatuses =
        delphi.db().postgres(secretMap).awsmSelect(new MlPg_DisassembleContentStatus(), null);
    clearTableRecords(mlPgDisassembleContentStatuses, null);
    Set<MlPg_ContentStatus> mlPgContentStatuses =
        delphi.db().postgres(secretMap).awsmSelect(new MlPg_ContentStatus(), null);
    List<Map<String, String>> pgEmailRecords =
        delphi.db().postgres(secretMap).awsmQueryNew("select md_message_id from PUBLIC.EMAIL");
    String pgEmailIds =
        pgEmailRecords.stream()
            .map(
                o -> o.values().stream()
                            .map(i -> String.format("'%s'", i)).collect(Collectors.joining(",")))
            .collect(Collectors.joining(","));
    delphi
        .db()
        .postgres(secretMap)
        .awsmQueryNew(
            String.format("delete from public.email where md_message_id in (%s)", pgEmailIds));
    String uowIds =
            mlPgUnitOfWorks.stream()
                    .map(MlPg_UnitOfWork::getId)
                    .map(String::valueOf)
                    .collect(Collectors.joining("\n, "));
    Set<MlPg_UnitOfWorkPipeline> mlPgUnitOfWorksPipelinePipelines =
            delphi
                    .db()
                    .postgres(secretMap)
                    .awsmSelect(
                            new MlPg_UnitOfWorkPipeline(),
                            String.format("unit_of_work_id in (%s)", uowIds));
    clearTableRecords(mlPgContentStatuses, null);
    clearTableRecords(mlPgUnitOfWorksPipelinePipelines, "unit_of_work_id");
    clearTableRecords(mlPgUnitOfWorks, null);
    mlPgUnitOfWorks = delphi.db().postgres(secretMap).awsmSelect(new MlPg_UnitOfWork(), null);
    Assert.assertEquals(mlPgUnitOfWorks.size(), 0);
  }

  @Test
  public void tc_delete_few() {
    Set<MlPg_UnitOfWork> uowsBefore = new HashSet<>();
    uowsBefore.add(
        DelphiDataContainer.genMlPgUnitOfWork(
            DelphiDataContainer.genNewMlWpUnitOfWork(WP_REPORT), 0));
    uowsBefore.add(
        DelphiDataContainer.genMlPgUnitOfWork(
            DelphiDataContainer.genNewMlWpUnitOfWork(WP_REPORT.withDate(DT_NOW.minusDays(40))), 0));
    uowsBefore = delphi.db().postgres(secretMap).awsmInsert(uowsBefore);
    delphi.db().postgres(secretMap).awsmDelete(uowsBefore, null);
    Set<MlPg_UnitOfWork> uowAfter =
        delphi
            .db()
            .postgres(secretMap)
            .awsmSelect(
                new MlPg_UnitOfWork(),
                String.format(
                    "unit_of_work_id in (%s)",
                    uowsBefore.stream()
                        .map(MlPg_UnitOfWork::getId)
                        .map(String::valueOf)
                        .collect(Collectors.joining(", "))));
    Assert.assertEquals(uowAfter.size(), 0);
  }

  @Test
  public void tc_insert() {
    MlPg_UnitOfWork uow = DelphiDataContainer.genMlPgUnitOfWork(WP_SLZ_UNIT_OF_WORK, 6);
    uow = delphi.db().postgres(secretMap).awsmInsert(Collections.singleton(uow)).iterator().next();
    Assert.assertNotNull(uow.getId());
  }

  @Test
  public void tc_select() {
    MlPg_UnitOfWork uow = DelphiDataContainer.genMlPgUnitOfWork(WP_SLZ_UNIT_OF_WORK, 6);
    uow = delphi.db().postgres(secretMap).awsmInsert(Collections.singleton(uow)).iterator().next();
    Set<MlPg_UnitOfWork> uows =
        delphi
            .db()
            .postgres(secretMap)
            .awsmSelect(
                new MlPg_UnitOfWork(), String.format("unit_of_work_id in (%s)", uow.getId()));
    Assert.assertTrue(uows.size() > 0);
  }

  @Test
  public void tc_update() {
    MlPg_UnitOfWork uow = DelphiDataContainer.genMlPgUnitOfWork(WP_SLZ_UNIT_OF_WORK, 0);
    Set<MlPg_UnitOfWork> uows = Collections.singleton(uow);
    Long idBefore = 0L;
    uows = delphi.db().postgres(secretMap).awsmInsert(uows);
    idBefore = uows.iterator().next().getId();
    uows =
        delphi
            .db()
            .postgres(secretMap)
            .awsmUpdate(
                DelphiDataContainer.genMlPgUnitOfWork(WP_SLZ_UNIT_OF_WORK, 3)
                    .withPriority(100)
                    .withId(idBefore));
    Assert.assertEquals(idBefore, uows.iterator().next().getId());
  }
}
