package cz.moneta.test.dsl.util.task.ufo.cb;

import cz.moneta.test.dsl.Harness;
import cz.moneta.test.dsl.ufo.banka.pages.main.codelists.HCisAllObrazovkySME;
import cz.moneta.test.dsl.ufo.banka.tasks.BankaTasks;
import cz.moneta.test.dsl.ufo.cb.landing.AUT402_S001_KOCriteriaListPage;
import cz.moneta.test.dsl.ufo.cb.landing.IKL402_S001_ClientPage;
import cz.moneta.test.dsl.ufo.cb.landing.SME451_S001_UfoCbLandingPage;
import cz.moneta.test.dsl.ufo.cb.landing.proposal.pages.*;
import cz.moneta.test.dsl.ufo.common.authentication.UfoLoginPage;
import cz.moneta.test.dsl.util.DateUtils;
import cz.moneta.test.dsl.util.TestUtils;
import cz.moneta.test.dsl.util.credentials.Keys;
import cz.moneta.test.dsl.util.data.client.NewClientCommercial;
import cz.moneta.test.dsl.util.data.client.NonClient;
import cz.moneta.test.dsl.util.task.wso2.ClientTasks;
import cz.moneta.test.dsl.util.task.wso2.ComodaTasks;
import cz.moneta.test.harness.endpoints.testautomationdb.TestAutomationDbEndpoint;
import cz.moneta.test.harness.endpoints.ufo.UfoEndpoint;
import cz.moneta.test.harness.support.auth.AuthSupport;
import cz.moneta.test.harness.support.auth.Credentials;
import cz.moneta.test.harness.support.web.Lookup;

import java.util.function.Function;

import static cz.moneta.test.dsl.ufo.cb.landing.AUT402_S001_KOCriteriaListPage.KO_CRITERIA_CALCULATION_TIME_KEY;
import static cz.moneta.test.dsl.ufo.cb.landing.IKL402_S001_ClientPage.INVOLVEMENT_CALCULATION_TIME_KEY;
import static cz.moneta.test.dsl.ufo.cb.landing.proposal.pages.JAN436_S001_AlertPage.PAGE_DIV;
import static cz.moneta.test.harness.support.data.GeneratorType.ICO;
import static cz.moneta.test.harness.support.data.GeneratorType.RC;

public class CommercialTasks {

    private final Harness harness;
    public static final String JIRA_COMMENT_STORE_KEY = "reports.tmfj.execution.comment";

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

    public NonClient createNewGlobalFopFe() {
        return harness.getGlobal("GLOBAL_FOP_FE", () -> {
            Credentials credentials = AuthSupport.getCredentials(Keys.ufo.banka.banker, harness);

            BankaTasks withBanka = harness.tasks().ufo().banka();

            String birthNumber = harness.generate(RC);

            NonClient fop = harness.data().newNonClient()
                    .withBirthNumber(birthNumber)
                    .withEmail(TestUtils.getEmailBasedOnRc(birthNumber));

            harness.withUfo()
                    .openLoginPage()
                    .then(withBanka.login().withCredentialsAndTurnOffSignpad(credentials))
                    .then(withBanka.newFopClient().createFopCif(fop))
                    .verifyThatCifIsValid();

            return fop;
        });
    }

    public void appendJiraComment(String anotherComment) {
        String currentComments = harness.get(JIRA_COMMENT_STORE_KEY);
        String updatedComment = currentComments + anotherComment + "<br>";
        harness.store(JIRA_COMMENT_STORE_KEY, updatedComment);
    }

    public NewClientCommercial createNewGlobalFopBe() {
        return harness.getGlobal("GLOBAL_FOP_BE", this::createNewFop);
    }

