package cz.moneta.test.regression.transactional.payments.cashlessFirstTests.payment_engine.domestic.analytical;

import cz.moneta.test.dsl.Harness;
import cz.moneta.test.dsl.payment_engine.model.FileForInputPreparation;
import cz.moneta.test.dsl.payment_engine.tasks.PaymentEngineTasks;
import cz.moneta.test.dsl.payment_engine.utils.PaymentEngineUtils;
import cz.moneta.test.dsl.util.DateUtils;
import cz.moneta.test.dsl.util.credentials.Keys;
import cz.moneta.test.dsl.util.data.payment.PaymentData;
import cz.moneta.test.harness.annotations.Environment;
import cz.moneta.test.harness.annotations.JiraTestCase;
import cz.moneta.test.harness.annotations.TestCase;
import cz.moneta.test.harness.annotations.TestScenarioWithOrder;
import cz.moneta.test.harness.support.auth.Credentials;
import cz.moneta.test.harness.support.auth.Key;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Order;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.ThreadLocalRandom;

import static cz.moneta.test.dsl.payment_engine.enums.TransactionReasonPAE.*;
import static cz.moneta.test.dsl.payment_engine.parts_of_menu.menu_monitoring.PaymentEngineMonitoringInstanceFileRecords.SECOND_ROW_AMOUNT_KEY;
import static cz.moneta.test.dsl.payment_engine.parts_of_menu.menu_monitoring.PaymentEngineMonitoringInstanceFileRecords.TRANSACTION_ID_KEY;
import static cz.moneta.test.dsl.payment_engine.parts_of_menu.menu_search.PaymentEngineSearchTransactionDetailLifeCycle.*;
import static cz.moneta.test.dsl.payment_engine.parts_of_menu.menu_search.PaymentEngineSearchTransactionFiles.TRANSACTION_FILE_NAME_KEY;

@TestScenarioWithOrder(name = "Create Request For Direct Debit Return")
public class RequestForDirectDebitReturn extends FileForInputPreparation {

    private String TOKEN_CBL;
    private String HD11_FILE;
    private String HD33_FILE;
    private PaymentData data;
    private PaymentEngineTasks tasks;

    @BeforeAll
    void setUpTestData(Harness harness) {
        data = PaymentData.builder()
                .channelId("PAE - Payment Engine")
                .debtorName("TEST")
                .icbsProfile("COU11 - HD:11")
                .bankCode("0600")
                .bankName("MONETA Money Bank, a.s.")
                .payScheme("CZ CT Non-priority")
                .nextDayDist("Ne")
                .todayDate(DateUtils.convertRawDateForWso2(DateUtils.getTodayRawDate()))
                .submissionDate(DateUtils.getFormattedTodayDateTime("dd.MM.yyyy HH:mm:ss"))
                .documentDate(DateUtils.getFormattedTodayDate("dd.MM.yyyy"))
                .documentId(String.valueOf(ThreadLocalRandom.current().nextInt(100, 999)))
                .dateXpath("")
                .channelName("O_CCO_CERTIS")
                .debtorAcc(harness.getConfig("payments_cashless.domesticPayment.debtorAcc"))
                .hdType("79")
                .lastNonpriorityField(ThreadLocalRandom.current().nextInt(501, 698))
                .random(String.valueOf(ThreadLocalRandom.current().nextInt(1000000, 2999999)))
                .messageId(String.valueOf(ThreadLocalRandom.current().nextInt(100000, 999999)))
                .build();
        HD11_FILE = harness.getConfig("payments_cashless.foreignPayment.HD11-14_FILE");
        HD33_FILE = harness.getConfig("payments_cashless.foreignPayment.HD33_FILE");
        TOKEN_CBL = harness.tasks().wso2().authorization().getToken("DigitalchannelsSB_CBL");
    }

    @BeforeEach
    void setUpUniqueTestData(Harness harness) {
        tasks = new PaymentEngineTasks(harness);
        data.setAmount(String.valueOf(ThreadLocalRandom.current().nextInt(1, 299)));
    }

    private void checkTransactionStatusBooked(Harness harness, String account, String amountICBS, String transactionId) {
        String request = harness.tasks()
                .wso2()
                .payments()
                .createRequestForTransactionCheck(account, data.getTodayDate(), amountICBS);
        harness.tasks()
                .wso2()
                .payments()
                .checkTransactionStatusBooked(TOKEN_CBL, request, transactionId);
    }

