package cz.moneta.test.dsl.ufo.banka.tasks.expres;

import cz.moneta.test.dsl.Harness;
import cz.moneta.test.dsl.ilods.Ilods;
import cz.moneta.test.dsl.ufo.banka.pages.loans.expres.HousingLoanData;
import cz.moneta.test.dsl.ufo.banka.pages.loans.expres.LoanData;
import cz.moneta.test.dsl.ufo.banka.pages.main.codelists.HCisAllLoanObject;
import cz.moneta.test.dsl.ufo.banka.pages.main.codelists.HCisBLRateFixation;
import cz.moneta.test.dsl.ufo.banka.pages.main.codelists.HCisPropertyOwnershipType;
import cz.moneta.test.dsl.ufo.banka.pages.main.codelists.HCisUcelUveruExpres;
import cz.moneta.test.dsl.util.data.client.*;
import cz.moneta.test.harness.support.auth.Credentials;
import cz.moneta.test.harness.support.data.GeneratorType;
import cz.moneta.test.harness.support.rest.RawRestRequest;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;

import static cz.moneta.test.dsl.util.DateUtils.convertRawDateForWso2;
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;
import static cz.moneta.test.harness.support.data.GeneratorType.*;

public class ExpresLoanDataPreparationTasks {
    private final Harness harness;

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

    public static final String CLIENT_CIF_STORE_KEY = "CLIENT_CIF";

    public NonClient createClientData() {
        return harness.data().newNonClient()
                .withBirthNumber(harness.tasks().common().getRcMinMaxAge(18, 64))
                .withEmail(DEFAULT_EMAIL)
                .withMobileNumber(DEFAULT_MOBILE_NUMBER)
                .withDriverLicenceId(DEFAULT_DRIVING_LICENSE_ID)
                .withDriveLicenceExpiryDateRaw(DEFAULT_DRIVING_LICENSE_EXPIRATION_DATE)
                .withResidencyAddress(DEFAULT_CLIENT_ADDRESS)
                .withIdCard(DEFAULT_ID_CARD)
                .withOtherExpenses(1000)
                .withOtherLoanPayments(0)
                .withNetMonthlyIncome(200000)
                .withHomeIncome(200000)
                .withOccupationEmploymentFromRaw(Date.from(LocalDate.now().minusYears(3).atStartOfDay(ZoneId.systemDefault()).toInstant()))
                .withCurrentAddressSinceRaw(Date.from(LocalDate.now().minusYears(3).atStartOfDay(ZoneId.systemDefault()).toInstant()))
                .withEmployer(DEFAULT_EMPLOYER);
    }

    public NonClient createCoApplicantData() {
        return harness.data().newNonClient()
                .withIdCard(new IdCard("212756197", LocalDate.of(2018, 8, 12), LocalDate.of(2031, 3, 15)))
                .withEmail("test@test.cz")
                .withMobileNumber(harness.generate(GeneratorType.MOBILE_PHONE_NUMBER))
                .withNetMonthlyIncome(100000)
                .withHomeIncome(100000)
                .withOtherExpenses(1000)
                .withOtherLoanPayments(0)
                .withOccupationEmploymentFromRaw(Date.from(LocalDate.now().minusYears(3).atStartOfDay(ZoneId.systemDefault()).toInstant()))
                .withCurrentAddressSinceRaw(Date.from(LocalDate.now().minusYears(3).atStartOfDay(ZoneId.systemDefault()).toInstant()))
                .withEmployer(DEFAULT_EMPLOYER);
    }

