package cz.moneta.test.regression.channels.digital.ml.hypos;

import cz.moneta.test.dsl.Harness;
import cz.moneta.test.dsl.hypos.enums.*;
import cz.moneta.test.dsl.hypos.pages.hypokalkulacka.HypokalkulackaPage;
import cz.moneta.test.dsl.hypos.tasks.HyposDbTasks;
import cz.moneta.test.dsl.hypos.tasks.HyposTasks;
import cz.moneta.test.dsl.util.DateUtils;
import cz.moneta.test.dsl.util.TestUtils;
import cz.moneta.test.dsl.util.data.client.*;
import cz.moneta.test.dsl.util.data.hypos.*;
import cz.moneta.test.harness.annotations.Environment;
import cz.moneta.test.harness.annotations.JiraTestCase;
import cz.moneta.test.harness.annotations.NonConcurrentTestScenario;
import cz.moneta.test.harness.annotations.TestCase;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;

import java.util.ArrayList;
import java.util.List;

import static cz.moneta.test.dsl.hypos.enums.Client.*;
import static cz.moneta.test.dsl.hypos.pages.contract.approval.ApVerificationPage.TASK_IDS;
import static cz.moneta.test.dsl.hypos.pages.contract.approval.ScoringPage.AP_ID;
import static cz.moneta.test.dsl.hypos.pages.hypokalkulacka.HypokalkulackaPage.HYPOKALKULACKA_ID;

@NonConcurrentTestScenario(name = "Scoring test scenario")
public class RiskTest {
    List<ScoringParameter> scoringParameters;
    private HyposContract hyposContract;
    private HyposTasks tasks;
    private String hypokalkulackaId, contractId;

