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

import cz.moneta.test.dsl.Harness;
import cz.moneta.test.dsl.util.DateUtils;
import cz.moneta.test.dsl.util.task.cvm.onlinedb.OnlineDbGetDataTasks;
import cz.moneta.test.dsl.util.task.cvm.onlinedb.OnlineDbVerificationTasks;
import cz.moneta.test.harness.annotations.TestCase;
import cz.moneta.test.harness.annotations.TestScenario;
import org.jooq.Record;
import org.jooq.Result;

import java.time.*;

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

@TestScenario(name = "Starts web express loan process and leave it alone. It expects that will be run every day after 8:30")
public class ProcessWebExpressDropOut {

    private static final String EVENT_DATA_TO_FIND = "\"PHONE_NUMBER\":\"%s\"";
    private static final String LOAN_AMOUNT = "295000";
    private static final String LOAN_DURATION = "50";
    private static final String WEB_EXP_DROPOUT_CC = "cvm.cluster/WEB_EXP_DROPOUT_CC/1.0.0";
    private static final String CLIENT_PHONENUMBER_CONFIG_KEY = "cvm.client.webexpressdropout.phonenumber";

    @TestCase(name = "Starts web express loan process and check, whether RTRD_WEB_TRIGGER_Expres planned drop out event",
            environments = {TST1, PPE})
    public void startWebExpressProcess(Harness harness) throws InterruptedException {
        // 2026-02 VV: FullyOnline no longer exists and has been removed from Harness
        // FullyOnlineExpressTasks tasksFullyOnline = harness.tasks().retail().loans().cloanFullyOnline();
        String clientPhoneNumber = harness.getConfig(CLIENT_PHONENUMBER_CONFIG_KEY);
        // NonClient nonClient = tasksFullyOnline.createFullyOnlineNonClient()
        //        .withMobileNumber(clientPhoneNumber.substring(4));
        // harness.withFullyOnline()
        //        .openWelcomePage()
        //        .then(tasksFullyOnline.setBasicLoanParams(LOAN_AMOUNT, LOAN_DURATION))
        //        .then(tasksFullyOnline.fillClientInfo(nonClient));

        Thread.sleep(2000); // Delay to finish async code

        OnlineDbGetDataTasks onlineDbGetDataTasks = harness.tasks().cvm().onlineDbGetData();
        Result<Record> onlineDbRecords = onlineDbGetDataTasks.getPlannedTasks(
                OnlineDbGetDataTasks.PAYLOAD_ATTRIBUTE_NAME_CLIENT_PHONE_NUMBER, clientPhoneNumber);
        assertTrue(onlineDbRecords.isNotEmpty(), "Should exist at least one planned event");
        Record onlineDbRecord = onlineDbRecords.get(onlineDbRecords.size() - 1);

        OnlineDbVerificationTasks onlineDbVerificationTasks = harness.tasks().cvm().onlineDbVerification();
        String activityId = onlineDbVerificationTasks.assertOnlineDbRecordIsValid(onlineDbRecord,
                "digitalChannelsLoanWebExpressTask", WEB_EXP_DROPOUT_CC, 40 * 60,
                data -> {
                    assertEquals(LOAN_AMOUNT, data.get("productExpresLoanAmount").getAsString(),
                            "Event data should contain correct data");
                    assertEquals(LOAN_DURATION, data.get("productExpresTerm").getAsString(),
                            "Event data should contain correct data");
                });

        Result<Record> triggerLogRecords = onlineDbGetDataTasks.getTriggerLogs(
                "RTRD_WEB_TRIGGER_Expres", activityId);
        assertEquals(1, triggerLogRecords.size(), "Should log one record");

        onlineDbVerificationTasks.assertTriggerLogRecordIsPlanned(triggerLogRecords.get(0), onlineDbRecord,
                WEB_EXP_DROPOUT_CC,
                logData -> assertTrue(logData.contains("\"PHONE_NUMBER\":\"" + clientPhoneNumber +
                                "\",\"PROCESS_TRACKER\":\"process.tracker.clientInfo\"}"),
                        "Planned call with correct additional data should be logged"));
    }

    @TestCase(name = "Check, whether web express loan drop out process initiated by previous startWebExpressProcess was successfully " +
            "finished in last day", environments = {TST1})
    public void checkFinishOfWebExpressDropOutInLastDayTst1(Harness harness) {
        OnlineDbGetDataTasks onlineDbGetDataTasks = harness.tasks().cvm().onlineDbGetData();
        String clientPhoneNumber = harness.getConfig(CLIENT_PHONENUMBER_CONFIG_KEY);
        DayOfWeek todayDayOfWeek = LocalDate.now().getDayOfWeek();
        if (todayDayOfWeek == DayOfWeek.SUNDAY ||
                (todayDayOfWeek == DayOfWeek.MONDAY && LocalTime.now().isBefore(LocalTime.of(8, 30))) ||
                DateUtils.isStateHoliday(LocalDate.now())) {
            return; // Skip test
        }
        Result<Record> triggerLogRecords = onlineDbGetDataTasks.getTriggerLogsFinishedInLastDay(
                String.format(EVENT_DATA_TO_FIND, clientPhoneNumber));
        assertTrue(triggerLogRecords.isNotEmpty(), "Should be there at least one record");

        Result<Record> decisionLogRecords = onlineDbGetDataTasks.getDecisionLogInLastDay("Web_Exp_Dropout_CC",
                "\"MOB_PHONE\":\"" + clientPhoneNumber + "\"");

        assertEquals(triggerLogRecords.size(), decisionLogRecords.size(),
                "Should be same count of finished tasks in RTRD and decisions in RTDM");

        for (int i = 0; i < triggerLogRecords.size(); i++) {
            Record triggerLogRecord = triggerLogRecords.get(i);
            Record decisionLogRecord = decisionLogRecords.get(i);

            String response = (String) decisionLogRecord.getValue("RESPONSE_VARIABLES_STRING");
            assertTrue(response.contains("\"REPLY_TYPE\":\"STANDARD\"") || response.contains("\"REPLY_TYPE\":\"NORMAL\""),
                    "Associated decision log should have had the correct response, but had: " + response);
            ZonedDateTime decisionTime = LocalDateTime.parse((String) decisionLogRecord.getValue("EVENT_DT"))
                    .atZone(ZoneId.systemDefault());

            OnlineDbVerificationTasks onlineDbVerificationTasks = harness.tasks().cvm().onlineDbVerification();
            onlineDbVerificationTasks.assertTriggerLogRecordSucceeded(triggerLogRecord, WEB_EXP_DROPOUT_CC, decisionTime);
        }

    }

