package cz.moneta.test.regression.risk;

import cz.moneta.test.dsl.Harness;
import cz.moneta.test.dsl.ufo.banka.pages.loans.expres.NEP006_S001_ExpressScoringResultPage;
import cz.moneta.test.dsl.ufo.banka.pages.loans.flexikredit.NFL006_S001_FlexikreditScoringResultPage;
import cz.moneta.test.dsl.ufo.banka.pages.main.HKO101_S001_MainClientPage;
import cz.moneta.test.dsl.ufo.banka.tasks.BankaTasks;
import cz.moneta.test.dsl.ufo.operations.client.ClientEvaluationPage;
import cz.moneta.test.dsl.util.code.lists.HCisAllStavZadosti;
import cz.moneta.test.dsl.util.data.ClientUtils;
import cz.moneta.test.dsl.util.data.client.NonClient;
import cz.moneta.test.dsl.util.task.ufo.operations.OperationsTasks;
import cz.moneta.test.harness.annotations.NonConcurrentTestScenario;
import cz.moneta.test.harness.annotations.TestCase;
import cz.moneta.test.harness.support.auth.Credentials;
import cz.moneta.test.harness.support.auth.Key;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;

import static cz.moneta.test.dsl.util.credentials.Keys.ufo.banka.banker;

@NonConcurrentTestScenario
public class UfoOpsChecks {

    private final String SCORECARD_EXPRESS_WALKIN = "EXON01S1";
    private final String SCORECARD_EXPRESS_EXIST = "EXON01S2";
    private final String SCORECARD_FLEXICREDIT_WALKIN = "FXON01S1";
    private final String SCORECARD_FLEXICREDIT_EXIST = "FXON01S2";
    private final String SCORECARD_CREDIT_CARD_WALKIN = "CCON01S1";
    private final String SCORECARD_CREDIT_CARD_EXIST = "CCON01S2";

    //Risk internal values
    private float dstiCoefWalkin;
    private float dstiCoefCr1;
    private float dstiCoefCr3;

    //Risk internal values
    private int cutoffExpressLoan;
    private int cutoffFlexiCredit;
    private int cutoffCreditCard;
    private int cutoffExist;

    private int loanAmount = 30000;
    private int term = 60;
    private NonClient applicant;
    private BankaTasks bankaTasks;
    private OperationsTasks operationsTasks;
    private HKO101_S001_MainClientPage ufoPage;
    private String applicationId;
    private float dstiCoef;
    private String scorecardId;
    private int cutoffValue;
    private boolean useApplicationScore = true;

    @BeforeAll
    void setup(Harness harness) {
        bankaTasks = harness.tasks().ufo().banka();
        operationsTasks = harness.tasks().ufo().operations();
        readInternalValues(harness);
    }

    void readInternalValues(Harness harness) {
        dstiCoefWalkin = Float.parseFloat(harness.getSystemOrConfigValue("dstiCoefWalkin"));
        dstiCoefCr1 = Float.parseFloat(harness.getSystemOrConfigValue("dstiCoefCr1"));
        dstiCoefCr3 = Float.parseFloat(harness.getSystemOrConfigValue("dstiCoefCr3"));

        cutoffExpressLoan = Integer.parseInt(harness.getSystemOrConfigValue("cutoffExpressLoan"));
        cutoffFlexiCredit = Integer.parseInt(harness.getSystemOrConfigValue("cutoffFlexiCredit"));
        cutoffCreditCard = Integer.parseInt(harness.getSystemOrConfigValue("cutoffCreditCard"));
        cutoffExist = Integer.parseInt(harness.getSystemOrConfigValue("cutoffExist"));
    }

    @BeforeEach
    void createClient(Harness harness, @Key(banker) Credentials credentials) {
        applicant = ClientUtils.getRiskDefaultClient(harness);
        ufoPage =
                bankaTasks.newProduct().createClientWithIb(harness, credentials, applicant);
    }

    void setScorecardId(String scorecardId, Harness harness) {
        this.scorecardId = scorecardId;
        if (!scorecardId.endsWith("N01S1")) {
            useApplicationScore = false;
            setScorecard(harness);
        }
    }

    void setScorecard(Harness harness) {
        harness.withIlods().setScore(scorecardId, applicant.birthNumber(), null);
        try {
            Thread.sleep(60000);//must wait, otherwise UFO uses default scorecard
        } catch (InterruptedException e) {
        }
    }