    public NewClientCommercial createNewFop() {
        ClientTasks tasks = harness.tasks().wso2().client();
        Credentials credentials = AuthSupport.getCredentials(Keys.ufo.banka.banker, harness);
        String createdDateTime = DateUtils.getFormattedTodayDateTime("yyyy-MM-dd hh:mm:ss");

        String birthNumber = harness.generate(RC);
        String ico = harness.generate(ICO);

        NonClient fop = harness.data().newNonClient()
                .withBirthNumber(birthNumber)
                .withEmail(TestUtils.getEmailBasedOnRc(birthNumber))
                .withIco(ico);

        String cifFo = tasks.createCifFo(fop);
        harness.getEndpoint(TestAutomationDbEndpoint.class)
                .insertCreatedClientInfo(cifFo, fop.birthNumber(), null, createdDateTime, credentials.getUsername(), "MWF", null);

        String cifFop = tasks.createCifFop(fop, credentials.getUsername());
        harness.getEndpoint(TestAutomationDbEndpoint.class)
                .insertCreatedClientInfo(cifFop, fop.birthNumber(), fop.ico(), createdDateTime, credentials.getUsername(), "MWF", null);

        tasks.relationFoFop(cifFo, cifFop);
        Long personId = harness.tasks().wso2().comoda().createAndGetClientId(fop.ico());
        NewClientCommercial newClientCommercial = new NewClientCommercial(fop, cifFop, personId);
        harness.log("Created FO cif: " + cifFo);
        harness.log("Created FOP cif: " + cifFop);
        harness.log("Created FOP ico: " + ico);
        harness.log("Created FOP ID OSOBY: " + personId.toString());
        return newClientCommercial;
    }

    public void linkNewFopClientToSalesForce(NewClientCommercial newClientCommercial) {
        harness.withUfo()
                .openLoginPage()
                .then(loginAsCbSalesSupport())
                .clickCreateToSalesForceLink()
                .selectClientType("FOP")
                .fillIco(newClientCommercial.getClientData().ico())
                .fillSubjectName(newClientCommercial.getClientData().fullName())
                .fillStreetName(newClientCommercial.getClientData().residencyAddress().getStreet())
                .fillStreetNumber(newClientCommercial.getClientData().residencyAddress().getOrientationNumber())
                .fillCityName(newClientCommercial.getClientData().residencyAddress().getCity())
                .fillDistrict(newClientCommercial.getClientData().residencyAddress().getCity())
                .fillCityPart(newClientCommercial.getClientData().residencyAddress().getCityPart())
                .fillZipCode(newClientCommercial.getClientData().residencyAddress().getZip())
                .fillRegion(newClientCommercial.getClientData().residencyAddress().getCity())
                .clickCreate()
                .clickContinue();
    }

    public void editPages(Long idNavrh, HCisAllObrazovkySME[] pages, String state) {
        ComodaTasks comodaTasks = harness.tasks().wso2().comoda();
        for (HCisAllObrazovkySME page : pages) {
            comodaTasks.editPage(idNavrh, page, state);
        }
    }

    private Function<UfoLoginPage, SME451_S001_UfoCbLandingPage> withCbCredentials(Credentials credentials) {
        return start -> start.typeUserNameAndPasswordAndClickLogin(credentials.getUsername(), credentials.getPassword())
                .onUfoCbPage();
    }

    private Function<UfoLoginPage, SME451_S001_UfoCbLandingPage> withCbCredentialsAndSelectFirstOM(Credentials credentials) {
        return start -> start.typeUserNameAndPasswordAndClickLogin(credentials.getUsername(), credentials.getPassword())
                .onApplicationSelectPage()
                .selectFirstOmIfPresent()
                .selectUfoCommercialBankingAndContinue();
    }

    public Function<UfoLoginPage, SME451_S001_UfoCbLandingPage> loginAsCbBanker() {
        Credentials credentials = AuthSupport.getCredentials(Keys.ufo.cb.bankerFiremniKlientela, harness);
        return this.withCbCredentials(credentials);
    }

    public Function<UfoLoginPage, SME451_S001_UfoCbLandingPage> loginAsCbSalesSupport() {
        Credentials credentials = AuthSupport.getCredentials(Keys.ufo.cb.salesSupport, harness);
        return this.withCbCredentialsAndSelectFirstOM(credentials);
    }

