package cz.moneta.test.dsl.util.task.cagw.api;

import cz.moneta.test.dsl.Harness;
import cz.moneta.test.dsl.cagw.api.cbl.psd.pisp.my.payments.*;

import java.util.function.Function;

//FIXME TA-361 remove parameters, change it to data object.
public class PaymentTasks {

    private final Harness harness;

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

    public Function<Payment, Payment> setRequestValues(String authToken, String currency, int paymentAmount,
                                                       String debtorAccountNumber, String creditAccountIban) {
        return start -> start.withAuthorizationBearer("Bearer " + authToken)
                .amount(Amount.builder()
                        .instructedAmount(Amount.InstructedAmount.builder()
                                .currency(currency)
                                .value(paymentAmount)
                                .build())
                        .build())
                .debtorAccount(DebtorAccount.builder()
                        .identification(DebtorAccount.DebtorIdentification.builder()
                                .other(DebtorAccount.Other.builder()
                                        .identification(debtorAccountNumber)
                                        .build())
                                .build())
                        .build())
                .creditorAccount(CreditorAccount.builder()
                        .identification(CreditorAccount.CreditorIdentification.builder()
                                .iban(creditAccountIban)
                                .build())
                        .build());
    }

    public Function<Payment, Payment> setRequestValuesForForeignPayment(String authToken, String currencyAmount,
                                                                        int valueAmount, String chargeBearer,
                                                                        String nameCreditor,
                                                                        String adressLineCreditor,
                                                                        String identificationCreditorAccount,
                                                                        String nameCreditorAgent,
                                                                        String bicCreditorAgent,
                                                                        String addressLineCreditorAgent,
                                                                        String countryCreditorAgent,
                                                                        String ibanDebtorAccount,
                                                                        String unstructured,
                                                                        String requestedExecutionDate,
                                                                        String transactionConfirmation) {
        return start -> start.withAuthorizationBearer("Bearer " + authToken)
                .then(setAmount(currencyAmount, valueAmount))
                .chargeBearer(chargeBearer)
                .then(setCreditor(nameCreditor, adressLineCreditor, null, null))
                .then(setCreditorAccount(null, null, identificationCreditorAccount))
                .then(setCreditorAgent(nameCreditorAgent, bicCreditorAgent, addressLineCreditorAgent, countryCreditorAgent))
                .then(setDebtorAccount(ibanDebtorAccount, null))
                .then(setRemittanceInformationForeign(unstructured))
                .requestedExecutionDate(requestedExecutionDate)
                .transactionConfirmation(transactionConfirmation);
    }

    public Function<Payment, Payment> setRequestValuesForSepaPayment(String authToken, String currencyAmount,
                                                                     int valueAmount, String chargeBearer,
                                                                     String nameCreditor,
                                                                     String adressLineCreditor,
                                                                     String countryCreditor,
                                                                     String townNameCreditor,
                                                                     String ibanCreditorAccount,
                                                                     String nameCreditorAgent,
                                                                     String ibanDebtorAccount,
                                                                     String endToEndIdentification,
                                                                     String unstructured,
                                                                     String requestedExecutionDate,
                                                                     String transactionConfirmation) {
        return start -> start.withAuthorizationBearer("Bearer " + authToken)
                .then(setAmount(currencyAmount, valueAmount))
                .chargeBearer(chargeBearer)
                .then(setCreditor(nameCreditor, adressLineCreditor, countryCreditor, townNameCreditor))
                .then(setCreditorAccount(null, ibanCreditorAccount, null))
                .then(setCreditorAgent(nameCreditorAgent, null, null, null))
                .then(setDebtorAccount(ibanDebtorAccount, null))
                .then(setPaymentIdentification(endToEndIdentification, null))
                .then(setRemittanceInformationForeign(unstructured))
                .requestedExecutionDate(requestedExecutionDate)
                .transactionConfirmation(transactionConfirmation);
    }

    public Function<Payment, Payment> setRequestValuesForDomesticPayment(String authToken, String currencyAmount,
                                                                         int valueAmount,
                                                                         String ibanCreditorAccount,
                                                                         String identificationDebtorAccount,
                                                                         String reference, String unstructured,
                                                                         String requestedExecutionDate) {
        return start -> start.withAuthorizationBearer("Bearer " + authToken)
                .then(setAmount(currencyAmount, valueAmount))
                .then(setCreditorAccount(null, ibanCreditorAccount, null))
                .then(setDebtorAccount(null, identificationDebtorAccount))
                .then(setRemittanceInformation(reference, unstructured))
                .requestedExecutionDate(requestedExecutionDate);

    }