    void setDstiCoef(Harness harness) {
/*        if (useApplicationScore) {//currently not used
            dstiCoef = dstiCoefWalkin;
            return;
        }
*/
        String grade = harness.get(ClientEvaluationPage.GRADE_STORE);
        switch (grade) {
            case "CR1":
            case "CR2":
                dstiCoef = dstiCoefCr1;
                break;
            case "CR3":
                dstiCoef = dstiCoefCr3;
                break;
            default:
                dstiCoef = dstiCoefWalkin;
                break;
        }
    }

    @TestCase(name = "New client with Express loan application, check score values in UFO OPS")
    public void newClientExpressLoan(Harness harness) {
        setScorecardId(SCORECARD_EXPRESS_WALKIN, harness);
        cutoffValue = cutoffExpressLoan;

        ufoPage = ufoPage
                .then(bankaTasks.expresTasks().createNewExpressApplication(applicant, loanAmount, term, HCisAllStavZadosti.NONE));

        applicationId = harness.get(NEP006_S001_ExpressScoringResultPage.APP_ID_STORE);
    }

    @TestCase(name = "Existing with Express loan application, check score values in UFO OPS")
    public void existingClientExpressLoan(Harness harness) {
        setScorecardId(SCORECARD_EXPRESS_EXIST, harness);
        cutoffValue = cutoffExist;

        ufoPage = ufoPage
                .then(bankaTasks.expresTasks().createNewExpressApplication(applicant, loanAmount, term, HCisAllStavZadosti.NONE));

        applicationId = harness.get(NEP006_S001_ExpressScoringResultPage.APP_ID_STORE);
    }

    @TestCase(name = "New client with FlexiCredit application, check score values in UFO OPS")
    public void newClientFlexiCredit(Harness harness) {
        setScorecardId(SCORECARD_FLEXICREDIT_WALKIN, harness);
        cutoffValue = cutoffFlexiCredit;

        ufoPage = ufoPage
                .then(bankaTasks.flexiCreditTasks().createNewFlexiCreditApplication(applicant, loanAmount, HCisAllStavZadosti.NONE));

        applicationId = harness.get(NFL006_S001_FlexikreditScoringResultPage.APP_ID_STORE);
    }

    @TestCase(name = "Existing client with FlexiCredit application, check score values in UFO OPS")
    public void existingClientFlexiCredit(Harness harness) {
        setScorecardId(SCORECARD_FLEXICREDIT_EXIST, harness);
        cutoffValue = cutoffExist;

        ufoPage = ufoPage
                .then(bankaTasks.flexiCreditTasks().createNewFlexiCreditApplication(applicant, loanAmount, HCisAllStavZadosti.NONE));

        applicationId = harness.get(NFL006_S001_FlexikreditScoringResultPage.APP_ID_STORE);
    }

    @TestCase(name = "New client with Credit Card application, check score values in UFO OPS")
    public void newClientCreditCard(Harness harness) {
        setScorecardId(SCORECARD_CREDIT_CARD_WALKIN, harness);
        cutoffValue = cutoffCreditCard;

        ufoPage = ufoPage
                .then(bankaTasks.cardsOnboarding().creditCards().createNewCreditCardApplication(applicant, loanAmount));

        applicationId = harness.get(NFL006_S001_FlexikreditScoringResultPage.APP_ID_STORE);
    }

    @TestCase(name = "Existing client with Credit Card application, check score values in UFO OPS")
    public void existingClientCreditCard(Harness harness) {
        setScorecardId(SCORECARD_CREDIT_CARD_EXIST, harness);
        cutoffValue = cutoffExist;

        ufoPage = ufoPage
                .then(bankaTasks.cardsOnboarding().creditCards().createNewCreditCardApplication(applicant, loanAmount));

        applicationId = harness.get(NFL006_S001_FlexikreditScoringResultPage.APP_ID_STORE);
    }

    @AfterEach
    void checkValuesInOps(Harness harness) {
        ClientEvaluationPage opsPage =
                ufoPage
                        .clickSearch()
                        .clickLoginMenu()
                        .selectFirstOmIfPresent()
                        .selectUfoOperationsAndContinueWithoutOmSelect()
                        .clickSearchApRisk()
                        .then(operationsTasks.searchClient().byAP(applicationId))
                        .clickClientEvaluationLink()
                        .logClientGrade(useApplicationScore);

        setDstiCoef(harness);

        opsPage
                .checkDstiValues(dstiCoef)
                .checkScorecardValues(useApplicationScore, scorecardId, cutoffValue);
    }
}