    public NonClient createSecondCoApplicantData() {
        return harness.data().newNonClient()
                .withIdCard(new IdCard("212756197", LocalDate.of(2018, 8, 12), LocalDate.of(2031, 3, 15)))
                .withEmail("test2@test2.cz")
                .withMobileNumber(harness.generate(GeneratorType.MOBILE_PHONE_NUMBER))
                .withNetMonthlyIncome(90000)
                .withHomeIncome(90000)
                .withOtherExpenses(1000)
                .withOtherLoanPayments(0)
                .withOccupationEmploymentFromRaw(Date.from(LocalDate.now().minusYears(3).atStartOfDay(ZoneId.systemDefault()).toInstant()))
                .withCurrentAddressSinceRaw(Date.from(LocalDate.now().minusYears(3).atStartOfDay(ZoneId.systemDefault()).toInstant()))
                .withEmployer(DEFAULT_EMPLOYER);
    }

    public NonClient createWifeData() {
        return createCoApplicantData()
                .withMaritalStatus(MaritalStatus.MARRIED)
                .withBirthNumber(harness.generate(RC, Gender.WOMAN))
                .withFirstName(harness.generate(FIRST_NAME, Gender.WOMAN))
                .withLastName(harness.generate(LAST_NAME, Gender.WOMAN))
                .withGender(Gender.WOMAN)
                .withEmployer(DEFAULT_EMPLOYER);
    }

    public LoanData preBuildLoanData() {
        NonClient client = createClientData();
        return LoanData.builder()
                .client(client)
                .housingLoanData(HousingLoanData.builder()
                        .isRealityCustomAddress(false)
                        .realityCustomAddress(Address.builder()
                                .street("Ořechová")
                                .descriptiveNumber("652")
                                .orientationNumber("")
                                .city("Benátky nad Jizerou")
                                .zip("29471")
                                .country("CZ")
                                .build())
                        .landRegistryArea("730122")
                        .plotNumber("2125/5")
                        .apartmentNumber("2")
                        .realityType(HCisAllLoanObject.APARTMENT)
                        .ownershipType(HCisPropertyOwnershipType.COOPERATIVE)
                        .purposeType(HCisUcelUveruExpres.TRANSFER_OF_COOPERATIVE_SHARE)
                        .fixation(HCisBLRateFixation._5Y).build())
                .amount(50000)
                .term(72)
                .paymentsOutsideMMB(0)
                .otherMonthlyExpenses(1000)
                .isInsurance(false)
                .insuranceName("Bez pojištění")
                .build();
    }

    public String prepareClient(NonClient client) {
        Credentials cr = getCredentials(banker, harness);
        NewClientWithCurrentAccountInformation info = harness.dataPrepare().createNewFoCustomerWithCurrentAccountAndIbViaWso2(client, cr.getUsername());
        harness.dataPrepare().setClientIncome(info.getCif(), client);
        addIncomeDocumentsByApi(client);

        Ilods i = harness.withIlods();
        i.setScore("EXBEH02", client.birthNumber(), "");
        i.setScore("EXECB02", client.birthNumber(), "");
        i.setScore("EXON04S3", client.birthNumber(), "");
        return info.getCif();
    }

    public String prepareClientForLoans(NonClient client) {
        Credentials cr = getCredentials(banker, harness);
        NewClientWithCurrentAccountInformation info = harness.dataPrepare().createNewFoCustomerWithCurrentAccountAndIbViaWso2(client, cr.getUsername());
        harness.dataPrepare().createSmartBankFo(info.getCif());
        harness.dataPrepare().setClientIncome(info.getCif(), client);
        addIncomeDocumentsByApi(client);

        Ilods i = harness.withIlods();
        i.setScore("BFX08", client.birthNumber(), "");
        i.setScore("EXON04S2", client.birthNumber(), "");
        i.setScore("FXON04S2", client.birthNumber(), "");
        i.setScore("CCON04S2", client.birthNumber(), "");
        i.setScore("UDCON04S2", client.birthNumber(), "");
        i.setSegment("AS_FAM", "EXIST", client.birthNumber(), "");
        i.setSegment("RSK_INFOLIMIT", "INFOLIMIT_CALC", client.birthNumber(), "");
        i.setSegment("CUST_INC_VER", "POI_VALID_STRICTLY", client.birthNumber(), "");
        return info.getCif();
    }