    private void checkTransactionTypeStatusBooked(Harness harness, String account, String amountICBS, String transactionId) {
        String request = harness.tasks()
                .wso2()
                .payments()
                .createRequestForTransactionCheck(account, data.getTodayDate(), amountICBS);
        harness.tasks()
                .wso2()
                .payments()
                .checkTransactionTypeStatusBooked(TOKEN_CBL, request, transactionId, data);
    }

    @Order(1)
    @JiraTestCase(id = "PAY-T3624")
    @TestCase(name = "Create inhouse Request For Direct Debit Return HD:33", environments = {Environment.TST1, Environment.PPE})
    void createInhouseRequestForDirectDebitReturn(Harness harness, @Key(Keys.paymentEngine.firstUser) Credentials user1,
                                                  @Key(Keys.paymentEngine.secondUser) Credentials user2) {

        data.setTransactionType("HD:11 Úhrada klientská");
        data.setCreditorAcc(harness.getConfig("payments_cashless.domesticPayment.creditorAccInh"));

        tasks.loginTasks().logInPae(harness, user1)
                .then(tasks.createDomesticPayment(data));
        harness.withPaymentEngine().closePaymentEngine();

        String transactionId1 = PaymentEngineUtils.getTransactionalId(harness);

        tasks.loginTasks().logInPae(harness, user2)
                .then(tasks.verifyAndWaitForStatus(transactionId1, ARCHIV))
                .closeTab()
                .then(tasks.createInternalRequestForCancellation(transactionId1));
        harness.withPaymentEngine().closePaymentEngine();

        tasks.loginTasks().logInPae(harness, user1)
                .then(tasks.verifyRequestAndWaitForStatus(transactionId1, ARCHIV))
                .then(tasks.checkLifeCycleAndStoreRowTransactionIds())
                .waitForRowStatus(harness, harness.get(FORTH_ROW_TRANSACTION_ID_KEY), SENT)
                .waitForRowStatus(harness, harness.get(FIFTH_ROW_TRANSACTION_ID_KEY), ARCHIV)
                .storeSixthRowTransactionId()
                .waitForRowStatus(harness, harness.get(SIXTH_ROW_TRANSACTION_ID_KEY), ARCHIV);
        harness.withPaymentEngine().closePaymentEngine();

        String transactionId2 = harness.get(SECOND_ROW_TRANSACTION_ID_KEY);
        String transactionId3 = harness.get(THIRD_ROW_TRANSACTION_ID_KEY);
        String transactionId4 = harness.get(FORTH_ROW_TRANSACTION_ID_KEY);
        String transactionId5 = harness.get(FIFTH_ROW_TRANSACTION_ID_KEY);
        String transactionId6 = harness.get(SIXTH_ROW_TRANSACTION_ID_KEY);

        checkTransactionStatusBooked(harness, data.getDebtorAcc(), data.getAmount(), transactionId1);
        checkTransactionStatusBooked(harness, data.getCreditorAcc(), data.getAmount(), transactionId1);
        checkTransactionTypeStatusBooked(harness, data.getCreditorAcc(), data.getAmount(), transactionId1);

        PaymentEngineUtils.logResultOfRequestForDirectDebitReturn(harness, transactionId1, transactionId2, transactionId3,
                transactionId4, transactionId5, transactionId6, data);
    }

    @Order(2)
    @JiraTestCase(id = "PAY-T3626")
    @TestCase(name = "Create Outgoing Request For Direct Debit Return HD:33", environments = {Environment.TST1, Environment.PPE})
    void createOutgoingRequestForDirectDebitReturn(Harness harness, @Key(Keys.paymentEngine.firstUser) Credentials user1,
                                                   @Key(Keys.paymentEngine.secondUser) Credentials user2) {

        data.setTransactionType("HD:33 Žádost o storno úhrady (KS 5)");
        data.setCreditorAcc(harness.getConfig("payments_cashless.domesticPayment.creditorAcc"));
        data.setBankCode(harness.getConfig("payments_cashless.domesticPayment.bankCodeCr"));
        data.setBankName(harness.getConfig("payments_cashless.domesticPayment.bankNameCr"));

        tasks.loginTasks().logInPae(harness, user1)
                .then(tasks.createDomesticPaymentWithDates(data));
        harness.withPaymentEngine().closePaymentEngine();

        String transactionId = PaymentEngineUtils.getTransactionalId(harness);
        data.setBankName("MONETA Money Bank, a.s.");

        tasks.loginTasks().logInPae(harness, user2)
                .then(tasks.verifyAndWaitForStatus(transactionId, DISTRIBUTION))
                .closeTab()
                .then(tasks.sendAndRunCZCTDDistribution(data, SENT_WAIT, transactionId))
                .then(tasks.checkTransactionChannelAndStoreFileName(data));
        harness.withPaymentEngine().closePaymentEngine();

        PaymentEngineUtils.logResultShortWithFileName(harness, transactionId,
                harness.get(TRANSACTION_FILE_NAME_KEY), data);
    }

