package ru.yandex.autotests.directapi.finance.accountmanagement.deposit;

import java.util.Arrays;

import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;

import ru.yandex.aqua.annotations.project.Aqua;
import ru.yandex.autotests.direct.utils.money.Currency;
import ru.yandex.autotests.direct.utils.money.Money;
import ru.yandex.autotests.direct.utils.money.MoneyCurrency;
import ru.yandex.autotests.direct.utils.tags.TagDictionary;
import ru.yandex.autotests.directapi.apiclient.config.Semaphore;
import ru.yandex.autotests.directapi.apiclient.errors.AxisError;
import ru.yandex.autotests.directapi.apiclient.errors.AxisErrorDetails;
import ru.yandex.autotests.directapi.common.api45.APIPort_PortType;
import ru.yandex.autotests.directapi.common.api45.Account;
import ru.yandex.autotests.directapi.common.api45.CreditLimitsInfo;
import ru.yandex.autotests.directapi.finance.FinanceFeatures;
import ru.yandex.autotests.directapi.finance.FinanceLogins;
import ru.yandex.autotests.directapi.model.User;
import ru.yandex.autotests.directapi.model.finances.PaymentMap;
import ru.yandex.autotests.directapi.rules.ApiSteps;
import ru.yandex.autotests.directapi.rules.Trashman;
import ru.yandex.autotests.directapi.steps.ConditionFactories;
import ru.yandex.autotests.directapi.steps.finance.FinanceSteps;
import ru.yandex.autotests.irt.testutils.allure.LogSteps;
import ru.yandex.qatools.Tag;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.hazelcast.SemaphoreRule;

import static org.hamcrest.core.IsEqual.equalTo;

/**
 * User: mariabye
 * Date: 16.10.13
 */
@Aqua.Test
@Features(FinanceFeatures.ACCOUNT_MANAGEMENT_DEPOSIT)
@Tag(TagDictionary.TRUNK)
public class DepositContractModeTest {
    private LogSteps log = LogSteps.getLogger(this.getClass());

    @ClassRule
    public static ApiSteps api = new ApiSteps().version(104).wsdl(APIPort_PortType.class);

    @ClassRule
    public static SemaphoreRule semaphore = Semaphore.getSemaphore();

    @Rule
    public Trashman trasher = new Trashman(api);

    static String agencyLogin = FinanceLogins.AGENCY_DEPOSIT_1;
    static String agencySubclient1Login = FinanceLogins.DEPOSIT_SC_4;
    static String agencySubclient2Login = FinanceLogins.DEPOSIT_SC_5;
    private static int accountID1;
    private static int accountID2;
    private static Money minPaymentAmount;
    private static String agencyContract;


