package cz.moneta.test.dsl.newib.investments;

import cz.moneta.test.dsl.Harness;
import cz.moneta.test.dsl.newib.mainpage.DashboardPage;
import cz.moneta.test.dsl.newib.mainpage.InvestmentsPage;
import cz.moneta.test.dsl.util.DateUtils;
import cz.moneta.test.dsl.util.data.client.NewClientWithCurrentAccountInformation;
import cz.moneta.test.dsl.util.data.client.NonClient;
import cz.moneta.test.dsl.util.task.ib.IbLoginApiTasks;
import cz.moneta.test.harness.endpoints.ib.NewIbEndpoint;
import cz.moneta.test.harness.support.web.Lookup;
import org.openqa.selenium.WebElement;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.function.Function;

import static cz.moneta.test.dsl.newib.mainpage.InvestmentsPage.FUND_RISK_PROFILE_NUMBER;
import static cz.moneta.test.dsl.util.credentials.Keys.ufo.banka.banker;
import static cz.moneta.test.dsl.util.task.retail.loans.constants.DefaultLoansConstants.*;
import static cz.moneta.test.harness.support.auth.AuthSupport.getCredentials;

public class InvestmentsTasks {
    private final Harness harness;

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

    public NonClient createNonClient() {
        return harness.data().newNonClient()
                .withLastName("InvestNákup")
                .withIdCard(DEFAULT_ID_CARD)
                .withBirthNumber(harness.tasks().common().getRcMinMaxAge(20, 50))
                .withResidencyAddress(DEFAULT_CLIENT_ADDRESS)
                .withEmail(DEFAULT_EMAIL)
                .withFixPhoneNumberWork(DEFAULT_MOBILE_NUMBER)
                .withFixPhoneNumberHome(DEFAULT_MOBILE_NUMBER)
                .withMobileNumber(DEFAULT_MOBILE_NUMBER)
                .withNetMonthlyIncome(DEFAULT_INCOME)
                .withHomeIncome(DEFAULT_INCOME);
    }

    public NewClientWithCurrentAccountInformation prepareClientViaWSO() {
        NonClient nonClient = createNonClient();
        String ufoUserName = getCredentials(banker, harness).getUsername();
        NewClientWithCurrentAccountInformation info = harness.dataPrepare().createNewFoCustomerWithCurrentAccountAndIbViaWso2(nonClient, ufoUserName);
        harness.tasks().wso2().payments().pennyPayment(
                "1000000",
                DateUtils.convertRawDateForWso2(new Date()),
                info.getCurrentAccount(),
                "1152131012",
                "0300",
                "Marcel Vaněček",
                "Marcel Vaněček, dar"
        );
        info.setCredentials(new IbLoginApiTasks(harness).loginAndConfirmAuthWithSms(info.getCredentials().getUsername()));
        return info;
    }

    public void logClientInfo(NewClientWithCurrentAccountInformation info) {
        harness.log("Name: " + info.getClientData().firstName() + " " + info.getClientData().lastName());
        harness.log("BirthNumber: " + info.getClientData().birthNumber());
        harness.log("Cif: " + info.getCif());
        harness.log("IB username: " + info.getCredentials().getUsername());
        harness.log("IB password: " + info.getCredentials().getPassword());
    }

    public Function<DashboardPage, InvestmentsPurchaseVictory> establishFirstInvestmentE2E() {
        return page -> {
            InvestmentsPurchaseDialog id = page
                    .goToInvestments()
                    .clickInvestmentsCard()
                    .confirmDisclaimer()
                    .clickShortTermCategory()
                    .clickInvestment()
                    .clickGoInvestAndFillQuestionnaire()
                    .clickGoFill()
                    .fillQuestionnaire()
                    .clickShowFunds()
                    .waitForMenu()
                    .clickRandomInvestment()
                    .clickGoInvest();

            String isin = id.getIsin();

            InvestmentsPurchaseVictory iv = id
                    .fillIndividualAmount("111111")
                    .fillRegularAmount("11111")
                    .clickAgreement()
                    .clickSubmitAndGoToFrameworkAgreement()
                    .scrollDown()
                    .clickGoSigneDocument()
                    .fillMobileKey("12341234")
                    .clickSubmitMobileKey();

            harness.log("Successfully purchased fund: " + isin);

            return iv.waitForVictory();
        };
    }

    private void purchaseInvestmentByProfileNumber(InvestmentsPage page, String profileNumber, String individualAmount, String regularAmount) {
        InvestmentsPurchaseDialog id = page
                .waitForMenu()
                .uncoverEntireFundList()
                .clickInvestmentByProfile(profileNumber)
                .clickGoInvest()
                .fillIndividualAmount(individualAmount)
                .fillRegularAmount(regularAmount)
                .clickAgreement();

        String isin = id.getIsin();

        id.clickSubmit()
                .fillMobileKey("12341234")
                .clickSecondFactorSubmit()
                .backToFundList();
        harness.log("Successfully purchased fund: " + isin);

    }

    public Function<InvestmentsPage, InvestmentsPage> purchasedInvestmentFromEachRiskProfile(List<String> riskProfileNumbers, String individualAmount, String regularAmount) {
        return investmentsPage -> {
            riskProfileNumbers.forEach(pn -> this.purchaseInvestmentByProfileNumber(investmentsPage, pn, individualAmount, regularAmount));
            return investmentsPage;
        };
    }

    /**
     * Find elements where is fund risk profile number
     * then get text from each element and make a list of fund risk profile numbers
     * then get rid of duplicity
     */
    public List<String> getRiskProfileNumbers() {
        List<String> riskProfileNumbers = new ArrayList<>();
        NewIbEndpoint ep = harness.getEndpoint(NewIbEndpoint.class);
        ep.waitForElementsToLoad(5, FUND_RISK_PROFILE_NUMBER);
        List<WebElement> elementsWithProfileNumber = ep.findAndGetListOfElements(FUND_RISK_PROFILE_NUMBER, Lookup.XPATH);
        elementsWithProfileNumber.forEach(e -> riskProfileNumbers.add(e.getText()));
        return new ArrayList<>(new HashSet<>(riskProfileNumbers));
    }
}
