package ru.yandex.autotests.directapi.finance.transfermoney;

import com.yandex.direct.api.v5.campaigns.CampaignGetItem;
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.directapi.apiclient.config.Semaphore;
import ru.yandex.autotests.directapi.common.api45.Account;
import ru.yandex.autotests.directapi.finance.FinanceFeatures;
import ru.yandex.autotests.directapi.finance.FinanceLogins;
import ru.yandex.autotests.directapi.model.finances.PayCampElementMap;
import ru.yandex.autotests.directapi.model.finances.TransferMoneyInfoMap;
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.irt.testutils.allure.LogSteps;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.hazelcast.SemaphoreRule;


/**
 * Author pavryabov
 * Date 26.08.14
 */

@Aqua.Test
@Features(FinanceFeatures.TRANSFER_MONEY)
public class TransferMoneyDifferentTypesOfClientsTest {

    private LogSteps log = LogSteps.getLogger(this.getClass());

    private static final String AGENCY_LOGIN = FinanceLogins.AGENCY_TMONEY;
    private static final String ACCOUNT_CLIENT_LOGIN1 = FinanceLogins.TMONEY_CLIENT0;
    private static final String CLIENT_LOGIN1 = FinanceLogins.TMONEY_CLIENT4;

    @ClassRule
    public static ApiSteps api = new ApiSteps().version(104).as(AGENCY_LOGIN);

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

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

    private static float sumForCreate;
    private static Money sumForTransfer;

    @BeforeClass
    public static void getAccountId() {
        api.userSteps.clientFakeSteps().enableAgencyWallet(AGENCY_LOGIN);
        api.as(AGENCY_LOGIN).userSteps.createAccount(ACCOUNT_CLIENT_LOGIN1);
        sumForCreate = 6000f;
        sumForTransfer = Money.valueOf(1000L, Currency.RUB);
        api.userSteps.financeSteps().verifyAccountExistsInBalance(ACCOUNT_CLIENT_LOGIN1);
        api.userSteps.balanceSteps().synchronizeWithBalance(
                ((Account) api.userSteps.financeSteps().getAccount(ACCOUNT_CLIENT_LOGIN1)).getAccountID());
    }

    public TransferMoneyDifferentTypesOfClientsTest() {
        api.as(AGENCY_LOGIN);
    }