    public Function<UfoLoginPage, SME451_S001_UfoCbLandingPage> loginAsCbBankerAndSelectFirstOM() {
        Credentials credentials = AuthSupport.getCredentials(Keys.ufo.cb.bankerFiremniKlientela, harness);
        return this.withCbCredentialsAndSelectFirstOM(credentials);
    }

    public Function<UfoLoginPage, SME451_S001_UfoCbLandingPage> loginAsCbContractualDocumentAdministratorAndSelectFirstOM() {
        Credentials credentials = AuthSupport.getCredentials(Keys.ufo.cb.ctenar, harness);
        return this.withCbCredentialsAndSelectFirstOM(credentials);
    }

    public Function<UfoLoginPage, SME451_S001_UfoCbLandingPage> loginAsCbContractualDocumentAdministrator() {
        Credentials credentials = AuthSupport.getCredentials(Keys.ufo.cb.ctenar, harness);
        return this.withCbCredentials(credentials);
    }

    public Function<UfoLoginPage, SME451_S001_UfoCbLandingPage> loginAsCbReader() {
        Credentials credentials = AuthSupport.getCredentials(Keys.ufo.cb.ctenar, harness);
        return this.withCbCredentials(credentials);
    }

    public Function<SME451_S001_UfoCbLandingPage, IKL402_S001_ClientPage> searchClient(String ico) {
        return start -> start.clickSearchLink().pickIco().typeDetailForSearch(ico).clickSearch();
    }

    public ProposalTasks proposalTasks() {
        return new ProposalTasks();
    }

    public Function<IKL402_S001_ClientPage, IKL402_S001_ClientPage> checkFirstInvolvementCalculation() {
        return start -> start
                .calculateInvolvement()
                .waitForCalculation()
                .checkCalculatedTimeNotEmpty();
    }

    public Function<IKL402_S001_ClientPage, IKL402_S001_ClientPage> checkNotFirstInvolvementCalculation() {
        return start -> start
                .storeLastInvolvementCalculationTime()
                .calculateInvolvement()
                .waitForCalculation()
                .checkChangeOfCalculatedTime(harness.get(INVOLVEMENT_CALCULATION_TIME_KEY));
    }

    /**
     * Data inconsistency means that we do not know, if involvement was historically already calculated or not.
     *
     * @return
     */
    public Function<IKL402_S001_ClientPage, IKL402_S001_ClientPage> checkInvolvementCalculation() {
        UfoEndpoint endpoint = harness.getEndpoint(UfoEndpoint.class);
        String text = endpoint.getText(IKL402_S001_ClientPage.CALCULATION_TIME_DIV, Lookup.ID);
        if (text.isEmpty()) {
            return start -> start
                    .then(checkFirstInvolvementCalculation());
        } else {
            return start -> start
                    .then(checkNotFirstInvolvementCalculation());
        }
    }

    public Function<AUT402_S001_KOCriteriaListPage, AUT402_S001_KOCriteriaListPage> checkFirstKOCriteriaCalculation() {
        return start -> start
                .clickRunKOCalculation()
                .checkCalculatedTimeNotEmpty()
                .checkFirstKOCriteriumIsPresent();
    }

    public Function<AUT402_S001_KOCriteriaListPage, AUT402_S001_KOCriteriaListPage> checkNotFirstKOCriteriaCalculation() {
        return start -> start
                .logSecondWindowSessionId()
                .storeLastKOCriteriaCalculationTime()
                .clickRunKOCalculation()
                .checkChangeOfCalculatedTime(harness.get(KO_CRITERIA_CALCULATION_TIME_KEY))
                .checkFirstKOCriteriumIsPresent();
    }

