package cz.moneta.test.regression.cvm.process;

import cz.moneta.test.dsl.Harness;
import cz.moneta.test.dsl.ufo.operations.search.SearchBy;
import cz.moneta.test.dsl.ufo.operations.ufoOperations.STO704_S001_ClientConsentsPage;
import cz.moneta.test.dsl.util.task.cvm.onlinedb.OnlineDbGetDataTasks;
import cz.moneta.test.dsl.util.task.cvm.onlinedb.OnlineDbVerificationTasks;
import cz.moneta.test.dsl.util.task.ufo.operations.OperationsTasks;
import cz.moneta.test.harness.annotations.TestCase;
import cz.moneta.test.harness.annotations.TestScenario;
import cz.moneta.test.harness.support.auth.Credentials;
import cz.moneta.test.harness.support.auth.Key;
import org.jooq.Record;
import org.jooq.Result;

import java.time.LocalDateTime;
import java.time.LocalTime;

import static cz.moneta.test.harness.annotations.Environment.TST1;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

@TestScenario(name = "Change client's consents and check state in online DB")
public class ProcessConsentChange {

    public static final String GRANTED = "CNST_GRANTED";
    public static final String RETRACTED = "CNST_RETRACTED";
    public static final String SOURCE_SYSTEM = "ODS_GET_EVDCNST_DATA";

    public static final String MARKETING_CONSENT_TYPE_ATTR_NAME = "EVD_CNST_TP_ID";
    public static final String MARKETING_CONSENT_VALUE_ATTR_NAME = "EVD_CNST_STAT_ID";
    public static final String MARKETING_CONSENT_TYPE_IB_SB_VALUE = "MKTG_BYONLINE";
    public static final String MARKETING_CONSENT_TYPE_SMS_VALUE = "MKTG_BYTEXTMSG";
    public static final String MARKETING_CONSENT_TYPE_POST_VALUE = "MKTG_BYPOST";

    public static final String MARKETING_CONSENT_IB_SB_COLUMN = "CNST_MKT_IB_SB";
    public static final String MARKETING_CONSENT_SMS_COLUMN = "CNST_MKT_SMS";
    public static final String MARKETING_CONSENT_POST_COLUMN = "CNST_MKT_POST";
    public static final String MARKETING_CONSENT_UPDATE_DT_COLUMN = "CNST_UPD_DT";

    public static final String UI_CONSENT_REVOKED = "odvolaný";
    public static final String UI_GRANTED = "platný";

    @TestCase(name = "Check of SMS consent state on client. If enabled, check of enabled IB/SB and post consent state, disable IB, SMS " +
            "and Post consent. If disabled, check of disabled IB/SB and post consent state, enable all consents. Check creation of " +
            "records in SASRT_ONLINE_DATA", environments = {TST1})
    public void switchConsentsStateAndControlInDB(Harness harness, @Key("ufo-banka-banker") Credentials credentials) throws InterruptedException {
        Long clientUniPtKey = Long.valueOf(harness.getConfig("cvm.client.processconsentchange.uniptkey"));
        OnlineDbGetDataTasks onlineDbGetDataTasks = harness.tasks().cvm().onlineDbGetData();
        OperationsTasks operationsTasksTasks = harness.tasks().ufo().operations();
        Record oldClientConsents = onlineDbGetDataTasks.getClientConsents(clientUniPtKey);

        assertTrue(GRANTED.equals(oldClientConsents.getValue(MARKETING_CONSENT_IB_SB_COLUMN))
                        || RETRACTED.equals(oldClientConsents.getValue(MARKETING_CONSENT_IB_SB_COLUMN)),
                "IB/SB consent should be granted or revoked in SASRT_CLIENT");

        String actualState = (String) oldClientConsents.getValue(MARKETING_CONSENT_IB_SB_COLUMN);
        boolean willRevokeConsents = GRANTED.equals(actualState);
        String futureState = willRevokeConsents ? RETRACTED : GRANTED;

        STO704_S001_ClientConsentsPage clientConsentsPage = harness.withUfo()
                .openLoginPage()
                .then(operationsTasksTasks.login().withCredentials(credentials))
                .fillSearchInput(clientUniPtKey.toString())
                .searchBy(SearchBy.UID)
                .onClientDetailsPage()
                .clickClientConsents();

        if (willRevokeConsents) {
            clientConsentsPage
                    .clickRevokeIbSbConsent()
                    .clickRevokeSmsConsent()
                    .clickRevokePostConsent()
                    .assertIbSBConsentRevoked(UI_CONSENT_REVOKED)
                    .assertSmsConsentRevoked(UI_CONSENT_REVOKED)
                    .assertPostConsentRevoked(UI_CONSENT_REVOKED);
        } else {
            clientConsentsPage
                    .clickGiveAllConsents()
                    .clickOkButton()
                    .assertAllConsentsValid(UI_GRANTED);
        }

        Thread.sleep(5000 + 5000); // Delay to finish async code (one retry 5s and maximum delay of scheduler 5s)

        assertEquals(actualState, oldClientConsents.getValue(MARKETING_CONSENT_IB_SB_COLUMN),
                "IB/SB consent should be " + actualState + " in SASRT_CLIENT");
        assertEquals(actualState, oldClientConsents.getValue(MARKETING_CONSENT_SMS_COLUMN),
                "SMS consent should be " + actualState + " in SASRT_CLIENT");
        assertEquals(actualState, oldClientConsents.getValue(MARKETING_CONSENT_POST_COLUMN),
                "Post consent should be " + actualState + " in SASRT_CLIENT");
        if (LocalTime.now().getHour() >= 9) {
            // At least one test run today
            assertTrue(LocalDateTime.now().plusHours(-5).isBefore(
                            LocalDateTime.parse((String) oldClientConsents.getValue(MARKETING_CONSENT_UPDATE_DT_COLUMN))),
                    "Consents should be changed in last 5 hours");
        }

        String baseMsgId = onlineDbGetDataTasks.getOnlineDataBaseMsgIdLastChanged(SOURCE_SYSTEM,
                clientUniPtKey.toString());
        assertNotNull(baseMsgId, "There should be logged event data in SASRT_ONLINE_DATA");

        OnlineDbVerificationTasks onlineDbVerificationTasks = harness.tasks().cvm().onlineDbVerification();

        Result<Record> onlineDataConsents = onlineDbGetDataTasks.getOnlineData(SOURCE_SYSTEM, baseMsgId);

        onlineDbVerificationTasks.assertOnlineDbRecordFindSubMessageAndCheckAttribute(onlineDataConsents,
                MARKETING_CONSENT_TYPE_ATTR_NAME, MARKETING_CONSENT_TYPE_IB_SB_VALUE, MARKETING_CONSENT_VALUE_ATTR_NAME, futureState);
        onlineDbVerificationTasks.assertOnlineDbRecordFindSubMessageAndCheckAttribute(onlineDataConsents,
                MARKETING_CONSENT_TYPE_ATTR_NAME, MARKETING_CONSENT_TYPE_SMS_VALUE, MARKETING_CONSENT_VALUE_ATTR_NAME, futureState);
        onlineDbVerificationTasks.assertOnlineDbRecordFindSubMessageAndCheckAttribute(onlineDataConsents,
                MARKETING_CONSENT_TYPE_ATTR_NAME, MARKETING_CONSENT_TYPE_POST_VALUE, MARKETING_CONSENT_VALUE_ATTR_NAME, futureState);
    }
}