    @Order(3)
    @JiraTestCase(id = "PAY-T3611")
    @TestCase(name = "Create Ingoing Request For Direct Debit Return HD:33", environments = {Environment.TST1, Environment.PPE})
    void createIngoingRequestForDirectDebitReturn(Harness harness, @Key(Keys.paymentEngine.firstUser) Credentials user1,
                                                  @Key(Keys.paymentEngine.secondUser) Credentials user2) throws IOException {
        data.setCreditorAcc(harness.getConfig("payments_cashless.domesticPayment.creditorAccInh"));
        data.setTodayDate(DateUtils.getFormattedTodayDate("yyyyMMdd"));
        data.setHdType("11");

        String HD11FileName = data.getTodayDate() + "_0600_000" + data.getLastNonpriorityField() + "_IL";
        File HD11File = prepareFileForInput(harness, HD11_FILE, HD11FileName, data);

        data.setRandom(String.valueOf(ThreadLocalRandom.current().nextInt(1000000, 2999999)));
        String HD33FileName = data.getTodayDate() + "_0600_000" + (data.getLastNonpriorityField() + 1) + "_IL";
        File HD33File = prepareFileForInput(harness, HD33_FILE, HD33FileName, data);

        data.setTodayDate(DateUtils.getFormattedTodayDate("yyyy-MM-dd"));

        try {
            tasks.loginTasks().logInPae(harness, user1)
                    .then(tasks.inputCCIFromCERTIS(HD11File.getAbsolutePath()))
                    .wait3sec() //the previous instance has to be finished
                    .then(tasks.inputCCIFromCERTIS(HD33File.getAbsolutePath()))
                    .then(tasks.checkStatusOfCCIFromCERTIS(HD11FileName, RELEASE))
                    .then(tasks.runReleaseAfterDispoCheck(ARCHIV, harness.get(TRANSACTION_ID_KEY)));
            harness.withPaymentEngine().closePaymentEngine();

            data.setAmount(harness.get(SECOND_ROW_AMOUNT_KEY).toString().replace(",", "."));
            String HD11TransactionId = harness.get(TRANSACTION_ID_KEY);
            String transactionIdFromFile = DateUtils.getFormattedTodayDate("yyMMdd") + "IDHD11x" + data.getMessageId();

            checkTransactionStatusBooked(harness, data.getDebtorAcc(), data.getAmount(), transactionIdFromFile);

            tasks.loginTasks().logInPae(harness, user1)
                    .then(tasks.checkStatusOfCCIFromCERTIS(HD33FileName, SENT));
            harness.withPaymentEngine().closePaymentEngine();

            String HD33TransactionId = harness.get(TRANSACTION_ID_KEY);

            harness.store("reports.tmfj.execution.comment", "HD:11 ingoing " + HD11TransactionId + " was successfully archived."
                    + "\n" + "HD:33 outgoing " + HD33TransactionId + " status: " + SENT
                    + "\n" + "Originators Document ID " + transactionIdFromFile + " was successfully archived in ICBS."
                    + "\n" + "HD:11 file: " + HD11FileName
                    + "\n" + "HD:33 file: " + HD33FileName
                    + "\n" + "Debtor account: " + data.getDebtorAcc()
                    + "\n" + "Creditor account: " + data.getCreditorAcc()
                    + "\n" + "Amount: " + data.getAmount());

        } catch (Exception e) {
            throw e;
        } finally {
            HD11File.delete();
            HD33File.delete();
        }
    }
}