package cz.moneta.test.dsl.ufo.banka.tasks;

import cz.moneta.test.dsl.Harness;
import cz.moneta.test.dsl.ufo.banka.pages.loans.NEP002_S001_ApplicantPage;
import cz.moneta.test.dsl.ufo.banka.pages.loans.expres.OPN008_S001_ExpressSignaturePage;
import cz.moneta.test.dsl.ufo.banka.pages.loans.flexikredit.ONC001_S001_NewFlexikreditPageTransitions;
import cz.moneta.test.dsl.ufo.banka.pages.loans.flexikredit.NFL006_S001_FlexikreditScoringResultPage;
import cz.moneta.test.dsl.ufo.banka.pages.loans.flexikredit.ONC001_S001_NewFlexikreditPage;
import cz.moneta.test.dsl.ufo.banka.pages.main.HKO101_S001_MainClientPage;
import cz.moneta.test.dsl.ufo.banka.pages.requests.BAL006_S002_ClientRequestPageTransitions;
import cz.moneta.test.dsl.ufo.banka.pages.requests.PSI001_S050_PreContractualInformationPrintedPage;
import cz.moneta.test.dsl.ufo.banka.tasks.products.NewProductTasks;
import cz.moneta.test.dsl.util.DateUtils;
import cz.moneta.test.dsl.util.code.lists.HCisAllStavZadosti;
import cz.moneta.test.dsl.util.data.client.NonClient;

import java.util.function.Function;

import static cz.moneta.test.dsl.ufo.banka.pages.main.codelists.HCisProductClass.FLEXIKREDIT;

public class FlexiCreditTasks {

    private final Harness harness;
    private NewProductTasks productTasks;

    public FlexiCreditTasks(Harness harness) {
        this.harness = harness;
        this.productTasks = harness.tasks().ufo().banka().newProduct();
    }

    public Function<HKO101_S001_MainClientPage, HKO101_S001_MainClientPage> createNewFlexiCreditApplication(NonClient applicant, int loanAmount, HCisAllStavZadosti expectedAppStat) {
        return start -> start
                .then(createApplicationToApplicantPage(applicant, loanAmount))
                .clickContinue()
                .onPrintPage()
                .closePrintWindow()
                .onSignaturePage()
                .then(productTasks.finishLoanApplication())
                .onFlexikreditScoringResultPage()
                .then(waitForStatusAndLogData(expectedAppStat.getValue()))
                .clickEnd()
                .onMainClientPage();
    }

    public Function<HKO101_S001_MainClientPage, HKO101_S001_MainClientPage> createNewFlexiCreditApplicationFixedTerm(NonClient applicant, int loanAmount, HCisAllStavZadosti expectedAppStat) {
        return start -> start
                .then(createApplicationToApplicantPage(applicant, loanAmount))
                .fillEmploymentEndDate(DateUtils.getDateWithFormat(applicant.occupationEmploymentTillRaw(), "d.M.yyyy"))
                .clickContinue()
                .onSignaturePage()
                .then(productTasks.finishLoanApplication())
                .onFlexikreditScoringResultPage()
                .then(waitForStatusAndLogData(expectedAppStat.getValue()))
                .clickEnd()
                .onMainClientPage();
    }

    public Function<HKO101_S001_MainClientPage, HKO101_S001_MainClientPage> createNewFlexiCreditApplicationWithPrefilledData(int amount, HCisAllStavZadosti expectedAppStat) {
        return start -> start.createNewProduct(FLEXIKREDIT)
                .onFlexikreditPage()
                .then(fillFlexikreditPage(amount))
                .onApplicantPage()
                .clickContinue()
                .onSignaturePage()
                .then(productTasks.finishLoanApplication())
                .onFlexikreditScoringResultPage()
                .then(waitForStatusAndLogData(expectedAppStat.getValue()))
                .clickEnd()
                .onMainClientPage();
    }

    private Function<NFL006_S001_FlexikreditScoringResultPage, NFL006_S001_FlexikreditScoringResultPage> waitForStatusAndLogData(String expectedAppStat) {
        return start -> start.waitForStatusAndRefresh(expectedAppStat)
                .storeAppId()
                .storeAppKey()
                .storeAppStat();
    }

    private Function<ONC001_S001_NewFlexikreditPage, ONC001_S001_NewFlexikreditPageTransitions> fillFlexikreditPage(int amount) {
        return start -> start.fillAmount(amount)
                .clickNoPromoIfVisible()
                .clickSend();
    }

    public Function<HKO101_S001_MainClientPage, OPN008_S001_ExpressSignaturePage> createAccountsForNewFlexiCreditWithExistingBuAndIbUntilSignature(int amount, String secondBankerLastName) {//uses application created in the same test
        return createAccountsForNewFlexiCreditWithExistingBuAndIbUntilSignature(harness.get(NFL006_S001_FlexikreditScoringResultPage.APP_ID_STORE), amount, secondBankerLastName);
    }