    @BeforeClass
    public static void getAccountIDs() {
        api.as(agencyLogin);
        api.userSteps.clientFakeSteps().enableAgencyWallet(agencyLogin);
        api.userSteps.createAccount(FinanceLogins.DEPOSIT_SC_2);
        api.userSteps.createAccount(agencySubclient1Login);
        api.userSteps.createAccount(agencySubclient2Login);
        accountID1 = api.userSteps.financeSteps().getAccountID(agencySubclient1Login);
        accountID2 = api.userSteps.financeSteps().getAccountID(agencySubclient2Login);
        api.userSteps.balanceSteps().synchronizeWithBalance(accountID1);
        api.userSteps.balanceSteps().synchronizeWithBalance(accountID2);
        api.userSteps.financeSteps().verifyCampaignExistsInBalance(accountID1);
        api.userSteps.financeSteps().verifyCampaignExistsInBalance(accountID2);
        minPaymentAmount = MoneyCurrency.get(Currency.RUB).getMinInvoiceAmount();
        agencyContract = User.get(agencyLogin).getExternalContractID();
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5982")
    public void agencyPayForSubClient() {
        api.as(FinanceLogins.AGENCY_DEPOSIT_1);
        Account account = api.userSteps.financeSteps().getAccount(agencySubclient1Login);
        Float amount = account.getAmount();
        api.userSteps.financeSteps().deposit(
                new PaymentMap(api.type())
                        .withAccountID(accountID1)
                        .withAmount(minPaymentAmount.addVAT().floatValue())
                        .withContract(agencyContract)
                        .withCurrency(Currency.RUB)
        );


        ConditionFactories.NOTIFY_ORDER2.until(
                api.userSteps.financeSteps().accountAmountIs(account), equalTo(
                        minPaymentAmount.add(amount).floatValue()));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5983")
    public void agencyPayForSubClientOverLimit() {
        api.as(FinanceLogins.AGENCY_DEPOSIT_1);
        CreditLimitsInfo limits = api.userSteps.financeSteps().getCreditLimits();
        float amount = Money.valueOf(limits.getLimits()[0].getLimit() - limits.getLimits()[0].getLimitSpent() + 1.0f)
                .convert(Currency.RUB).addVAT().multiply(2).floatValue();
        api.userSteps.financeSteps().shouldGetErrorsOnAMDeposit(
                new PaymentMap[]{new PaymentMap(api.type())
                        .withAccountID(accountID1)
                        .withAmount(amount)
                        .withContract(agencyContract)
                        .withCurrency(Currency.RUB)},
                new AxisError(355, AxisErrorDetails.EMPTY_STRING)
        );

    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5984")
    public void agencyPayForSubClients() {
        api.as(FinanceLogins.AGENCY_DEPOSIT_1);
        Account account1 = api.userSteps.financeSteps().getAccount(accountID1);
        Account account2 = api.userSteps.financeSteps().getAccount(accountID2);
        Float amount1 = account1.getAmount();
        Float amount2 = account2.getAmount();
        api.userSteps.financeSteps().deposit(
                new PaymentMap(api.type())
                        .withAccountID(accountID1)
                        .withAmount(minPaymentAmount.addVAT().floatValue())
                        .withContract(agencyContract)
                        .withCurrency(Currency.RUB),
                new PaymentMap(api.type())
                        .withAccountID(accountID2)
                        .withAmount(minPaymentAmount.add(100f).addVAT().floatValue())
                        .withContract(agencyContract)
                        .withCurrency(Currency.RUB)
        );


        ConditionFactories.NOTIFY_ORDER2.until(
                api.userSteps.financeSteps().accountAmountIs(account1),
                equalTo(minPaymentAmount.add(amount1).floatValue()));


        ConditionFactories.NOTIFY_ORDER2.until(
                api.userSteps.financeSteps().accountAmountIs(account2),
                equalTo(minPaymentAmount.add(amount2).add(100f).floatValue()));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5987")
    public void agencyPaymentItemsMaxNumber() {
        api.as(FinanceLogins.AGENCY_DEPOSIT_1);
        PaymentMap payment = new PaymentMap(api.type())
                .withAccountID(0)
                .withAmount(400f)
                .withCurrency(Currency.RUB)
                .withContract(agencyContract);
        PaymentMap[] payments = new PaymentMap[FinanceSteps.PAYMENT_ITEMS_MAX_NUMBER];
        Arrays.fill(payments, payment);
        AxisError[] errors = new AxisError[FinanceSteps.PAYMENT_ITEMS_MAX_NUMBER];
        Arrays.fill(errors, new AxisError(54, AxisErrorDetails.EMPTY_STRING));
        api.userSteps.financeSteps().shouldGetErrorsOnAMDeposit(payments, errors);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5988")
    public void agencyPaymentItemsLimit() {
        api.as(FinanceLogins.AGENCY_DEPOSIT_1);
        PaymentMap payment = new PaymentMap(api.type())
                .withAccountID(0)
                .withAmount(400f)
                .withCurrency(Currency.RUB);
        PaymentMap[] payments = new PaymentMap[FinanceSteps.PAYMENT_ITEMS_MAX_NUMBER + 1];
        Arrays.fill(payments, payment);
        api.userSteps.financeSteps()
                .shouldGetErrorOnAMDeposit(
                        new AxisError(241, AxisErrorDetails.THE_ARRAY_MUST_CONTAIN_NO_MORE_THAN_N_ELEMENTS,
                                "Payments", 50),
                        payments);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5989")
    public void subClientNoRightToPay() {
        int accountID = api.as(agencyLogin).userSteps.financeSteps()
                .getAccountID(FinanceLogins.DEPOSIT_SC_2);
        api.as(FinanceLogins.DEPOSIT_SC_2);
        api.userSteps.financeSteps().shouldGetErrorOnAMDeposit(
                new AxisError(71, AxisErrorDetails.FIELD_MUST_NOT_BE_EMPTY, "Payments[0].Origin"),
                new PaymentMap(api.type())
                        .withAccountID(accountID)
                        .withAmount(minPaymentAmount.floatValue())
                        .withContract(agencyContract)
                        .withCurrency(Currency.RUB)
        );
    }
}
