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

import java.math.RoundingMode;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.yandex.direct.api.v5.campaigns.TextCampaignSearchStrategyTypeEnum;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;

import ru.yandex.aqua.annotations.project.Aqua;
import ru.yandex.autotests.direct.db.models.jooq.ppc.tables.records.CampaignsRecord;
import ru.yandex.autotests.direct.db.models.jooq.ppc.tables.records.StrategiesRecord;
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.darkside.Logins;
import ru.yandex.autotests.directapi.darkside.connection.Semaphore;
import ru.yandex.autotests.directapi.darkside.model.RunBsTransportScriptResponse;
import ru.yandex.autotests.directapi.darkside.model.bslogs.clientdata.Campaign;
import ru.yandex.autotests.directapi.model.api5.campaigns.CampaignUpdateItemMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.StrategyAverageCpaMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.TextCampaignNetworkStrategyMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.TextCampaignSearchStrategyMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.TextCampaignStrategyMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.TextCampaignUpdateItemMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.UpdateRequestMap;
import ru.yandex.autotests.directapi.rules.ApiSteps;
import ru.yandex.autotests.directintapi.bstransport.FeatureNames;
import ru.yandex.autotests.directintapi.bstransport.StoriesNames;
import ru.yandex.autotests.irt.testutils.beandiffer2.comparestrategy.defaultcomparestrategy.DefaultCompareStrategies;
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.notNullValue;
import static ru.yandex.autotests.directapi.model.campaigns.MetrikaGoals.getGoalForLogin;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assertThat;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assumeThat;
import static ru.yandex.autotests.irt.testutils.beandiffer2.BeanDifferMatcher.beanDiffer;

/**
 * Created by buhter on 23/09/15.
 * https://st.yandex-team.ru/TESTIRT-7220
 * https://st.yandex-team.ru/TESTIRT-7642
 */
@Aqua.Test
@Tag(TagDictionary.RELEASE)
@Tag(TagDictionary.TRUNK)
@Issue("https://st.yandex-team.ru/DIRECT-46309")
@Title("Транспорт: проверка округления при отправке параметров автобюджета(AvgCpa, AvgBid, WeekLimit)")
@Stories(StoriesNames.CAMPAIGN_PARAMS_PRECISION)
@Features({FeatureNames.CAMPAIGNS, FeatureNames.NOT_FOR_FULL_EXPORT})
public class BsTransportAutobudgetParamsPrecisionTest {

    private static final String LOGIN = Logins.LOGIN_TRANSPORT;

    @ClassRule
    public static ApiSteps api = new ApiSteps().as(LOGIN);

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

    private static final Double AVG_CPA = 4.0192837465;
    private static final Double AVG_BID = 4.1029384756;
    private static final Double AVG_WEEK_LIMIT = 400.0123456789;

    private static Campaign campaign;