    /**
     * Data inconsistency means that we do not know, if KO Criteria were historically already calculated or not.
     *
     * @return
     */
    public Function<AUT402_S001_KOCriteriaListPage, AUT402_S001_KOCriteriaListPage> checkKOCriteriaCalculation() {
        UfoEndpoint endpoint = harness.getEndpoint(UfoEndpoint.class);
        String text = endpoint.getText(AUT402_S001_KOCriteriaListPage.CALCULATION_TIME_DIV, Lookup.ID);

        if (text.isEmpty()) {
            return start -> start
                    .then(checkFirstKOCriteriaCalculation());
        } else {
            return start -> start
                    .then(checkNotFirstKOCriteriaCalculation());
        }
    }

    public Function<JAN459_S001_CreateFinancialSheetPageTransitions, JAN475_S001_FinancialSheetsPage> skipAlertPageIfPresent(Harness harness) {
        UfoEndpoint endpoint = harness.getEndpoint(UfoEndpoint.class);
        if (endpoint.isElementVisible(3, PAGE_DIV, Lookup.ID)) {
            return start -> start
                    .onAlertPage()
                    .clickContinue();
        } else {
            return start -> start
                    .onFinancialSheets();
        }
    }

    public Function<IKL402_S001_ClientPage, IKL402_S001_ClientPage> checkDetailClientInfo() {
        return start -> start
                .clickDetailedClientInfo()
                .checkOMIsNotEmpty()
                .checkClientsBankerIsNotEmpty()
                .checkAdministratorIsNotEmpty()
                .clickCloseDetailedClientInfo();
    }

    public Function<JAN451_S001_FinancialSheetsSignPost, JAN452_S001_IndividualFinancialSheetsPage> createFinancialSheet() {
        return start -> start
                .clickIndividualFinancialSheets()
                .clickOlderVersions()
                .clickFilter()
                .storeFinancialSheetsCountOlderVersionsIncluded()
                .then(constructFinancialSheet())
                .checkFinancialSheetCreatedSuccessfully();
    }

    public Function<JAN452_S001_IndividualFinancialSheetsPage, JAN452_S001_IndividualFinancialSheetsPage> constructFinancialSheet() {
        return start -> start
                .clickCreateFinancialSheet()
                .then(fillFinancialSheetMandatoryInformation())
                .clickFillSheet()
                .clickExisitingFinancialSheetContinueIfVisible()
                .then(skipAlertPageIfPresent(harness))
                .then(doNeccessaryCountingsForEstablishingFinancialSheet())
                .clickAnalysis()
                .clickWait();
    }

    public Function<JAN475_S001_FinancialSheetsPage, JAN475_S001_FinancialSheetsPage> doNeccessaryCountingsForEstablishingFinancialSheet() {
        return start -> start
                .clickAssetsDoCount()
                .clickAssetsNext()
                .clickRunningAssetsDoCount()
                .clickRunningAssetsNext()
                .clickPassivesDoCount()
                .clickPassivesNext()
                .clickShortTermCommitmentsDoCount()
                .clickShortTermCommitmentsNext()
                .clickIncomeStatementDoCount()
                .clickIncomeStatementNext()
                .clickIncomeStatement2DoCount();
    }

    private Function<JAN459_S001_CreateFinancialSheetPage, JAN459_S001_CreateFinancialSheetPage> fillFinancialSheetMandatoryInformation() {
        return start -> start
                .fillClientIfEmpty()
                .fillICOIfEmpty()
                .fillEstablishmentDateIfEmpty("1.1.2016")
                .fillCzNacePercentage("100")
                .selectMarketShareIfEmpty("<5%")
                .clickAccountingPUDoubly()
                .selectUnits("Jednotky")
                .selectCurrency("CZK")
                .clickNotSeasonal()
                .fillSheetsToDate("31.12.2023")
                .selectSheetType("Auditované")
                .fillMonthsInWatchedPeriodCount("12")
                .fillAuditor("Auditor")
                .fillCertificateNuber("12345644")
                .selectAuditorsStatement("Bez výhrad")
                .selectSheetImage("Od 2016")
                .selectSheetForm("Plná")
                .selectCzNace1IfEmpty("010000");
    }

    public Function<VST403_S001_Relations, KOM419_S001_SendProposal> checkLoadOfScreens() {
        return start -> start
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage()
                .clickNextPage();
    }

}