package cz.moneta.test.dsl.util.task.udebs;

import cz.moneta.test.dsl.udebs.Udebs;
import cz.moneta.test.dsl.util.task.udebs.cbljournal.CblJournalTasks;
import cz.moneta.test.harness.context.StoreAccessor;
import cz.moneta.test.harness.endpoints.udebs.UdebsEndpoint;
import cz.moneta.test.harness.exception.HarnessException;
import cz.moneta.test.harness.support.auth.Credentials;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.Optional;

public class UdebsTasks {

    private static final Logger logger = LogManager.getLogger(UdebsTasks.class);

    private final StoreAccessor harness;

    // envelope number from UDEBS
    private final String GET_ENVELOPE_QUERY =
            "SELECT " +
                    "     cislo_obalky " +
                    " FROM " +
                    "     ( " +
                    "         SELECT " +
                    "             envelopeid as cislo_obalky " +
                    "         FROM " +
                    "             csdbge.ge_envelopepassw " +
                    "         WHERE " +
                    "             status = 3 " +
                    "             AND envelopetype = 1 " +
                    "             AND sms is null " +
                    "             AND assignedby is null " +
                    "         ORDER BY " +
                    "             dbms_random.random " +
                    "     ) " +
                    " WHERE " +
                    "     ROWNUM = 1";

    // envelope number from UDEBS without prefix 0
    private final String GET_ENVELOPE_QUERY_WITHOUT_PREFIX_ZERO =
            "SELECT " +
                    "     cislo_obalky " +
                    " FROM " +
                    "     ( " +
                    "         SELECT " +
                    "             ltrim(TO_CHAR(envelopeid),'0') cislo_obalky " +
                    "         FROM " +
                    "             csdbge.ge_envelopepassw " +
                    "         WHERE " +
                    "             status = 3 " +
                    "             AND envelopetype = 1 " +
                    "             AND sms is null " +
                    "             AND assignedby is null " +
                    "         ORDER BY " +
                    "             dbms_random.random " +
                    "     ) " +
                    " WHERE " +
                    "     ROWNUM = 1";

    private final String CHECK_ACC_NUM_INKASO_EXISTS =
            "SELECT accountid,  " +
                    "       CREDITACCOUNTID, " +
                    "       creditbankid " +
                    "  FROM collectionpermission " +
                    " WHERE accountid = '#CLIENT_ACC_NUM' " +
                    "   and creditaccountid = '#PARTNER_ACC_NUM' ";

    public UdebsTasks(StoreAccessor harness) {
        this.harness = harness;
    }

    public CblJournalTasks cblJournal() {
        return new CblJournalTasks(harness);
    }

    public Credentials findCredentialsByRC(String birthNumber) {
        return new Udebs(harness).ib().usernameAndPassword().getUsernameAndPasswordByRc(birthNumber);
    }

    private String getEnvelopeNumberFromQuery(String envelopeQuery) {
        String envelopeNumber = Optional.of(harness.getEndpoint(UdebsEndpoint.class))
                .map(e -> e.executeSql(envelopeQuery))
                .flatMap(rs -> rs.stream().findFirst())
                .map(r -> r.getValue(0, String.class))
                .orElseThrow(() -> new HarnessException("Error getting envelope number from UDEBS."));
        logger.log(Level.INFO, "Envelope number obtained from UDEBS: {}.", envelopeNumber);
        return envelopeNumber;
    }

    public String getEnvelopeNumberWithoutPrefixZero() {
        return getEnvelopeNumberFromQuery(GET_ENVELOPE_QUERY_WITHOUT_PREFIX_ZERO);
    }

    public String getEnvelopeNumber() {
        return getEnvelopeNumberFromQuery(GET_ENVELOPE_QUERY);
    }

    public boolean isExistInkasoCombination(String clientAccountNumber, String partnerAccountNumber) {
        String clientAccNum = StringUtils.leftPad(clientAccountNumber, 10, '0');
        String partnerAccNum = "000000 " + StringUtils.leftPad(partnerAccountNumber, 10, '0');
        return harness.getEndpoint(UdebsEndpoint.class)
                .executeSql(CHECK_ACC_NUM_INKASO_EXISTS.replaceAll("#CLIENT_ACC_NUM", clientAccNum).replaceAll("#PARTNER_ACC_NUM", partnerAccNum))
                .isNotEmpty();
    }
}
