package cz.moneta.test.dsl.util.task.cvm.onlinedb;

import cz.moneta.test.dsl.Harness;
import cz.moneta.test.dsl.util.DateUtils;
import cz.moneta.test.harness.endpoints.ods.OdsEndpoint;
import org.jooq.Record;
import org.jooq.Result;

import java.time.DayOfWeek;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class OnlineDbGetDataTasks {

    public static final String PAYLOAD_ATTRIBUTE_NAME_ACTIVITY_ID = "$.activityId";
    public static final String PAYLOAD_ATTRIBUTE_NAME_CLIENT_PHONE_NUMBER = "$.data.clientMobilePhoneNumber";

    private static final String SELECT_ONLINE_DATA_BY_SYSTEM_AND_ACTIVITY_ID = "" +
            "SELECT * " +
            "FROM SAS_RTDM_OWNER.SASRT_ONLINE_DATA " +
            "WHERE SRC_SYS_ID = '%s' AND (MSG_ID = '%s' OR MSG_ID like '%s.%%') " +
            "ORDER BY MSG_ID, NAME";

    private static final String SELECT_ONLINE_DATA_BASE_MSG_ID_LAST_CHANGED = "" +
            "SELECT MSG_ID " +
            "FROM ( " +
            "   SELECT * " +
            "   FROM SAS_RTDM_OWNER.SASRT_ONLINE_DATA " +
            "   WHERE SRC_SYS_ID = '%s' AND SRC_ID = '%s' AND NAME = 'UNI_PT_KEY' AND INS_DT > SYSDATE - INTERVAL '1' MINUTE " +
            "   ORDER BY INS_DT DESC " +
            ") " +
            "WHERE ROWNUM = 1 ";

    private static final String SELECT_SCHEDULED_TASK_BY_PAYLOAD_ATTRIBUTE = "" +
            "SELECT SCHD.TASK_NAME, " +
            "   SCHD.TASK_INSTANCE, " +
            "   SCHD.TASK_DATA, " +
            "   TO_CHAR(SCHD.EXECUTION_TIME, 'YYYY-MM-DD\"T\"hh24:mi:sstzh:tzm') AS EXECUTION_TIME, " +
            "   SCHD.PICKED, " +
            "   SCHD.PICKED_BY, " +
            "   TO_CHAR(SCHD.LAST_SUCCESS, 'YYYY-MM-DD\"T\"hh24:mi:sstzh:tzm') AS LAST_SUCCESS, " +
            "   TO_CHAR(SCHD.LAST_FAILURE, 'YYYY-MM-DD\"T\"hh24:mi:sstzh:tzm') AS LAST_FAILURE, " +
            "   SCHD.CONSECUTIVE_FAILURES, " +
            "   TO_CHAR(SCHD.LAST_HEARTBEAT, 'YYYY-MM-DD\"T\"hh24:mi:sstzh:tzm') AS LAST_HEARTBEAT, " +
            "   SCHD.VERSION, " +
            "   TO_NUMBER(ATT.ATTR_VALUE) AS ORIGINAL_PLANNED_TIME " +
            "FROM SAS_RTDM_OWNER.SASRT_ONLINE_DATA_RTRD_SCHD SCHD " +
            "   JOIN SAS_RTDM_OWNER.SASRT_RTRD_TRIGGER_LOG TR " +
            "       ON (SCHD.TASK_NAME = TR.TASK_NAME AND SCHD.TASK_INSTANCE = TR.TASK_INSTANCE) " +
            "   LEFT JOIN SAS_RTDM_OWNER.SASRT_ONLINE_DATA_RTRD_SCHD_AT ATT " +
            "       ON (SCHD.TASK_NAME = ATT.TASK_NAME AND SCHD.TASK_INSTANCE = ATT.TASK_INSTANCE " +
            "               AND ATT.ATTR_NAME = 'originalPlannedTime') " +
            "WHERE json_value(TASK_DATA, '%s') = '%s' " +
            "ORDER BY TR.PLANNING_TIME";

    private static String SASRT_RTRD_TRIGGER_LOG_COLUMNS = "" +
            "   RTRD_SOURCE_ENDPOINT_NAME, " +
            "   ACTIVITY_ID, " +
            "   WSO2_TARGET_ENDPOINT_NAME, " +
            "   TASK_NAME, " +
            "   TASK_INSTANCE, " +
            "   TO_CHAR(INS_DT, 'YYYY-MM-DD\"T\"hh24:mi:sstzh:tzm') AS INS_DT, " +
            "   TO_CHAR(UPD_DT, 'YYYY-MM-DD\"T\"hh24:mi:sstzh:tzm') AS UPD_DT, " +
            "   CONSECUTIVE_ATTEMPTS, " +
            "   TO_CHAR(PLANNING_TIME, 'YYYY-MM-DD\"T\"hh24:mi:sstzh:tzm') AS PLANNING_TIME, " +
            "   TO_CHAR(EXECUTION_TIME, 'YYYY-MM-DD\"T\"hh24:mi:sstzh:tzm') AS EXECUTION_TIME, " +
            "   TO_CHAR(SUCCEEDED_TIME, 'YYYY-MM-DD\"T\"hh24:mi:sstzh:tzm') AS SUCCEEDED_TIME, " +
            "   TO_CHAR(FAILED_TIME, 'YYYY-MM-DD\"T\"hh24:mi:sstzh:tzm') AS FAILED_TIME, " +
            "   TO_CHAR(CANCELED_TIME, 'YYYY-MM-DD\"T\"hh24:mi:sstzh:tzm') AS CANCELED_TIME, " +
            "   DATA ";

    private static final String SELECT_TRIGGER_LOG_BY_ENDPOINT_AND_ACTIVITY_ID = "" +
            "SELECT " + SASRT_RTRD_TRIGGER_LOG_COLUMNS +
            "FROM SAS_RTDM_OWNER.SASRT_RTRD_TRIGGER_LOG " +
            "WHERE RTRD_SOURCE_ENDPOINT_NAME = '%s' AND ACTIVITY_ID like '%s' " +
            "ORDER BY EXECUTION_TIME, PLANNING_TIME";

    private static final String SELECT_TRIGGER_LOG_FINISHED_IN_LAST_DAY_BY_DATA = "" +
            "SELECT " + SASRT_RTRD_TRIGGER_LOG_COLUMNS +
            "FROM SAS_RTDM_OWNER.SASRT_RTRD_TRIGGER_LOG " +
            "WHERE DATA LIKE '%%%s%%' " +
            "   AND (SUCCEEDED_TIME >= SYSTIMESTAMP - INTERVAL '1' DAY OR FAILED_TIME >= SYSTIMESTAMP - INTERVAL '1' DAY) " +
            "ORDER BY EXECUTION_TIME, PLANNING_TIME";

    private static final String SELECT_TRIGGER_LOG_PLANNED_BY_DATA = "" +
            "SELECT " + SASRT_RTRD_TRIGGER_LOG_COLUMNS +
            "FROM SAS_RTDM_OWNER.SASRT_RTRD_TRIGGER_LOG " +
            "WHERE DATA LIKE '%%%s%%' AND SUCCEEDED_TIME IS NULL AND FAILED_TIME IS NULL AND CANCELED_TIME IS NULL " +
            "ORDER BY EXECUTION_TIME, PLANNING_TIME";

    private static final String SELECT_TRIGGER_LOG_CANCELED_IN_LAST_DAY_BY_DATA = "" +
            "SELECT " + SASRT_RTRD_TRIGGER_LOG_COLUMNS +
            "FROM SAS_RTDM_OWNER.SASRT_RTRD_TRIGGER_LOG " +
            "WHERE DATA LIKE '%%%s%%' AND CANCELED_TIME >= SYSTIMESTAMP - INTERVAL '1' DAY " +
            "ORDER BY EXECUTION_TIME, PLANNING_TIME";

    private static final String SELECT_DECISION_LOG_IN_LAST_DAY_BY_FLOW_NAME_AND_REQUEST_VARIABLES = "" +
            "SELECT DECISION_LOG_KEY, " +
            "   TO_CHAR(EVENT_DT, 'YYYY-MM-DD\"T\"hh24:mi:ss') AS EVENT_DT, " +
            "   RTDM_FLOW_NAME, " +
            "   MSG_ID, " +
            "   REQUEST_VARIABLES_STRING, " +
            "   DECISION_VARIABLES_STRING, " +
            "   RESPONSE_VARIABLES_STRING " +
            "FROM SAS_RTDM_OWNER.SASRT_DECISION_LOG " +
            "WHERE EVENT_DT > SYSDATE - INTERVAL '1' DAY AND RTDM_FLOW_NAME LIKE '%s%%' AND REQUEST_VARIABLES_STRING LIKE '%%%s%%' " +
            "ORDER BY EVENT_DT";

    private static final String SELECT_CLIENT_CONSENTS = "" +
            "SELECT UNI_PT_KEY, " +
            "   CIF, " +
            "   RC_NUM, " +
            "   ICO_NUM, " +
            "   CITIZENSHIP_ID, " +
            "   CNST_MKT_EMAIL, " +
            "   CNST_MKT_IB_SB, " +
            "   CNST_MKT_SURVEY, " +
            "   CNST_MKT_PHONE, " +
            "   CNST_MKT_POST, " +
            "   CNST_MKT_SMS, " +
            "   CNST_BANKSECRET_UNSECUR, " +
            "   TO_CHAR(CNST_UPD_DT, 'YYYY-MM-DD\"T\"hh24:mi:ss') AS CNST_UPD_DT " +
            "FROM SAS_RTDM_OWNER.SASRT_CLIENT " +
            "WHERE UNI_PT_KEY = %s AND ROWNUM = 1";

    private Harness harness;

    public OnlineDbGetDataTasks(Harness harness) {
        this.harness = harness;
    }

    public Result<Record> getOnlineData(String sourceSystem, String activityId) {
        return harness.getEndpoint(OdsEndpoint.class)
                .executeSql(String.format(SELECT_ONLINE_DATA_BY_SYSTEM_AND_ACTIVITY_ID, sourceSystem, activityId, activityId));
    }

    public String getOnlineDataBaseMsgIdLastChanged(String sourceSystem, String sourceId) {
        Result<Record> records = harness.getEndpoint(OdsEndpoint.class)
                .executeSql(String.format(SELECT_ONLINE_DATA_BASE_MSG_ID_LAST_CHANGED, sourceSystem, sourceId));
        return records.isNotEmpty() ? (String) records.get(0).getValue("MSG_ID") : null;
    }

    public Result<Record> getPlannedTasks(String payloadAttributeName, String payloadAttributeValue) {
        return harness.getEndpoint(OdsEndpoint.class)
                .executeSql(String.format(SELECT_SCHEDULED_TASK_BY_PAYLOAD_ATTRIBUTE, payloadAttributeName, payloadAttributeValue));
    }

    public Result<Record> getTriggerLogs(String rtrdSourceEndpointName, String activityId) {
        return harness.getEndpoint(OdsEndpoint.class)
                .executeSql(String.format(SELECT_TRIGGER_LOG_BY_ENDPOINT_AND_ACTIVITY_ID, rtrdSourceEndpointName, activityId));
    }

    public Result<Record> getTriggerLogsFinishedInLastDay(String dataSubString) {
        return harness.getEndpoint(OdsEndpoint.class)
                .executeSql(String.format(SELECT_TRIGGER_LOG_FINISHED_IN_LAST_DAY_BY_DATA, dataSubString));
    }

    public Result<Record> getTriggerLogsPlanned(String dataSubString) {
        return harness.getEndpoint(OdsEndpoint.class)
                .executeSql(String.format(SELECT_TRIGGER_LOG_PLANNED_BY_DATA, dataSubString));
    }

    public Result<Record> getTriggerLogsCanceledInLastDay(String dataSubString) {
        return harness.getEndpoint(OdsEndpoint.class)
                .executeSql(String.format(SELECT_TRIGGER_LOG_CANCELED_IN_LAST_DAY_BY_DATA, dataSubString));
    }

    public ZonedDateTime getNearestContactCenterWorkingHours(ZonedDateTime dateTime) {
        if (dateTime.toLocalTime().isBefore(LocalTime.of(8, 30))) {
            dateTime = dateTime.withHour(8).withMinute(30).withSecond(0).withNano(0);
        }
        if (dateTime.toLocalTime().isAfter(LocalTime.of(17, 0))) {
            dateTime = dateTime.plusDays(1).withHour(8).withMinute(30).withSecond(0).withNano(0).withZoneSameLocal(ZoneId.systemDefault());
        }
        while ((dateTime.getDayOfWeek() == DayOfWeek.SATURDAY && dateTime.toLocalTime().isAfter(LocalTime.of(12, 0))) ||
                dateTime.getDayOfWeek() == DayOfWeek.SUNDAY ||
                DateUtils.isStateHoliday(dateTime.toLocalDate())) {
            dateTime = dateTime.plusDays(1).withHour(8).withMinute(30).withSecond(0).withNano(0).withZoneSameLocal(ZoneId.systemDefault());
        }
        return dateTime;
    }

    public Result<Record> getDecisionLogInLastDay(String flowName, String requestVariablesSubstring) {
        return harness.getEndpoint(OdsEndpoint.class)
                .executeSql(String.format(SELECT_DECISION_LOG_IN_LAST_DAY_BY_FLOW_NAME_AND_REQUEST_VARIABLES,
                        flowName, requestVariablesSubstring));
    }

    public Record getClientConsents(Long uniPtKey) {
        Result<Record> records = harness.getEndpoint(OdsEndpoint.class)
                .executeSql(String.format(SELECT_CLIENT_CONSENTS, uniPtKey));
        return records.isNotEmpty() ? records.get(0) : null;
    }
}