    @BeforeAll
    public void setup(Harness harness) {
        tasks = harness.tasks().hypos();

        //CLIENT 1
        String birthNumber1 = "9703067132";

        Address permanentAddress1 = Address.builder()
                .street("Pražská")
                .descriptiveNumber("121")
                .orientationNumber("")
                .city("Kolín")
                .zip("28002")
                .country("CZ")
                .build();

        NonClient nonClient1 = harness.data().newNonClient()
                .withBirthNumber(birthNumber1)
                .withFirstName("Matěj")
                .withLastName("Havlík")
                .withEmail(TestUtils.getEmailBasedOnRc(birthNumber1))
                .withPlaceOfBirth("Praha")
                .withNationality(ClientNationality.CZ.getValue())
                .withMaritalStatus(MaritalStatus.SINGLE)
                .withEducationLevel(EducationLevel.HIGHER)
                .withGrossIncome(190000)
                .withNetMonthlyIncome(140000)
                .withEmployer(Employer.builder().ico("00007064").build())
                .withOccupationStatus(OccupationStatus.FULL_TIME_EMPLOYEE)
                .withOccupationEmploymentFromRaw(DateUtils.getSpecificDayRaw(1, 1, 2000))
                .withOccupationType(OccupationType.IT_GUYS)
                .withAccommodationType(AccommodationType.PARENTS)
                .withResidencyAddress(permanentAddress1);

        BusinessIncome businessIncome1 = BusinessIncome.builder()
                .turnoverLatest(800000)
                .taxBaseLatest(600000)
                .paidTax(200000)
                .costAccounting("Daňová evidence")
                .naceCode("64921")
                .turnoverPenultimate(850000)
                .taxBasePenultimate(650000)
                .ico("25672720")
                .startDate("1.12.2000")
                .currency(IncomeCurrency.CZK.getValue())
                .build();

        List<OtherIncome> otherIncome1 = new ArrayList<OtherIncome>() {{
            add(OtherIncome.builder().type(OtherIncomeType.ALIMENT.getValue()).amount("800").currency(IncomeCurrency.CZK.getValue()).build());
            add(OtherIncome.builder().type(OtherIncomeType.PARENTAL_CONTRIBUTION.getValue()).amount("1200").currency(IncomeCurrency.CZK.getValue()).build());
            add(OtherIncome.builder().type(OtherIncomeType.OTHER.getValue()).amount("900").currency(IncomeCurrency.CZK.getValue()).build());
        }};

        List<Expenditure> expenditures1 = new ArrayList<Expenditure>(){{
            add(Expenditure.builder()
                    .type(ExpenditureType.OTHER_CLIENT.getValue())
                    .amount("1000")
                    .correction(CorrectionType.NO_CORRECTION.getValue())
                    .build());
        }};

        HyposClient hyposClient1 = HyposClient.builder()
                .nonClient(nonClient1)
                .businessIncome(businessIncome1)
                .otherIncomes(otherIncome1)
                .stayType(StayType.PERMANENT_WITH_PIN.getValue())
                .livingType(LivingType.WITH_PARENTS.getValue())
                .expenditures(expenditures1)
                .household("1")
                .build();

        //CLIENT 2
        String birthNumber2 = "9703068738";

        Address permanentAddress2 = Address.builder()
                .street("Vyskočilova")
                .descriptiveNumber("1442")
                .orientationNumber("1b")
                .city("Praha")
                .zip("14000")
                .country("CZ")
                .build();

        NonClient nonClient2 = harness.data().newNonClient()
                .withBirthNumber(birthNumber2)
                .withFirstName("Karel")
                .withLastName("Havlík")
                .withEmail(TestUtils.getEmailBasedOnRc(birthNumber2))
                .withPlaceOfBirth("Praha")
                .withNationality(ClientNationality.CZ.getValue())
                .withMaritalStatus(MaritalStatus.SINGLE)
                .withEducationLevel(EducationLevel.HIGHER)
                .withGrossIncome(150000)
                .withNetMonthlyIncome(110000)
                .withEmployer(Employer.builder().ico("00007064").build())
                .withOccupationStatus(OccupationStatus.FULL_TIME_EMPLOYEE)
                .withOccupationEmploymentFromRaw(DateUtils.getSpecificDayRaw(1, 1, 2000))
                .withOccupationType(OccupationType.IT_GUYS)
                .withAccommodationType(AccommodationType.PARENTS)
                .withResidencyAddress(permanentAddress2);

        List<OtherIncome> otherIncome2 = new ArrayList<OtherIncome>() {{
            add(OtherIncome.builder().type(OtherIncomeType.ALIMENT.getValue()).amount("800").currency(IncomeCurrency.CZK.getValue()).build());
            add(OtherIncome.builder().type(OtherIncomeType.PARENTAL_CONTRIBUTION.getValue()).amount("1200").currency(IncomeCurrency.CZK.getValue()).build());
            add(OtherIncome.builder().type(OtherIncomeType.OTHER.getValue()).amount("900").currency(IncomeCurrency.CZK.getValue()).build());
        }};

        List<Expenditure> expenditures2 = new ArrayList<Expenditure>(){{
            add(Expenditure.builder()
                    .type(ExpenditureType.OTHER_CLIENT.getValue())
                    .amount("1000")
                    .correction(CorrectionType.NO_CORRECTION.getValue())
                    .build());
        }};

        HyposClient hyposClient2 = HyposClient.builder()
                .nonClient(nonClient2)
                .otherIncomes(otherIncome2)
                .stayType(StayType.PERMANENT_WITH_PIN.getValue())
                .clientRelation(ClientRelationType.PARTNER.getValue())
                .livingType(LivingType.WITH_PARENTS.getValue())
                .expenditures(expenditures2)
                .household("1")
                .build();

        //CLIENT 3
        String birthNumber3 = "9703067693";

        Address permanentAddress3 = Address.builder()
                .street("Vyskočilova")
                .descriptiveNumber("1442")
                .orientationNumber("1b")
                .city("Praha")
                .zip("14000")
                .country("CZ")
                .build();

        NonClient nonClient3 = harness.data().newNonClient()
                .withBirthNumber(birthNumber3)
                .withFirstName("Jan")
                .withLastName("Novák")
                .withEmail(TestUtils.getEmailBasedOnRc(birthNumber3))
                .withPlaceOfBirth("Praha")
                .withNationality(ClientNationality.CZ.getValue())
                .withMaritalStatus(MaritalStatus.SINGLE)
                .withEducationLevel(EducationLevel.HIGHER)
                .withGrossIncome(100000)
                .withNetMonthlyIncome(80000)
                .withEmployer(Employer.builder().ico("00007064").build())
                .withOccupationStatus(OccupationStatus.FULL_TIME_EMPLOYEE)
                .withOccupationEmploymentFromRaw(DateUtils.getSpecificDayRaw(1, 1, 2000))
                .withOccupationType(OccupationType.IT_GUYS)
                .withAccommodationType(AccommodationType.PARENTS)
                .withResidencyAddress(permanentAddress3);

        List<OtherIncome> otherIncome3 = new ArrayList<OtherIncome>() {{
            add(OtherIncome.builder().type(OtherIncomeType.ALIMENT.getValue()).amount("800").currency(IncomeCurrency.CZK.getValue()).build());
            add(OtherIncome.builder().type(OtherIncomeType.PARENTAL_CONTRIBUTION.getValue()).amount("1200").currency(IncomeCurrency.CZK.getValue()).build());
        }};


        List<Expenditure> expenditures3 = new ArrayList<Expenditure>(){{
            add(Expenditure.builder()
                    .type(ExpenditureType.OTHER_CLIENT.getValue())
                    .amount("1000")
                    .correction(CorrectionType.NO_CORRECTION.getValue())
                    .build());
        }};

        HyposClient hyposClient3 = HyposClient.builder()
                .nonClient(nonClient3)
                .otherIncomes(otherIncome3)
                .stayType(StayType.PERMANENT_WITH_PIN.getValue())
                .clientRelation(ClientRelationType.CHILD.getValue())
                .livingType(LivingType.WITH_PARENTS.getValue())
                .expenditures(expenditures3)
                .household("2")
                .build();

        //HYPOS CONTRACT
        List<HyposClient> hyposClients = new ArrayList<HyposClient>() {{
            add(hyposClient1);
            add(hyposClient2);
            add(hyposClient3);
        }};

        Realty realty = Realty.builder()
                .searchByRealtyType(RealtySearchType.FLAT.getValue())
                .registerArea("Brno")
                .autosuggestionText("Město Brno")
                .descriptiveNumber("1234")
                .flatNumber("1")
                .realtyPrice(3000000)
                .realtyPriceCurrent(3500000)
                .realtyType(RealtyType.FLAT.getValue())
                .pledgeType(PledgeType.PROPERTY_HOUSING.getValue())
                .contractRelation(ContractRelation.PLEDGE_WITH_CURRENT_REALTY.getValue())
                .collateralType(CollateralType.FLAT.getValue())
                .appraiserCompany(AppraiserCompany.MONETA_SUPERVISION.getValue())
                .build();

        List<LoanPurpose> loanPurposes = new ArrayList<LoanPurpose>() {{
            add(LoanPurpose.builder().type(LoanPurposeType.BUY.getValue()).amount("1000000").tranche("1").paymentType(PaymentType.GROUP_PURPOSE_BUY.getValue()).build());
        }};

        List<DrawingCondition> drawingConditions = new ArrayList<DrawingCondition>() {{
            add(DrawingCondition.builder().condition("ZS 01 A) návrh na vklad VP").tranches(new ArrayList<String>() {{
                add("1");
            }}).build());
            add(DrawingCondition.builder().condition("01 c) Uzavření zástavní smlouvy a podání návrhu na vklad").tranches(new ArrayList<String>() {{
                add("1");
            }}).build());
        }};

        hyposContract = HyposContract.builder()
                .clients(hyposClients)
                .realty(realty)
                .mortgageLoanAmount(1000000)
                .mortgageOwnResources(0)
                .mortgageOtherResources(0)
                .loanObjectType(LoanObjectType.FLAT.getValue())
                .purchaseReason(PurchaseReason.OWN_HOUSING.getValue())
                .firstHouseholdIncome(HouseholdIncome.builder().withIncome(2).withoutIncome(0).build())
                .secondHouseholdIncome(HouseholdIncome.builder().withIncome(1).withoutIncome(0).build())
                .loanPurposes(loanPurposes)
                .drawingConditions(drawingConditions)
                .build();

        //SCORING PARAMETERS
        scoringParameters = new ArrayList<ScoringParameter>() {{
            add(ScoringParameter.builder().type(ScoringParameterType.LIMIT).name("FIN_AMT_AUT").expectedValue("-1214167.4").build());
            add(ScoringParameter.builder().type(ScoringParameterType.LIMIT).name("FIN_AMT_MAN").expectedValue("4845098.38").build());
            add(ScoringParameter.builder().type(ScoringParameterType.LIMIT).name("FINA_MAX_MAN").expectedValue("4845098.38").build());
            add(ScoringParameter.builder().type(ScoringParameterType.LIMIT).name("FINA_MAX_AUT").expectedValue("160000").build());
            add(ScoringParameter.builder().type(ScoringParameterType.APPROVAL_RESULT).expectedValue("Schválení").build());
            add(ScoringParameter.builder().type(ScoringParameterType.BONITY).name("ČNB DTI").automat(ScoringApprovalResultType.AUTOMAT).expectedValue("0,00").build());
            add(ScoringParameter.builder().type(ScoringParameterType.BONITY).name("ČNB DSTI").automat(ScoringApprovalResultType.AUTOMAT).expectedValue("30 526,99").build());
            add(ScoringParameter.builder().type(ScoringParameterType.BONITY).name("ČNB DSTI").automat(ScoringApprovalResultType.MANUAL).expectedValue("51 268,00").build());
            add(ScoringParameter.builder().type(ScoringParameterType.BONITY_LTV).name("LTV pro Automat").expectedValue("33,33").build());
            add(ScoringParameter.builder().type(ScoringParameterType.BONITY_LTV).name("LTV pro Manual").expectedValue("50,00").build());
            add(ScoringParameter.builder().type(ScoringParameterType.REFUSAL_REASON).name("R221").build());
            add(ScoringParameter.builder().type(ScoringParameterType.REFUSAL_REASON).name("R111").build());
            add(ScoringParameter.builder().type(ScoringParameterType.REFUSAL_REASON).name("R999").build());
            add(ScoringParameter.builder().type(ScoringParameterType.STRATEGY).name("MainApplicant").expectedValue("1").build());
        }};
    }