    public String prepareFopClientForLoans(NonClient client) {
        Credentials cr = getCredentials(banker, harness);
        String fopCif = harness.dataPrepare().createNewFopCustomerViaWso2AndGetCif(client, cr.getUsername());

        Ilods i = harness.withIlods();
        i.setScore("ABC01", client.birthNumber(), "");
        i.setSegment("BANKID_CLIENT", "BANKID_VERIFIED", client.birthNumber(), "");
        i.setSegment("RSK_INFOLIMIT_EBR", "INFOLIMIT_EBR_CALC", client.birthNumber(), "");
        i.setSegment("NTC", "NTC", client.birthNumber(), "");
        return fopCif;
    }

    private void addIncomeDocumentsByApi(NonClient client) {
        RawRestRequest.Response resp = harness.tasks().wso2().restRequest()
                .prepareEmptyRequestFromUfo("/t/backoffice.cluster/application/documents/create-document/001")
                .addField("POS_ID", "86001340")
                .addField("ISSUER_ICO_NUM", client.employer().getIco())
                .addField("CHANNEL", "UFO BANKA")
                .addField("CLIENT_RC_NUM", client.birthNumber())
                .addField("OTHER_INSTALMENT_PAYMENTS", client.otherLoanPayments())
                .addField("EMPLOYMENT_TYPE", "1")
                .addField("CLIENT_FAMILY_NAME", client.lastName())
                .addField("CLIENT_FIRST_NAME", client.firstName())
                .addField("MONTHLY_DEDUCTION", 0)
                .addField("ISSUER_SIGN_FLAG", 1)
                .addField("ISSUER_COMP_NAME", client.employer().getName())
                .addField("USER_SSO", "212431936")
                .addField("DOC_COUNTRY_SOURCE", "52")
                .addField("ADVICE_OF_RECEIPT_COUNT", 1)
                .addField("INCOME_CASH_FLAG", 0)
                .addField("ISSUE_DATE", convertRawDateForWso2(new Date()))
                .addField("CLIENT_NET_INC", client.netMonthlyIncome())
                .addField("DOCUMENT_TYPE", "1")
                .addField("CURRENCY", "0")
                .addField("ISSUER_STAMP_FLAG", 1)
                .addField("STANDALONE_FLAG", 1)
                .addField("EMPLOYMENT_START_DATE", convertRawDateForWso2(client.occupationEmploymentFromRaw()))
                .addField("MAINTAINED_PERSON_COUNT", 0)
                .post()
                .andAssertStatus(200)
                .andAssertPresent("DOC_INST_KEY");
        int DOC_INST_KEY = resp.extract("DOC_INST_KEY").intValue();

        harness.tasks().wso2().restRequest()
                .prepareEmptyRequestFromUfo("/t/risk.cluster/NAS/DO_FORMAL_DOCS_002/001")
                .addField("DOC_INST_KEY", DOC_INST_KEY)
                .post()
                .andAssertStatus(200)
                .andAssertFieldValue("FORMAL_OK_FLAG", "1");

        harness.withWso2().prepareRequest().withPath("/t/mwf.legacy/HUB/MWF736/001")
                .withHeader("Authorization", harness.tasks().wso2().authorization().getToken("UFO"))
                .withHeader("Content-Type", "application/json")
                .withHeader("USERID_L2", "212431936")
                .withPayload(
                        "{\n" +
                                "    \"PROCESS_CONTEXT\": \"null\",\n" +
                                "    \"DocsToCheck\": null,\n" +
                                "    \"Data\": [\n" +
                                "        {\n" +
                                "            \"RS_RC_NUMBER\": \"" + client.birthNumber() + "\",\n" +
                                "            \"RS_PAIRING_COMPLETE\": null\n" +
                                "        }\n" +
                                "    ]\n" +
                                "}")
                .post()
                .andAssertStatus(200);
    }

    public void prepareCoApplicants(List<NonClient> coApplicants) {
        for (NonClient coApplicant : coApplicants) {
            prepareClient(coApplicant);
        }
    }
}