    //2 клиента

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("6545")
    public void transferMoneyBetweenClientWithAccountAndClientNoAccount() {
        log.info("Перевод между двумя кампаниями разных клиентов. " +
                "Кампания источник привязана к кошельку, кампания приемник - нет");
        Account accountFrom = api.userSteps.financeSteps().getAccount(ACCOUNT_CLIENT_LOGIN1);
        long campaignIDFrom = api.userSteps.addActiveCampaign(ACCOUNT_CLIENT_LOGIN1, sumForCreate, Currency.RUB);

        ConditionFactories.NOTIFY_ORDER2.until(api.userSteps.financeSteps().accountAmountChanged(accountFrom));
        long campaignIDTo = api.userSteps.campaignSteps().addDefaultTextCampaign(CLIENT_LOGIN1);
        Money accountAmountBefore = api.userSteps.financeSteps().getAccountAmount(accountFrom.getAccountID());
        CampaignGetItem campaignTo =
                api.userSteps.campaignSteps().getCampaign(CLIENT_LOGIN1, campaignIDTo);
        api.userSteps.financeSteps()
                .transferMoney(campaignIDFrom, campaignIDTo, sumForTransfer.floatValue(), Currency.RUB);

        ConditionFactories.NOTIFY_ORDER2.until(
                api.userSteps.financeSteps().accountAmountChangedOnSum(
                        accountFrom.getAccountID(), accountAmountBefore, sumForTransfer.negate()));

        ConditionFactories.NOTIFY_ORDER2.until(api.userSteps.campaignSteps()
                .campaignFundsChangedOnFunds(CLIENT_LOGIN1, campaignTo, sumForTransfer));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("6547")
    public void transferMoneyBetweenClientNoAccountAndClientWithAccount() {
        log.info("Перевод между двумя кампаниями разных клиентов. " +
                "Кампания приемник привязана к кошельку, кампания источник - нет");
        long campaignIDFrom =
                api.userSteps.addActiveCampaign(CLIENT_LOGIN1, sumForCreate, Currency.RUB);

        ConditionFactories.NOTIFY_ORDER2.until(
                api.userSteps.campaignSteps().campaignFundsChanged(CLIENT_LOGIN1, campaignIDFrom));
        long campaignIDTo = api.userSteps.campaignSteps().addDefaultTextCampaign(ACCOUNT_CLIENT_LOGIN1);
        CampaignGetItem campaignFrom =
                api.userSteps.campaignSteps().getCampaign(CLIENT_LOGIN1, campaignIDFrom);

        Account account = api.userSteps.financeSteps().getAccount(ACCOUNT_CLIENT_LOGIN1);
        Money accountAmountBefore = api.userSteps.financeSteps().getAccountAmount(account.getAccountID());

        api.userSteps.financeSteps()
                .transferMoney(campaignIDFrom, campaignIDTo, sumForTransfer.floatValue(), Currency.RUB);

        ConditionFactories.NOTIFY_ORDER2.until(
                api.userSteps.financeSteps().accountAmountChangedOnSum(
                        account.getAccountID(), accountAmountBefore, sumForTransfer));

        ConditionFactories.NOTIFY_ORDER2.until(api.userSteps.campaignSteps()
                .campaignFundsChangedOnFunds(CLIENT_LOGIN1, campaignFrom, sumForTransfer.negate()));
    }

    //3 клиента

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("6546")
    public void transferMoneyFromAccountToTwoCampaignsOneClient() {
        log.info("Перевод с кампании, приязанной к кошельку на две кампании одного клиента без кошелька");
        Account account = api.userSteps.financeSteps().getAccount(ACCOUNT_CLIENT_LOGIN1);
        long accountFrom =
                api.userSteps.addActiveCampaign(ACCOUNT_CLIENT_LOGIN1, sumForCreate, Currency.RUB);

        ConditionFactories.NOTIFY_ORDER2.until(api.userSteps.financeSteps().accountAmountChanged(account));
        long campaignIDTo = api.userSteps.campaignSteps().addDefaultTextCampaign(CLIENT_LOGIN1);
        long campaignIDToElse = api.userSteps.campaignSteps().addDefaultTextCampaign(CLIENT_LOGIN1);
        Money accountAmountBefore = api.userSteps.financeSteps().getAccountAmount(account.getAccountID());
        CampaignGetItem campaignTo =
                api.userSteps.campaignSteps().getCampaign(CLIENT_LOGIN1, campaignIDTo);
        CampaignGetItem campaignToElse =
                api.userSteps.campaignSteps().getCampaign(CLIENT_LOGIN1, campaignIDToElse);
        TransferMoneyInfoMap transferMoneyInfoMap = new TransferMoneyInfoMap(api.type())
                .withFromCampaigns(new PayCampElementMap(api.type())
                        .withCampaignID(accountFrom)
                        .withSum(sumForTransfer.multiply(2L))
                        .withCurrency(Currency.RUB))
                .withToCampaigns(new PayCampElementMap(api.type())
                                .withCampaignID(campaignIDTo)
                                .withSum(sumForTransfer)
                                .withCurrency(Currency.RUB),
                        new PayCampElementMap(api.type())
                                .withCampaignID(campaignIDToElse)
                                .withSum(sumForTransfer)
                                .withCurrency(Currency.RUB));
        api.userSteps.financeSteps().transferMoney(transferMoneyInfoMap);

        ConditionFactories.NOTIFY_ORDER2.until(
                api.userSteps.financeSteps().accountAmountChangedOnSum(
                        account.getAccountID(), accountAmountBefore, sumForTransfer.multiply(-2L)));

        ConditionFactories.NOTIFY_ORDER2.until(api.userSteps.campaignSteps()
                .campaignFundsChangedOnFunds(CLIENT_LOGIN1, campaignTo, sumForTransfer));

        ConditionFactories.NOTIFY_ORDER2.until(api.userSteps.campaignSteps()
                .campaignFundsChangedOnFunds(CLIENT_LOGIN1, campaignToElse, sumForTransfer));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("6548")
    public void transferMoneyFromTwoCampaignsOneClientToAccount() {
        log.info("Перевод с двух кампании одного клиента без кошелька на кампанию, приязанную к кошельку");
        long campaignIDFrom =
                api.userSteps.addActiveCampaign(CLIENT_LOGIN1, sumForCreate, Currency.RUB);
        ConditionFactories.NOTIFY_ORDER2.until(
                api.userSteps.campaignSteps().campaignFundsChanged(CLIENT_LOGIN1, campaignIDFrom));

        long campaignIDFromElse =
                api.userSteps.addActiveCampaign(CLIENT_LOGIN1, sumForCreate, Currency.RUB);
        ConditionFactories.NOTIFY_ORDER2.until(
                api.userSteps.campaignSteps().campaignFundsChanged(CLIENT_LOGIN1, campaignIDFromElse));

        CampaignGetItem campaignFrom = api.userSteps.campaignSteps().getCampaign(CLIENT_LOGIN1, campaignIDFrom);
        CampaignGetItem campaignFromElse =
                api.userSteps.campaignSteps().getCampaign(CLIENT_LOGIN1, campaignIDFromElse);

        long accountTo = api.userSteps.campaignSteps().addDefaultTextCampaign(ACCOUNT_CLIENT_LOGIN1);
        Account account = api.userSteps.financeSteps().getAccount(ACCOUNT_CLIENT_LOGIN1);
        Money accountAmountBefore = api.userSteps.financeSteps().getAccountAmount(account.getAccountID());

        TransferMoneyInfoMap transferMoneyInfoMap = new TransferMoneyInfoMap(api.type())
                .withFromCampaigns(new PayCampElementMap(api.type())
                                .withCampaignID(campaignIDFrom)
                                .withSum(sumForTransfer)
                                .withCurrency(Currency.RUB),
                        new PayCampElementMap(api.type())
                                .withCampaignID(campaignIDFromElse)
                                .withSum(sumForTransfer)
                                .withCurrency(Currency.RUB))
                .withToCampaigns(new PayCampElementMap(api.type())
                        .withCampaignID(accountTo)
                        .withSum(sumForTransfer.multiply(2L))
                        .withCurrency(Currency.RUB));
        api.userSteps.financeSteps().transferMoney(transferMoneyInfoMap);

        ConditionFactories.NOTIFY_ORDER2.until(
                api.userSteps.financeSteps().accountAmountChangedOnSum(
                        account.getAccountID(), accountAmountBefore, sumForTransfer.multiply(2L)));

        ConditionFactories.NOTIFY_ORDER2.until(api.userSteps.campaignSteps()
                .campaignFundsChangedOnFunds(CLIENT_LOGIN1, campaignFrom, sumForTransfer.negate()));

        ConditionFactories.NOTIFY_ORDER2.until(api.userSteps.campaignSteps()
                .campaignFundsChangedOnFunds(CLIENT_LOGIN1, campaignFromElse, sumForTransfer.negate()));
    }
}
