package cz.moneta.test.regression.channels.digital.ib.newib.payment.fon;

import cz.moneta.test.dsl.Harness;
import cz.moneta.test.dsl.newib.tasks.NewIbTasks;
import cz.moneta.test.dsl.newib.util.PaymentFormData;
import cz.moneta.test.dsl.util.DateUtils;
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 org.junit.jupiter.api.*;

import java.text.DecimalFormat;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.ThreadLocalRandom;

import static cz.moneta.test.dsl.newib.tasks.NewIbTasks.DEFAULT_MOBILE_KEY;
import static cz.moneta.test.harness.support.data.GeneratorType.ACCOUNT_NUMBER;

@TestScenarioWithOrder(name = "Domestic payment order")
public class DomesticPaymentOrderTest {
    Credentials clientCredentials;
    PaymentFormData formData;
    double generatedPayment;
    String generatedPaymentString;
    String clientId;
    String generatedRecipientAccountNumber;

    private double generateRandomPayment() {
        String random = new DecimalFormat("#.00").format(ThreadLocalRandom.current().nextDouble(1.00, 2.00));
        generatedPaymentString = random.replace(".", ",");
        return Double.parseDouble(random.replace(",", "."));
    }

    @BeforeEach
    public void generatePayment(Harness harness) {
        generatedPayment = generateRandomPayment();
        harness.log("Generated payment is " + generatedPayment);
    }

    @BeforeAll
    public void setup(Harness harness) {
        String clientBirthNumber = harness.getConfig("nib.rc.priority-payment");
        String fromAccountNumber = harness.getConfig("nib.fromaccount.priority-payment");
        String recipientAccountNumber = harness.getConfig("nib.recipientaccount.czk-currency");
        String recipientAccountNumberOtherBank = harness.getConfig("nib.recipientaccount.outside-moneta.czk-currency");

        clientCredentials = harness.tasks()
                .udebs()
                .findCredentialsByRC(clientBirthNumber);

        clientId = harness.withUdebs()
                .usersTable()
                .getClientId(clientBirthNumber);

        generatedRecipientAccountNumber = harness.generate(ACCOUNT_NUMBER);

        formData = PaymentFormData.builder()
                .fromAccountType("Běžný účet CZK")
                .fromAccountNumber(fromAccountNumber)
                .recipientAccountNumber(recipientAccountNumber)
                .recipientAccountNumberOtherBank(recipientAccountNumberOtherBank)
                .category("Bankomat")
                .bankCode("0600")
                .bankCodeOtherBank("0100")
                .variableSymbol("111")
                .constantSymbol("2222")
                .specificSymbol("33333")
                .recipientMessage("Toto je zpráva pro příjemce")
                .myNote("Toto je moje poznamka")
                .build();

        harness.tasks().wso2().client().subsidyCzkAccount(fromAccountNumber, 12);
    }

    private void assertAmountsEqual(double expected, double actual) {
        Assertions.assertEquals(expected, actual, "Expected payment: " + expected + ", but actual payment in udebs: " + actual);
    }

    @Order(1)
    @TestCase(name = "Domestic payment order – Priority - all steps", environments = {Environment.TST1, Environment.PPE})
    @JiraTestCase(id = "SB-T9192")
    public void domesticPaymentOrderPriorityAllSteps(Harness harness) {
        NewIbTasks newIbTasks = harness.tasks().newIb();
        formData.setAmount(generatedPaymentString);
        formData.setDateOfPayment(DateUtils.getFormattedTodayDate("d. M. yyyy"));
        formData.setTypeOfPayment("Prioritní");

        Assumptions.assumeTrue(LocalTime.now().isBefore(LocalTime.of(14, 0)),
                "Skipped: Priority payments are processed only until 14:00.");

        harness.withNewIb()
                .openLoginPage()
                .then(newIbTasks.loginWithUsernamePasswordAndDefaultMobKey(clientCredentials.getUsername(), clientCredentials.getPassword()))
                .then(newIbTasks.setDomesticPriorityPaymentFirstStep(formData))
                .then(newIbTasks.setDomesticPriorityPaymentSecondStep(formData))
                .then(newIbTasks.setDomesticPaymentThirdStep(formData));

        double amount = harness.withUdebs()
                .accountMovements()
                .getAmountLastAccountMovement(180, formData.getFromAccountNumber(), formData.getRecipientAccountNumberOtherBank(), String.valueOf(generatedPayment));

        assertAmountsEqual(generatedPayment, amount);
        harness.log("Generated payment is:" + generatedPayment + " and amount in UDEBS is: " + amount);
    }