    @Disabled("Missing data")
    @TestCase(name = "Scoring with AP verification", environments = {Environment.TST1})
    @JiraTestCase(id = "ML-T513")
    public void tcScoringWithApVerification(Harness harness) {
        HypokalkulackaPage hypokalkulackaPage = harness.withHypos()
                .openLoginPage()
                .then(tasks.loginToHyposWithProfile(HyposProfile.EMERGENCY))
                .switchToHypokalkulacka()


                .then(tasks.hypokalkulackaTasks().addClientData(hyposContract, FIRST_CLIENT.getValue()))
                .then(tasks.hypokalkulackaTasks().addClientAddress(hyposContract, FIRST_CLIENT.getValue()))
                .then(tasks.hypokalkulackaTasks().addClientIncomeBusiness(hyposContract, FIRST_CLIENT.getValue()))
                .then(tasks.hypokalkulackaTasks().addClientIncomeOther(hyposContract, FIRST_CLIENT.getValue()))
                .then(tasks.hypokalkulackaTasks().addClientExpenditure(hyposContract, FIRST_CLIENT.getValue()))

                .then(tasks.hypokalkulackaTasks().addClientData(hyposContract, SECOND_CLIENT.getValue()))
                .then(tasks.hypokalkulackaTasks().addClientAddress(hyposContract, SECOND_CLIENT.getValue()))
                .then(tasks.hypokalkulackaTasks().addClientIncomeEmployee(hyposContract, SECOND_CLIENT.getValue()))
                .then(tasks.hypokalkulackaTasks().addClientIncomeOther(hyposContract, SECOND_CLIENT.getValue()))
                .then(tasks.hypokalkulackaTasks().addClientExpenditure(hyposContract, SECOND_CLIENT.getValue()))

                .then(tasks.hypokalkulackaTasks().addClientData(hyposContract, THIRD_CLIENT.getValue()))
                .then(tasks.hypokalkulackaTasks().addClientAddress(hyposContract, THIRD_CLIENT.getValue()))
                .then(tasks.hypokalkulackaTasks().addClientIncomeEmployee(hyposContract, THIRD_CLIENT.getValue()))
                .then(tasks.hypokalkulackaTasks().addClientIncomeOther(hyposContract, THIRD_CLIENT.getValue()))
                .then(tasks.hypokalkulackaTasks().addClientExpenditure(hyposContract, THIRD_CLIENT.getValue()))

                .then(tasks.hypokalkulackaTasks().addHouseholds(hyposContract))
                .then(tasks.hypokalkulackaTasks().addSecondHousehold(hyposContract))
                .then(tasks.hypokalkulackaTasks().addRealtyData(hyposContract))
                .then(tasks.hypokalkulackaTasks().addLoanData(hyposContract))
                .then(tasks.hypokalkulackaTasks().addApplicationData(hyposContract))
                .clickSaveHypokalkulackaButtonAndCheckAlertText()
                .then(tasks.hypokalkulackaTasks().generateAndSignAgreements101())
                .then(tasks.hypokalkulackaTasks().generateAndSignMortgageApplication())
                .getHypokalkulackaVersion(harness);

        hypokalkulackaId = harness.get(HYPOKALKULACKA_ID).toString();
        hypokalkulackaPage.then(tasks.hypokalkulackaTasks().saveHypokalkulacka());
        harness.withHypos().closeHypos();
        Assertions.assertNotNull(hypokalkulackaId, "Hypokalkulačka ID is empty. Stopping test.");
        contractId = new HyposDbTasks(harness).getContractId(hypokalkulackaId);
        Assertions.assertNotNull(contractId, "Contract ID is empty. Stopping test.");

        harness.withHypos()
                .openLoginPage()
                .then(tasks.loginToHyposWithProfile(HyposProfile.EMERGENCY))
                .switchToHypokom()
                .then(tasks.hypokomTasks().searchClientByContractId(contractId))
                .then(tasks.hypokomTasks().setClientAppointmentDate())
                .then(tasks.hypokomTasks().createNewContract(contractId, hyposContract));

        harness.withHypos().closeHypos();
        Assertions.assertEquals(true, new HyposDbTasks(harness).contractPrescoringFinished(contractId), "Prescoring was not finished in 180 seconds interval.");

        harness.withHypos()
                .openLoginPage()
                .then(tasks.loginToHyposWithProfile(HyposProfile.EMERGENCY))
                .then(tasks.searchAndOpenContractAndCheckState(contractId, "Obchod založen - kontrola OK"))
                .then(tasks.contractTasks().setLoanAndDrawingConditions(hyposContract))
                .then(tasks.contractTasks().setNewRealtyAndSupervision(hyposContract))
                .then(tasks.contractTasks().importChecklistUwDocument())
                .then(tasks.hypokalkulackaTasks().setClientDetailIncomeBusiness(hyposContract, FIRST_CLIENT))
                .then(tasks.hypokalkulackaTasks().setClientDetailIncomeEmployee(hyposContract, SECOND_CLIENT))
                .then(tasks.hypokalkulackaTasks().setClientDetailIncomeEmployee(hyposContract, THIRD_CLIENT))
                .then(tasks.contractTasks().setScoringAutomat());

        harness.withHypos().closeHypos();
        Assertions.assertEquals(true, new HyposDbTasks(harness).contractScoringWithApVerificationFinished(contractId), "Scoring with AP verification was not finished in 180 seconds interval.");

        harness.withHypos()
                .openLoginPage()
                .then(tasks.loginToHyposWithProfile(HyposProfile.EMERGENCY))
                .then(tasks.searchAndOpenContractAndCheckState(contractId, "Scoring"))
                .then(tasks.contractTasks().setApVerification());

        harness.withHypos().closeHypos();
        Assertions.assertNotNull(harness.get(AP_ID).toString(), "AP ID is empty. Stopping test.");
        List<String> taskIds = harness.get(TASK_IDS);
        Assertions.assertFalse(taskIds.isEmpty(), "Task ID is empty. Stopping test.");
        Assertions.assertEquals(true, new HyposDbTasks(harness).contractScoringFinished(contractId), "Scoring was not finished in 180 seconds interval.");

        harness.withHypos()
                .openLoginPage()
                .then(tasks.loginToHyposWithProfile(HyposProfile.EMERGENCY))
                .then(tasks.searchAndOpenContractAndCheckState(contractId, "Ověřování"))
                .then(tasks.contractTasks().checkScoringResult(scoringParameters));

        harness.withHypos()
                .openLoginPage()
                .then(tasks.loginToHyposWithProfile(HyposProfile.EMERGENCY))
                .then(tasks.searchAndOpenContract(contractId))
                .then(tasks.contractTasks().setCancelContract());
    }
}