package cz.moneta.test.dsl.hypos.contractPrepare;

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.Expenditure;
import cz.moneta.test.dsl.util.data.hypos.HouseholdIncome;
import cz.moneta.test.dsl.util.data.hypos.HyposContract;
import cz.moneta.test.dsl.util.data.hypos.Realty;
import org.junit.jupiter.api.Assertions;

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

import static cz.moneta.test.dsl.hypos.enums.Client.FIRST_CLIENT;
import static cz.moneta.test.dsl.hypos.pages.hypokalkulacka.HypokalkulackaPage.HYPOKALKULACKA_ID;

public class HyposContractPrepare {

    private final Harness harness;
    private HyposTasks tasks;

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

    /**
     * Creating new contract used as precondition for Hypos tests.
     *
     * @return String of contract id used for following tests.
     */
    public String createNewContract(Harness harness) {

        HyposTasks tasks = harness.tasks().hypos();

        String birthNumber = harness.tasks().common().getRcMinMaxAge(20, 30);

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

        NonClient nonClient = harness.data().newNonClient()
                .withBirthNumber(birthNumber)
                .withEmail(TestUtils.getEmailBasedOnRc(birthNumber))
                .withPlaceOfBirth("Praha")
                .withNationality(ClientNationality.CZ.getValue())
                .withMaritalStatus(MaritalStatus.SINGLE)
                .withEducationLevel(EducationLevel.HIGHER)
                .withGrossIncome(90000)
                .withNetMonthlyIncome(80000)
                .withEmployer(Employer.builder().ico("00007064").build())
                .withOccupationStatus(OccupationStatus.FULL_TIME_EMPLOYEE)
                .withOccupationEmploymentFromRaw(DateUtils.getSpecificDayRaw(1, 1, 2000))
                .withOccupationType(OccupationType.IT_GUYS)
                .withIncomeSources("1")
                .withDependants(0)
                .withAccommodationType(AccommodationType.PARENTS)
                .withResidencyAddress(permanentAddress);

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

        HyposClient hyposClient = HyposClient.builder()
                .nonClient(nonClient)
                .stayType(StayType.PERMANENT_WITH_PIN.getValue())
                .livingType(LivingType.WITH_PARENTS.getValue())
                .expenditures(expenditures)
                .build();

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

        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();

        HyposContract 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(1).withoutIncome(0).build())
                .build();

        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().addClientIncomeEmployee(hyposContract, FIRST_CLIENT.getValue()))
                .then(tasks.hypokalkulackaTasks().addClientExpenditure(hyposContract, FIRST_CLIENT.getValue()))

                .then(tasks.hypokalkulackaTasks().addHouseholds(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);

        String hypokalkulackaId = harness.get(HYPOKALKULACKA_ID).toString();

        hypokalkulackaPage.then(tasks.hypokalkulackaTasks().saveHypokalkulacka());
        Assertions.assertNotNull(hypokalkulackaId, "Hypokalkulačka ID is empty. Stopping test.");

        String contractId = new HyposDbTasks(harness).getContractId(hypokalkulackaId);

        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.store("CONTRACT_ID", contractId);

        return harness.get("CONTRACT_ID");
    }

    /**
     * Add unit to Realty as precondition for continuous tests
     *
     * @param harness
     * @param contractId - String of contract id created in createNewContract method.
     */
    public void addUnitToRealty(Harness harness, String contractId, int realtyType) {
        tasks = harness.tasks().hypos();
        harness.withHypos()
                .openLoginPage()
                .then(tasks.loginToHyposWithProfile(HyposProfile.SUPERVISOR))
                .then(tasks.searchAndOpenContract(contractId))
                .then(tasks.valuationTasks().setNewRealty(realtyType))
                .then(tasks.valuationTasks().checkUnitUsage(realtyType))
                .then(tasks.valuationTasks().addUnitToRealty(realtyType))
        ;
    }

    public void createValuationFlat(Harness harness, String contractId) {
        int REALTY_FLAT_DESKTOP = 1;
        tasks = harness.tasks().hypos();
        harness.withHypos()
                .openLoginPage()
                .then(tasks.loginToHyposWithProfile(HyposProfile.SUPERVISOR))
                .then(tasks.searchAndOpenContract(contractId))
                .then(tasks.valuationTasks().goToMarketValuationForm())
                .then(tasks.valuationTasks().doFlatMarketValuation(REALTY_FLAT_DESKTOP));
    }

    /**
     * Close browser after precondition is finished.
     * Reason is, that precondition test should be independent from other tests -> every test has it's own browser session.
     */
    public void closeBrowser() {
        harness.withHypos().closeHypos();
    }
}