    @Order(2)
    @TestCase(name = "Domestic payment order – payment from template", environments = {Environment.TST1, Environment.PPE})
    @JiraTestCase(id = "SB-T9362")
    public void domesticPaymentOrderFromTemplate(Harness harness) {
        NewIbTasks newIbTasks = harness.tasks().newIb();
        formData.setAmount(generatedPaymentString);
        formData.setTemplateName("Název šablony" + generatedPaymentString);

        harness.withNewIb()
                .openLoginPage()
                .then(newIbTasks.loginWithUsernamePasswordAndDefaultMobKey(clientCredentials.getUsername(), clientCredentials.getPassword()))
                .then(newIbTasks.setDomesticPaymentSaveTemplate(formData))
                .then(newIbTasks.setDomesticPaymentFromTemplate(formData))
                .clickOverviewTransactions()
                .onHistoryTabs()
                .checkTransaction(formData.getRecipientAccountNumber(), "-" + generatedPayment)
                .clickOnSettings()
                .clickOnTemplates()
                .then(newIbTasks.deleteTemplate(formData));

        double amount = harness.withUdebs()
                .accountMovements()
                .getAmountLastAccountMovement(180, formData.getFromAccountNumber(), formData.getRecipientAccountNumber(), String.valueOf(generatedPayment));

        assertAmountsEqual(generatedPayment, amount);
        harness.log("Generated payment is:" + generatedPayment + " and amount in UDEBS is: " + amount);
    }

    @Order(3)
    @TestCase(name = "Domestic payment order – Instant - all steps", environments = {Environment.TST1, Environment.PPE})
    @JiraTestCase(id = "SB-T9195")
    public void domesticPaymentOrderInstantAllSteps(Harness harness) {
        NewIbTasks newIbTasks = harness.tasks().newIb();
        formData.setAmount(generatedPaymentString);
        formData.setTypeOfPayment("Okamžitá");
        formData.setDateOfPayment("Okamžitě");

        harness.withNewIb()
                .openLoginPage()
                .then(newIbTasks.loginWithUsernamePasswordAndDefaultMobKey(clientCredentials.getUsername(), clientCredentials.getPassword()))
                .then(newIbTasks.setDomesticPaymentFirstStep(formData))
                .clickContinue()
                .then(newIbTasks.checkSummaryPaymentPageAndConfirmWithMobileKey(formData))
                .then(newIbTasks.setDomesticPaymentThirdStep(formData));

        double amount = harness.withUdebs()
                .accountMovements()
                .getAmountLastAccountMovement(180, formData.getFromAccountNumber(), formData.getRecipientAccountNumber(), String.valueOf(generatedPayment));

        assertAmountsEqual(generatedPayment, amount);
        harness.log("Generated payment is:" + generatedPayment + " and amount in UDEBS is: " + amount);
    }

    @Order(4)
    @TestCase(name = "Domestic payment order – standard", environments = {Environment.TST1, Environment.PPE})
    @JiraTestCase(id = "SB-T9196")
    public void domesticPaymentOrderStandardAllSteps(Harness harness) {
        NewIbTasks newIbTasks = harness.tasks().newIb();
        formData.setAmount(generatedPaymentString);
        formData.setTypeOfPayment("Standardní");
        formData.setDateOfPayment(DateUtils.getFormattedTodayDate("d. M. yyyy"));

        harness.withNewIb()
                .openLoginPage()
                .then(newIbTasks.loginWithUsernamePasswordAndDefaultMobKey(clientCredentials.getUsername(), clientCredentials.getPassword()))
                .then(newIbTasks.setDomesticPaymentFirstStep(formData))
                .clickContinue()
                .then(newIbTasks.checkSummaryPaymentPageAndConfirmWithMobileKey(formData))
                .then(newIbTasks.setDomesticPaymentThirdStep(formData));

        double amount = harness.withUdebs()
                .accountMovements()
                .getAmountLastAccountMovement(180, formData.getFromAccountNumber(), formData.getRecipientAccountNumber(), String.valueOf(generatedPayment));

        assertAmountsEqual(generatedPayment, amount);
        harness.log("Generated payment is:" + generatedPayment + " and amount in UDEBS is: " + amount);
    }