    public Function<HKO101_S001_MainClientPage, OPN008_S001_ExpressSignaturePage> createAccountsForNewFlexiCreditWithExistingBuAndIbUntilSignature(String applicationId, int amount, String secondBankerLastName) {
        return start -> start.then(harness.tasks().ufo().banka().newProduct().showApplicationDetails(applicationId))
                .then(createAccountsWithExistingBUandIBUntilSignature(amount, secondBankerLastName));
    }

    public Function<HKO101_S001_MainClientPage, OPN008_S001_ExpressSignaturePage> createAccountsForNewFlexiCreditWithExistingBuAndIbUntilSignatureWithoutAmountSelect(String secondBankerLastName) {//uses application created in the same test
        return createAccountsForNewFlexiCreditWithExistingBuAndIbUntilSignatureWithoutAmountSelect(harness.get(NFL006_S001_FlexikreditScoringResultPage.APP_ID_STORE), secondBankerLastName);
    }

    public Function<HKO101_S001_MainClientPage, OPN008_S001_ExpressSignaturePage> createAccountsForNewFlexiCreditWithExistingBuAndIbUntilSignatureWithoutAmountSelect(String applicationId, String secondBankerLastName) {
        return start -> start.then(harness.tasks().ufo().banka().newProduct().showApplicationDetails(applicationId))
                .then(createAccountsUntilSignatureWithoutAmountSelect(secondBankerLastName));
    }

    private Function<BAL006_S002_ClientRequestPageTransitions, OPN008_S001_ExpressSignaturePage> createAccountsWithExistingBUandIBUntilSignature(int amount, String secondBankerLastName) {
        return start -> start
                .onFlexiCreditScoringResultPage()
                .clickFoundationPrintContractButton()
                .onSelectingApprovedVariantsPage()
                .clickToLoanAmountRadioButton()
                .typeIntoLoanAmount(String.valueOf(amount))
                .clickSelect()
                .then(finishAccountCreationUntilSignature(secondBankerLastName));
    }

    private Function<PSI001_S050_PreContractualInformationPrintedPage, OPN008_S001_ExpressSignaturePage> finishAccountCreationUntilSignature(String secondBankerLastName) {
        return start -> start
                .continueToPrintCopyOfContractProposalPage()
                .clickContinue()
                .onSecondBankerJoiningPage()
                .fillSurnameInput(secondBankerLastName)
                .clickSearch()
                .selectFirstName()
                .clickContinue()
                .onSignerSelectionPage()
                .clickContinue()
                .onSpecialConditionsPage()
                .clickContinueButton()
                .continueToContractDocumentationPage()
                .clickContinue()
                .onExpressSignaturePage()
                .clickApplicantCheckbox()
                .clickYesAndDismissAlert();
    }

    private Function<BAL006_S002_ClientRequestPageTransitions, OPN008_S001_ExpressSignaturePage> createAccountsUntilSignatureWithoutAmountSelect(String secondBankerLastName) {
        return start -> start
                .onFlexiCreditScoringResultPage()
                .clickFoundationPrintContractButton()
                .onPreContractualInformationPrintedPage()
                .then(finishAccountCreationUntilSignature(secondBankerLastName));
    }

    public Function<OPN008_S001_ExpressSignaturePage, HKO101_S001_MainClientPage> finishAccountCreation(HCisAllStavZadosti expectedAppStat) {
        return start -> start.clickCheck()
                .clickContinue()
                .waitForLoader()
                .onContractSignedPage()
                .clickContinueButton()
                .onFlexikreditScoringResultPage()
                .waitForStatusAndRefresh(expectedAppStat.getValue())
                .clickEnd()
                .onListOfRequestsPage()
                .clickBackToMainClientPage();
    }

    public Function<HKO101_S001_MainClientPage, HKO101_S001_MainClientPage> createDeclipApplication(int newLoanAmount) {
        return start -> start
                .clickActiveProduct("FLEXIKREDIT")
                .onFlexiCreditDetailPage()
                .clickDeclipButton()
                .fillLoanAmount(newLoanAmount)
                .clickSendButton()
                .clickEnd()
                .onFlexiCreditDetailPage()
                .clickBackButton();
    }

    private Function<HKO101_S001_MainClientPage, NEP002_S001_ApplicantPage> createApplicationToApplicantPage(NonClient applicant, int loanAmount) {
        return start -> start
                .createNewProduct(FLEXIKREDIT)
                .onFlexikreditPage()
                .then(fillFlexikreditPage(loanAmount))
                .onIdSelectionPage()
                .then(productTasks.selectIDs())
                .then(productTasks.fillApplicantPage(applicant, false));
    }

}