    @TestCase(name = "Check, whether web express loan drop out process initiated by previous startWebExpressProcess was successfully " +
            "finished in last day", environments = {PPE})
    public void checkFinishOfWebExpressDropOutInLastDayPpe(Harness harness) {
        OnlineDbGetDataTasks onlineDbGetDataTasks = harness.tasks().cvm().onlineDbGetData();
        String clientPhoneNumber = harness.getConfig(CLIENT_PHONENUMBER_CONFIG_KEY);
        DayOfWeek todayDayOfWeek = LocalDate.now().getDayOfWeek();
        if (todayDayOfWeek == DayOfWeek.SUNDAY ||
                (todayDayOfWeek == DayOfWeek.MONDAY && LocalTime.now().isBefore(LocalTime.of(8, 30))) ||
                DateUtils.isStateHoliday(LocalDate.now())) {
            return; // Skip test
        }
        Result<Record> triggerLogRecords = onlineDbGetDataTasks.getTriggerLogsFinishedInLastDay(
                String.format(EVENT_DATA_TO_FIND, clientPhoneNumber));
        assertTrue(triggerLogRecords.isNotEmpty(), "Should be there at least one record");

    }

    @TestCase(name = "Check, there is not any finished drop out event in last 24 hours on sunday test run", environments = {TST1, PPE})
    public void checkNoFinishOfWebExpressDropOutInLastDayOnSunday(Harness harness) {
        if ((LocalDate.now().getDayOfWeek() == DayOfWeek.SUNDAY && LocalTime.now().isAfter(LocalTime.of(12, 0))) ||
                (LocalDate.now().getDayOfWeek() == DayOfWeek.MONDAY && LocalTime.now().isBefore(LocalTime.of(8, 30)))) {
            String clientPhoneNumber = harness.getConfig(CLIENT_PHONENUMBER_CONFIG_KEY);
            Result<Record> triggerLogRecords = harness.tasks().cvm().onlineDbGetData().getTriggerLogsFinishedInLastDay(
                    String.format(EVENT_DATA_TO_FIND, clientPhoneNumber));

            assertEquals(0, triggerLogRecords.size(), "Should not be there any finished record");
        }
    }

    @TestCase(name = "Check, whether there is exactly one planned web express loan drop out on monday morning for all processes " +
            "initiated by startWebExpressProcess calls during weekend", environments = {TST1, PPE})
    public void checkOnlyOneWebExpressDropOutPlannedToMondayMorning(Harness harness) {
        String clientPhoneNumber = harness.getConfig(CLIENT_PHONENUMBER_CONFIG_KEY);
        DayOfWeek todayDayOfWeek = LocalDate.now().getDayOfWeek();
        if (todayDayOfWeek == DayOfWeek.SUNDAY) {
            OnlineDbGetDataTasks onlineDbGetDataTasks = harness.tasks().cvm().onlineDbGetData();
            Result<Record> triggerLogRecords = onlineDbGetDataTasks.getTriggerLogsPlanned(String.format(EVENT_DATA_TO_FIND,
                    clientPhoneNumber));

            assertTrue(triggerLogRecords.isNotEmpty(), "Should be there at least one planned event");
            OnlineDbVerificationTasks onlineDbVerificationTasks = harness.tasks().cvm().onlineDbVerification();
            onlineDbVerificationTasks.assertLogRecordsPlannedToMondayMorning(WEB_EXP_DROPOUT_CC, triggerLogRecords.get(0), false);
            for (int i = 1; i < triggerLogRecords.size(); i++) {
                onlineDbVerificationTasks.assertLogRecordsPlannedToMondayMorning(WEB_EXP_DROPOUT_CC, triggerLogRecords.get(i), true);
            }

            if (LocalTime.now().isAfter(LocalTime.of(12, 0))) {
                Result<Record> canceledTriggerLogRecords =
                        onlineDbGetDataTasks.getTriggerLogsCanceledInLastDay(String.format(EVENT_DATA_TO_FIND, clientPhoneNumber));

                assertTrue(canceledTriggerLogRecords.isNotEmpty(), "Should be there at least one canceled event");
                for (Record canceledTriggerLogRecord : canceledTriggerLogRecords) {
                    onlineDbVerificationTasks.assertLogRecordsPlannedToMondayMorning(WEB_EXP_DROPOUT_CC, canceledTriggerLogRecord, false);
                }
            }
        }
    }

}