    @Order(5)
    @TestCase(name = "Domestic payment order – standard – future due date", environments = {Environment.TST1, Environment.PPE})
    @JiraTestCase(id = "SB-T9190")
    public void domesticPaymentOrderStandardFutureDueDate(Harness harness) {
        NewIbTasks newIbTasks = harness.tasks().newIb();
        formData.setAmount(generatedPaymentString);
        formData.setTypeOfPayment("Standardní");
        formData.setDateOfPayment(DateUtils.getNextWorkday().format(DateTimeFormatter.ofPattern("d. M. yyyy")));

        harness.withNewIb()
                .openLoginPage()
                .then(newIbTasks.loginWithUsernamePasswordAndDefaultMobKey(clientCredentials.getUsername(), clientCredentials.getPassword()))
                .then(newIbTasks.setDomesticPaymentFirstStep(formData))
                .fillDate(formData.getDateOfPayment())
                .clickContinue()
                .then(newIbTasks.checkSummaryPaymentPageAndConfirmWithMobileKey(formData))
                .clickOverviewTransactions()
                .clickOnFuturePayment()
                .checkFuturePaymentVisible(formData.getAmount())
                .clickOnFutureOrderPayment(formData.getAmount())
                .then(newIbTasks.checkFutureTransaction(formData));
    }

    @Order(6)
    @TestCase(name = "Domestic payment order – standard – future due date cancel", environments = {Environment.TST1, Environment.PPE})
    @JiraTestCase(id = "SB-T9191")
    public void domesticPaymentOrderStandardFutureDueDateCancel(Harness harness) {
        NewIbTasks newIbTasks = harness.tasks().newIb();
        formData.setAmount(generatedPaymentString);
        formData.setTypeOfPayment("Standardní");
        formData.setDateOfPayment(DateUtils.getNextWorkday().format(DateTimeFormatter.ofPattern("d. M. yyyy")));

        harness.withNewIb()
                .openLoginPage()
                .then(newIbTasks.loginWithUsernamePasswordAndDefaultMobKey(clientCredentials.getUsername(), clientCredentials.getPassword()))
                .then(newIbTasks.setDomesticPaymentFirstStep(formData))
                .fillDate(formData.getDateOfPayment())
                .clickContinue()
                .then(newIbTasks.checkSummaryPaymentPageAndConfirmWithMobileKey(formData))
                .clickOverviewTransactions()
                .clickOnFuturePayment()
                .checkFuturePaymentVisible(formData.getAmount())
                .clickOnFutureOrderPayment(formData.getAmount())
                .clickOnCancelPaymentButton()
                .clickOnConfirmCancelPaymentButton()
                .checkCancelVictoryText();
    }

    //only PPE due to hackemon settings
    @Order(7)
    @TestCase(name = "Switching from instant payment to standard payment and cancel it", environments = {Environment.PPE})
    @JiraTestCase(id = "SB-T9703")
    public void fromInstantToStandardPaymentCancel(Harness harness) {
        NewIbTasks newIbTasks = harness.tasks().newIb();
        formData.setAmount("26000");
        formData.setTypeOfPayment("Okamžitá");
        formData.setRecipientAccountNumber(generatedRecipientAccountNumber);
        formData.setBankCode("0300");
        String channelId = "15";

        harness.withNewIb()
                .openLoginPage()
                .then(newIbTasks.loginWithUsernamePasswordAndDefaultMobKey(clientCredentials.getUsername(), clientCredentials.getPassword()))
                .then(newIbTasks.setDomesticPaymentFirstStep(formData))
                .clickContinue()
                .clickContinue()
                .fillMobileKey(DEFAULT_MOBILE_KEY)
                .clickMobileKey()
                .checkPaymentSwithToStandardTitle()
                .checkPaymentSwithToStandardText()
                .clickCancelPayment();

        String statusCanceledDomesticPayment = harness.withUdebs()
                .transactionsClient()
                .getLastTransactionStatus(clientId, "301", channelId, 30, "65");

        Assertions.assertEquals("65", statusCanceledDomesticPayment, "Status of created payment  is not equals expected status");
        harness.log("Expected status is: " + "65" + " and status in UDEBS is: " + statusCanceledDomesticPayment);

        String statusCreatedSwitchedPayment = harness.withUdebs()
                .transactionsClient()
                .getLastTransactionStatus(clientId, "317", channelId, 30, "60");

        Assertions.assertEquals("60", statusCreatedSwitchedPayment, "Status of created operation  is not equals expected status");
        harness.log("Expected status is: " + "60" + " and status in UDEBS is: " + statusCreatedSwitchedPayment);
    }

