package cz.moneta.test.dsl.util.task.wso2.cards;

import com.fasterxml.jackson.databind.JsonNode;
import cz.moneta.test.dsl.Harness;
import cz.moneta.test.dsl.wso2.data.CardData;
import cz.moneta.test.harness.support.rest.RawRestRequest;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class CardsTasks {

    private final Harness harness;

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

    public RawRestRequest.Response getDebitCardInfo(String accountNumber) {
        return harness.withWso2()
                .prepareRequestXml()
                .withPath("/t/cards.cluster/test-ods-get-card-data")
                .withPayloadFromFile("regression/transactional/cards/get_debit_card_details.xml")
                .addField("CRNT_ACC_NUM_IN", accountNumber)
                .post();
    }

    public RawRestRequest.Response getCreditCardInfo(String contractNumber) {
        return harness.withWso2()
                .prepareRequestXml()
                .withPath("/t/cards.cluster/test-ods-get-card-data")
                .withPayloadFromFile("regression/transactional/cards/get_credit_card_details.xml")
                .addField("CONTR_NUM_IN", contractNumber)
                .post();
    }

    public CardData getCardInfoByRc(String rc, String cardType) {
        JsonNode data = getInstPtKey(rc);

        String uniPtKey = data.path("UNI_PT_KEY").textValue();
        String cif = data.path("CIF").textValue();

        JsonNode response = getCardInfoByUniPtKey(cardType, uniPtKey);

        String card = response.path("CARD_NUM").textValue();
        String account = response.path("ACC_NUM").textValue();
        String contract = response.path("CONTR_NUM").textValue();
        String prodInstKey = response.path("PROD_INST_KEY").textValue();
        String name = response.path("FIRST_NAME_OWNR").textValue() + " " + response.path("FAMILY_NAME_OWNR").textValue();
        String bu;

        if ("D".equalsIgnoreCase(cardType)) {
            bu = response.path("CRNT_ACC_NUM").textValue(); //for DC bu can be found in ods
        } else {
            bu = harness.withWso2() //for CC bu can be found in VMX.ACCOUNT.INQ
                    .prepareRequestXml()
                    .withPath("t/cards.cluster/call-fv/v1")
                    .withPayloadFromFile("regression/transactional/cards/VMX.ACCOUNT.INQ.xml")
                    .addField("VMX_MSGIN", "ACCOUNT", account)
                    .post()
                    .andAssertFieldValue("VMX_ROOT.VMX_MSGOUT.SVC_RETURN", "P")
                    .extract("VMX_ROOT.VMX_MSGOUT.ACCT_BS_OUTPUT.BANK_ACCT_NBR")
                    .textValue()
                    .substring(8);
        }

        return CardData.builder()
                .rc(rc)
                .account(account)
                .card(card)
                .cif(cif)
                .bu(bu)
                .name(name)
                .cardType(cardType)
                .contract(contract)
                .prodInstKey(prodInstKey)
                .build();
    }

    public RawRestRequest.Response activateCard(String card) {
        return harness.tasks().wso2().restRequest()
                .prepareEmptyRequestFromUfo("/t/cards.cluster/card-servicing-do-activation-v1")
                .addField("NOTE", "Activated")
                .addField("CisloKarty", card)
                .postExtended();
    }

    private JsonNode getCardInfoByUniPtKey(String cardType, String uniPtKey) {
        return harness.withWso2()
                .prepareRequestXml()
                .withPath("/t/cards.cluster/test-ods-get-card-data")
                .withPayloadFromFile("regression/transactional/cards/getCardData.xml")
                .addField("CARD_DC_FLAG_IN", cardType)
                .addField("RS_2.row", "UNI_PT_KEY_IN", uniPtKey)
                .post()
                .extract("RS_3.rows.row");
    }

    private JsonNode getInstPtKey(String rc) {
        return harness.withWso2()
                .prepareRequestXml()
                .withPath("/t/cards.cluster/test-ods-get-inst-pt-key")
                .withPayloadFromFile("regression/transactional/cards/getInstPtKey.xml")
                .addField("RC_NUM_IN", rc)
                .post()
                .extract("RS_1.rows.row");
    }

    private String getUfoToken() {
        return harness.tasks()
                .wso2()
                .authorization()
                .getToken("UFO");
    }

    public String getCardNumberByBirthNumber(String birthNumber) {
        return harness.withWso2()
                .prepareRequest()
                .withPath("t/cards.cluster/GET_CARD_LIST_BY_BIRTH_NUM/001")
                .withHeader("Authorization", getUfoToken())
                .withHeader("Content-Type", "application/json")
                .withHeader("userid_l2", "GEMTEST")
                .withPayload("{\n" +
                        "    \"RodneCislo\": " + birthNumber + "\n" +
                        "}")
                .post()
                .andAssertStatus(200)
                .extract("Data")
                .findValue("CisloKarty")
                .asText();
    }

    private boolean isActivatedServicesOnCard(String cardNumber) {
        int numberActivated = harness.withWso2()
                .prepareRequest()
                .withPath("t/cards.cluster/GET_LIST_ADD_SERVICES/001")
                .withHeader("Authorization", getUfoToken())
                .withHeader("Content-Type", "application/json")
                .withHeader("userid_l2", "GEMTEST")
                .withPayload("{\n" +
                        "  \"CisloKarty\": " + cardNumber + ", \n" +
                        "  \"DruhKarty\": \"1\",\n" +
                        "  \"JenAktivniDS\": \"1\"\n" +
                        "}")
                .post()
                .andAssertStatus(200)
                .extract("Pocet")
                .asInt();

        return numberActivated > 0;
    }

    private void deactivateInsuranceOnCard(String cardNumber) {
        String date = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(LocalDate.now().minusDays(30));
        harness.withWso2()
                .prepareRequest()
                .withPath("t/cards.cluster/DO_ADD_SERVICES_DEACTIVATE/001")
                .withHeader("Authorization", getUfoToken())
                .withHeader("Content-Type", "application/json")
                .withHeader("userid_l2", "GEMTEST")
                .withPayload("{\n" +
                        "  \"CisloKaretnihoUctu\": \"\",\n" +
                        "  \"CisloKarty\": \"" + cardNumber + "\",\n" +
                        "  \"DSDatumUcinnostiZaniku\": \"" + date + "\",\n" +
                        "  \"DSDatumZruseni\": \"" + date + "\",\n" +
                        "  \"DSDatumZruseniDoruceno\": \"" + date + "\",\n" +
                        "  \"DSDuvodRuseni\": \"5\",\n" +
                        "  \"DSKodDistribucnihoKanalu\": \"1\",\n" +
                        "  \"KodDS\": \"BC\"\n" +
                        "}")
                .post()
                .andAssertStatus(200);
    }

    public void deactivateExhaustedAmountInsuranceCreditCard(String birthNumber) {
        String cardNumber = getCardNumberByBirthNumber(birthNumber);

        if (isActivatedServicesOnCard(cardNumber)) {
            deactivateInsuranceOnCard(cardNumber);
            harness.log("Exhausted amount insurance on credit card " + cardNumber + " is deactivated");
            return;
        }
        harness.log("Credit card " + cardNumber + " has not active additional services");
    }
}