package ru.yandex.autotests.directintapi.bstransport.main.campaign.parameters.daybudget;

import org.junit.BeforeClass;
import org.junit.ClassRule;
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.tags.TagDictionary;
import ru.yandex.autotests.directapi.common.api45.CreateNewSubclientResponse;
import ru.yandex.autotests.directapi.darkside.connection.Semaphore;
import ru.yandex.autotests.directapi.darkside.model.RunBsTransportScriptResponse;
import ru.yandex.autotests.directapi.darkside.model.bslogs.SpendMode;
import ru.yandex.autotests.directapi.darkside.model.bslogs.clientdata.Campaign;
import ru.yandex.autotests.directapi.model.api5.campaigns.CampaignAddItemMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.DailyBudgetMap;
import ru.yandex.autotests.directapi.model.finances.sharedaccount.AccountDayBudgetInfoMap;
import ru.yandex.autotests.directapi.model.finances.sharedaccount.AccountMap;
import ru.yandex.autotests.directapi.rules.ApiSteps;
import ru.yandex.autotests.directintapi.bstransport.FeatureNames;
import ru.yandex.autotests.directintapi.bstransport.StoriesNames;
import ru.yandex.qatools.Tag;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Issue;
import ru.yandex.qatools.allure.annotations.Stories;
import ru.yandex.qatools.allure.annotations.Title;
import ru.yandex.qatools.hazelcast.SemaphoreRule;

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;
import static ru.yandex.autotests.directapi.darkside.Logins.LOGIN_AGENCY;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assertThat;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assumeThat;

@Aqua.Test
@Tag(TagDictionary.TRUNK)
@Tag(TagDictionary.RELEASE)
@Issue("https://st.yandex-team.ru/DIRECT-64428")
@Title("Транспорт: проверка отправки размера дневного бюджета и режима трат для кампании под кошельком (также с ограничениями по дневному бюджету)")
@Stories(StoriesNames.CAMPAIGN_PARAMS_DAYBUDGET)
@Features({FeatureNames.CAMPAIGNS, FeatureNames.NOT_FOR_FULL_EXPORT})
public class BsTransportOfDayLimitAndRegularSpentUnderWalletForDayBudgetTest {

    private static final Money CAMP_DAY_BUDGET_AMOUNT = Money.valueOf(350f);
    private static final SpendMode CAMP_SPEND_MODE = SpendMode.STRETCHED;
    private static final Money WALLET_DAY_BUDGET_AMOUNT = Money.valueOf(1050f);
    private static final SpendMode WALLET_SPEND_MODE = SpendMode.DEFAULT;

    private static final String AGENCY_RUB = LOGIN_AGENCY;
    private static final Currency currency = Currency.RUB;

    private static int shard;
    private static String login;
    private static Long cid;
    private static Long walletCid;
    private static Campaign wallet;
    private static Campaign campaign;

    @ClassRule
    public static ApiSteps api = new ApiSteps();

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

    @BeforeClass
    public static void beforeClass() {
        // инициализируем степы для заданного агентства
        api.as(AGENCY_RUB);
        // создаем клиента с кампанией
        api.userSteps.clientFakeSteps().enableToCreateSubClients(AGENCY_RUB);
        CreateNewSubclientResponse createNewSubclientResponse = api.userSteps.clientSteps()
                .createNewAgencySubClient("transport-wallet-", AGENCY_RUB, currency);
        login = createNewSubclientResponse.getLogin();
        shard = api.userSteps.clientFakeSteps().getUserShard(login);

        cid = api.userSteps.campaignSteps().addCampaign(new CampaignAddItemMap()
                        .defaultCampaignAddItem()
                        .withDailyBudget(new DailyBudgetMap()
                                .withAmount(CAMP_DAY_BUDGET_AMOUNT.bidLong().longValue())
                                .withMode(CAMP_SPEND_MODE.api5SpendMode()))
                        .withDefaultTextCampaign(),
                login);
        api.userSteps.campaignFakeSteps().makeNewCampaignReadyForSendingToBS(cid);

        // устанавливаем на кошелек свои ограничения общего счета
        walletCid = api.userSteps.getDirectJooqDbSteps().useShard(shard).campaignsSteps().getCampaignById(cid)
                .getWalletCid();
        AccountMap account = new AccountMap(api.type())
                .withAccountID(walletCid.intValue())
                .withAccountDayBudget(new AccountDayBudgetInfoMap(api.type())
                        .withSpendMode(WALLET_SPEND_MODE.apiSpendMode())
                        .withAmount(WALLET_DAY_BUDGET_AMOUNT.floatValue()));
        api.userSteps.financeSteps().update(account);
        api.userSteps.campaignFakeSteps().makeNewCampaignReadyForSendingToBS(walletCid);

        // отправляем кампанию-кошелек
        RunBsTransportScriptResponse resp =
                api.userSteps.getDarkSideSteps().getTransportSteps().sendSyncedCampaign(shard, walletCid);
        wallet = api.userSteps.getDarkSideSteps().getTransportSteps().getClientDataRequestCampaign(resp, walletCid);
        assumeThat("кампания-кошелек успешно отправлена в БК", wallet, notNullValue());

        // отправляем кампанию под кошельком
        resp = api.userSteps.getDarkSideSteps().getTransportSteps().sendNewCampaign(shard, cid);
        campaign = api.userSteps.getDarkSideSteps().getTransportSteps().getClientDataRequestCampaign(resp, cid);
        assumeThat("кампания под кошельком успешно отправлена в БК", wallet, notNullValue());
    }

    @Test
    @Title("Отправка в БК размера дневного бюджета на кошелек")
    public void testTransportOfDayLimitForDayBudgetOnWallet() {
        Float actualDayLimit = wallet.getAutoBudgetDayLimitMoneyCur();
        Float expectedDayLimit = WALLET_DAY_BUDGET_AMOUNT.addVAT(currency).floatValue();
        assertThat("отправленный в БК размер дневного бюджета соответствует ожидаемому",
                actualDayLimit,
                equalTo(expectedDayLimit));
    }

    @Test
    @Title("Отправка в БК режира распределения дневного бюджета на кошелек (AutoBudgetRegularSpent)")
    public void testTransportOfAutoBudgetRegularSpentForDayBudgetOnWallet() {
        assertThat("отправленный в БК режим распределения дневного бюджета соответствует ожидаемому",
                wallet.getAutoBudgetRegularSpent(),
                equalTo(WALLET_SPEND_MODE.transportRegularSpent()));
    }

    @Test
    @Title("Отправка в БК размера дневного бюджета на кампанию под кошельком")
    public void testTransportOfDayLimitForDayBudgetOnCampaignUnderWallet() {
        Float actualDayLimit = campaign.getAutoBudgetDayLimitMoneyCur();
        Float expectedDayLimit = CAMP_DAY_BUDGET_AMOUNT.addVAT(currency).floatValue();
        assertThat("отправленный в БК размер дневного бюджета соответствует ожидаемому",
                actualDayLimit,
                equalTo(expectedDayLimit));
    }

    @Test
    @Title("Отправка в БК режима распределения дневного бюджета на кампанию под кошельком (AutoBudgetRegularSpent)")
    public void testTransportOfAutoBudgetRegularSpentForDayBudgetOnCampaignUnderWallet() {
        assertThat("отправленный в БК режим распределения дневного бюджета соответствует ожидаемому",
                campaign.getAutoBudgetRegularSpent(),
                equalTo(CAMP_SPEND_MODE.transportRegularSpent()));
    }
}