    //only PPE due to hackemon settings
    @Order(8)
    @TestCase(name = "Switching from instant payment to standard payment and confirm  it", environments = {Environment.PPE})
    @JiraTestCase(id = "SB-T9536")
    public void fromInstantToStandardPaymentConfirm(Harness harness) {
        NewIbTasks newIbTasks = harness.tasks().newIb();
        formData.setAmount("26000");
        formData.setTypeOfPayment("Okamžitá");
        formData.setRecipientAccountNumber(generatedRecipientAccountNumber);
        formData.setBankCode("0300");
        String channelId = "15";
        String fromAccountNumber = formData.getFromAccountNumber();
        harness.tasks().wso2().client().subsidyCzkAccount(fromAccountNumber, 26000);

        harness.withNewIb()
                .openLoginPage()
                .then(newIbTasks.loginWithUsernamePasswordAndDefaultMobKey(clientCredentials.getUsername(), clientCredentials.getPassword()))
                .then(newIbTasks.setDomesticPaymentFirstStep(formData))
                .clickContinue()
                .clickContinue()
                .fillMobileKey(DEFAULT_MOBILE_KEY)
                .clickMobileKey()
                .checkPaymentSwithToStandardTitle()
                .checkPaymentSwithToStandardText()
                .confirmStandardPayment();

        String statusConfirmDomesticPayment = harness.withUdebs()
                .transactionsClient()
                .getLastTransactionStatus(clientId, "301", channelId, 30, "46");

        Assertions.assertEquals("46", statusConfirmDomesticPayment, "Status of created payment  is not equals expected status");
        harness.log("Expected status is: " + "46" + " and status in UDEBS is: " + statusConfirmDomesticPayment);

        String statusCreatedSwitchedPayment = harness.withUdebs()
                .transactionsClient()
                .getLastTransactionStatus(clientId, "317", channelId, 30, "60");

        Assertions.assertEquals("60", statusCreatedSwitchedPayment, "Status of created operation  is not equals expected status");
        harness.log("Expected status is: " + "60" + " and status in UDEBS is: " + statusCreatedSwitchedPayment);
    }

    @Order(9)
    @TestCase(name = "Domestic payment order – to own accounts", environments = {Environment.TST1, Environment.PPE})
    @JiraTestCase(id = "SB-T9726")
    public void domesticPaymentOrderToOwnAccountFon(Harness harness) {
        NewIbTasks newIbTasks = harness.tasks().newIb();
        formData.setAmount(generatedPaymentString);
        formData.setRecipientAccountNumber(formData.getRecipientAccountNumber());

        String savingsAccount = harness.getConfig("nib.savings.account.fon");

        harness.withNewIb()
                .openLoginPage()
                .then(newIbTasks.loginWithUsernamePasswordAndDefaultMobKey(clientCredentials.getUsername(), clientCredentials.getPassword()))
                .then(newIbTasks.setDomesticPaymentToOwnAccount(formData, savingsAccount))
                .clickContinue()
                .then(newIbTasks.checkSummaryPaymentToOwnAccountPageAndConfirm(formData, savingsAccount))
                .then(newIbTasks.setDomesticPaymentThirdStep(formData));

        double amount = harness.withUdebs()
                .accountMovements()
                .getAmountLastAccountMovement(180, formData.getFromAccountNumber(), savingsAccount, String.valueOf(generatedPayment));

        assertAmountsEqual(generatedPayment, amount);
        harness.log("Generated payment is:" + generatedPayment + " and amount in UDEBS is: " + amount);
    }
}