    @BeforeClass
    public static void before() {
        long goalId = getGoalForLogin(LOGIN);
        int shard = api.userSteps.clientFakeSteps().getUserShard(LOGIN);
        TextCampaignSearchStrategyMap searchStrategy =
                new TextCampaignSearchStrategyMap()
                        .withBiddingStrategyType(TextCampaignSearchStrategyTypeEnum.AVERAGE_CPA)
                        .withAverageCpa(new StrategyAverageCpaMap()
                                .withGoalId(goalId)
                                .withAverageCpa(Money.valueOf(AVG_CPA).bidLong().longValue()));
        TextCampaignNetworkStrategyMap networkStrategy =
                new TextCampaignNetworkStrategyMap().defaultNetworkDefault();

        Long cid = api.userSteps.campaignSteps().addDefaultTextCampaign();
        api.userSteps.campaignFakeSteps().makeNewCampaignReadyForSendingToBS(cid);
        api.userSteps.getDirectJooqDbSteps().useShard(shard).campaignsSteps()
                .addCampMetrikaGoals(cid, goalId, 100L, 100L);
        api.userSteps.campaignSteps().campaignsUpdate(new UpdateRequestMap()
                .withCampaigns(new CampaignUpdateItemMap()
                        .withId(cid)
                        .withTextCampaign(new TextCampaignUpdateItemMap()
                                .withBiddingStrategy(new TextCampaignStrategyMap()
                                        .withSearch(searchStrategy)
                                        .withNetwork(networkStrategy)))));
        Long pid = api.userSteps.adGroupsSteps().addDefaultGroup(cid);
        Long bid = api.userSteps.adsSteps().addDefaultTextAd(pid);
        Long keywordId = api.userSteps.keywordsSteps().addDefaultKeyword(pid);
        api.userSteps.groupFakeSteps().makeGroupFullyModerated(pid);
        api.userSteps.bannersFakeSteps().makeBannerFullyModerated(bid);
        api.userSteps.phrasesFakeSteps().makeKeywordModerated(keywordId);
        CampaignsRecord campaignsRecord =
                api.userSteps.getDirectJooqDbSteps().useShard(shard).campaignsSteps().getCampaignById(cid);
        JsonObject strategy = campaignsRecord.getStrategyData().getAsJsonObject();
        strategy.addProperty("avg_cpa", AVG_CPA);
        strategy.addProperty("avg_bid", AVG_BID);
        strategy.addProperty("sum", AVG_WEEK_LIMIT);
        campaignsRecord.setStrategyData(strategy);
        api.userSteps.getDirectJooqDbSteps().useShard(shard).campaignsSteps().updateCampaigns(campaignsRecord);

        Long strategyId =
                api.userSteps.getDirectJooqDbSteps().useShard(shard).campaignsSteps().getCampaignById(cid).getStrategyId();
        if (strategyId != 0) {
            StrategiesRecord strategiesRecord =
                    api.userSteps.getDirectJooqDbSteps().useShard(shard).strategiesSteps().getStrategiesRecord(strategyId);
            JsonElement strategyData = new Gson().fromJson(strategiesRecord.getStrategyData(), JsonElement.class);
            strategyData.getAsJsonObject().addProperty("avg_cpa", AVG_CPA);
            strategyData.getAsJsonObject().addProperty("avg_bid", AVG_BID);
            strategyData.getAsJsonObject().addProperty("sum", AVG_WEEK_LIMIT);
            strategiesRecord.setStrategyData(strategyData.toString());
            api.userSteps.getDirectJooqDbSteps().useShard(shard).strategiesSteps().updateStrategies(strategiesRecord);
        }

        RunBsTransportScriptResponse resp =
                api.userSteps.getDarkSideSteps().getTransportSteps().sendNewCampaign(shard, cid);
        campaign = api.userSteps.getDarkSideSteps().getTransportSteps().getClientDataRequestCampaign(resp, cid);
        assumeThat("в БК отправлена кампания", campaign, notNullValue());
    }

    @Test
    @Title("Округление параметров автобюджета")
    public void testTransportOfAutoBudgetParams() {
        Campaign expected = new Campaign();
        expected.setAutoBudgetAvgBid(Money.valueOf(AVG_BID, Currency.RUB).convert(Currency.YND_FIXED)
                .setScale(Campaign.PRECISION_DIGIT_COUNT_YNDX_FIXED, RoundingMode.HALF_UP).floatValue());
        expected.setAutoBudgetAvgBidCur(Money.valueOf(AVG_BID, Currency.RUB).addVAT()
                .setScale(Campaign.PRECISION_DIGIT_COUNT_RUB, RoundingMode.HALF_UP).floatValue());
        expected.setAutoBudgetWeekLimit(Money.valueOf(AVG_WEEK_LIMIT, Currency.RUB).convert(Currency.YND_FIXED)
                .setScale(Campaign.PRECISION_DIGIT_COUNT_YNDX_FIXED, RoundingMode.HALF_UP).floatValue());
        expected.setAutoBudgetWeekLimitCur(Money.valueOf(AVG_WEEK_LIMIT, Currency.RUB).addVAT()
                .setScale(Campaign.PRECISION_DIGIT_COUNT_RUB, RoundingMode.HALF_UP).floatValue());
        expected.setAutoBudgetAvgCPA(Money.valueOf(AVG_CPA, Currency.RUB).convert(Currency.YND_FIXED)
                .setScale(Campaign.PRECISION_DIGIT_COUNT_YNDX_FIXED, RoundingMode.HALF_UP).floatValue());
        expected.setAutoBudgetAvgCPACur(Money.valueOf(AVG_CPA, Currency.RUB).addVAT()
                .setScale(Campaign.PRECISION_DIGIT_COUNT_RUB, RoundingMode.HALF_UP).floatValue());
        expected.setNdsHistory(null);
        expected.setDiscountHistory(null);
        assertThat("при отправке в БК значения параметров автобюджета ушли округленными",
                campaign, beanDiffer(expected).useCompareStrategy(DefaultCompareStrategies.onlyExpectedFields()));
    }

}