    public Function<Payment, Payment> setRequestValuesForDomForeignCurrPayment(String authToken,
                                                                               String currencyAmount,
                                                                               int valueAmount,
                                                                               String identificationCreditorAccount,
                                                                               String identificationDebtorAccount,
                                                                               String requestedExecutionDate) {
        return start -> start.withAuthorizationBearer("Bearer " + authToken)
                .then(setAmount(currencyAmount, valueAmount))
                .then(setCreditorAccount(null, null, identificationCreditorAccount))
                .then(setDebtorAccount(null, identificationDebtorAccount))
                .requestedExecutionDate(requestedExecutionDate);

    }

    private static Function<Payment, Payment> setAmount(String currencyAmount, Integer valueAmount) {
        return start -> start.amount(Amount.builder()
                .instructedAmount(Amount.InstructedAmount.builder()
                        .currency(currencyAmount)
                        .value(valueAmount)
                        .build())
                .build());
    }

    private static Function<Payment, Payment> setCreditor(String nameCreditor,
                                                          String adressLineCreditor, String countryCreditor,
                                                          String townNameCreditor) {
        return start -> start.creditor(Creditor.builder()
                .name(nameCreditor)
                .postalAddress(Creditor.PostalAddress.builder()
                        .addressLine(adressLineCreditor)
                        .country(countryCreditor)
                        .townName(townNameCreditor)
                        .build())
                .build());
    }

    private static Function<Payment, Payment> setCreditorAccount(String currencyCreditorAccount,
                                                                 String ibanCreditorAccount,
                                                                 String identificationCreditorAccount) {
        return start -> start.creditorAccount(CreditorAccount.builder()
                .currency(currencyCreditorAccount)
                .identification(CreditorAccount.CreditorIdentification.builder()
                        .iban(ibanCreditorAccount)
                        .other(CreditorAccount.Other.builder()
                                .identification(identificationCreditorAccount)
                                .build())
                        .build())
                .build());
    }

    private static Function<Payment, Payment> setCreditorAgent(String nameCreditorAgent, String bicCreditorAgent,
                                                               String addressLineCreditorAgent,
                                                               String countryCreditorAgent) {
        return start -> start.creditorAgent(CreditorAgent.builder()
                .financialInstitutionIdentification(CreditorAgent.FinancialInstitutionIdentification.builder()
                        .name(nameCreditorAgent)
                        .bic(bicCreditorAgent)
                        .postalAddress(CreditorAgent.PostalAddress.builder()
                                .addressLine(addressLineCreditorAgent)
                                .country(countryCreditorAgent)
                                .build())
                        .build())
                .build());
    }

    private static Function<Payment, Payment> setDebtorAccount(String ibanDebtorAccount,
                                                               String identificationDebtorAccount) {
        return start -> start.debtorAccount(DebtorAccount.builder()
                .identification(DebtorAccount.DebtorIdentification.builder()
                        .iban(ibanDebtorAccount)
                        .other(DebtorAccount.Other.builder()
                                .identification(identificationDebtorAccount)
                                .build())
                        .build())
                .build());
    }

    private static Function<Payment, Payment> setPaymentIdentification(String endToEndIdentification,
                                                                       String transactionIdentification) {
        return start -> start.paymentIdentification(PaymentIdentification.builder()
                .endToEndIdentification(endToEndIdentification)
                .transactionIdentification(transactionIdentification)
                .build());
    }

    private static Function<Payment, Payment> setRemittanceInformation(String reference, String unstructured) {
        return start -> start.remittanceInformation(RemittanceInformation.builder()
                .structured(RemittanceInformation.Structured.builder()
                        .creditorReferenceInformation(RemittanceInformation.CreditorReferenceInformation.builder()
                                .reference(reference)
                                .build())
                        .build())
                .unstructured(unstructured)
                .build());
    }

    private static Function<Payment, Payment> setRemittanceInformationForeign(String unstructured) {
        return start -> start.remittanceInformation(RemittanceInformation.builder()
                .unstructured(unstructured)
                .build());
    }
}
