package ru.yandex.autotests.direct.api.bids.setauto;

import java.math.BigDecimal;

import com.yandex.direct.api.v5.general.PositionEnum;
import com.yandex.direct.api.v5.general.ScopeEnum;
import org.junit.Before;
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.api.bids.BidsFeatures;
import ru.yandex.autotests.direct.api.bids.BidsLogins;
import ru.yandex.autotests.direct.db.models.jooq.ppc.tables.records.BidsRecord;
import ru.yandex.autotests.direct.utils.money.Currency;
import ru.yandex.autotests.direct.utils.money.MoneyCurrency;
import ru.yandex.autotests.direct.utils.money.MoneyFormat;
import ru.yandex.autotests.directapi.apiclient.config.Semaphore;
import ru.yandex.autotests.directapi.model.api5.bids.BidExpectedResult;
import ru.yandex.autotests.directapi.model.api5.bids.BidSetAutoItemMap;
import ru.yandex.autotests.directapi.model.api5.bids.SetAutoRequestMap;
import ru.yandex.autotests.directapi.rules.ApiSteps;
import ru.yandex.autotests.directapi.rules.Trashman;
import ru.yandex.autotests.irt.testutils.beandiffer2.comparestrategy.defaultcomparestrategy.DefaultCompareStrategies;
import ru.yandex.qatools.allure.annotations.Description;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Issue;
import ru.yandex.qatools.allure.annotations.Step;
import ru.yandex.qatools.hazelcast.SemaphoreRule;

import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.comparesEqualTo;
import static org.hamcrest.core.IsNot.not;
import static ru.yandex.autotests.direct.db.utils.JooqRecordDifferMatcher.recordDiffer;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assertThat;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assumeThat;

/**
 * Created by pavryabov on 07.07.16.
 * https://st.yandex-team.ru/TESTIRT-9701
 */
@Aqua.Test
@Features(BidsFeatures.SET_AUTO)
@Issue("https://st.yandex-team.ru/DIRECT-55594")
@Description("Обновление ставок у двух разных объектов в одном запросе (объекты из одной кампании)")
public class SetAutoSeveralObjectsFromOneCampaignTest {

    private static final String CLIENT = BidsLogins.BIDS_CLIENT;

    private static final String KEYWORD = "мониторы";

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

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

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

    private Long adGroupId1;
    private Long adGroupId2;
    private Long keywordId1;
    private Long keywordId2;
    private static int shard;

    @BeforeClass
    public static void getShard() {
        shard = api.userSteps.clientFakeSteps().getUserShard(CLIENT);

    }

    @Before
    @Step("Подготовка данных для теста")
    public void prepareData() {
        api.userSteps.clientFakeSteps().fakeClearClientSpentUnits(BidsLogins.BIDS_CLIENT);
        Long campaignId = api.userSteps.campaignSteps().addDefaultTextCampaign();
        adGroupId1 = api.userSteps.adGroupsSteps().addDefaultGroup(campaignId);
        Long adId1 = api.userSteps.adsSteps().addDefaultTextAd(adGroupId1);
        keywordId1 = api.userSteps.keywordsSteps().addKeyword(adGroupId1, KEYWORD);
        adGroupId2 = api.userSteps.adGroupsSteps().addDefaultGroup(campaignId);
        Long adId2 = api.userSteps.adsSteps().addDefaultTextAd(adGroupId2);
        keywordId2 = api.userSteps.keywordsSteps().addKeyword(adGroupId2, KEYWORD);
        api.userSteps.bannersFakeSteps().makeBannerActive(adId1, adId2);
        BidsRecord bids = api.userSteps.getDirectJooqDbSteps().useShard(shard).bidsSteps().getBidById(keywordId1);
        BidsRecord expectedBids = new BidsRecord()
                .setCid(campaignId)
                .setPid(adGroupId1)
                .setId(keywordId1)
                .setPrice(new BigDecimal(MoneyCurrency.get(Currency.RUB).getMinPrice().stringValue(MoneyFormat.TWO_DIGITS_POINT)))
                .setPriceContext(new BigDecimal(MoneyCurrency.get(Currency.RUB).getMinPrice().stringValue(MoneyFormat.TWO_DIGITS_POINT)));
        assumeThat("первая фраза создалась с минимальными ставками", bids,
                recordDiffer(expectedBids).useCompareStrategy(DefaultCompareStrategies.onlyExpectedFields()));
        bids = api.userSteps.getDirectJooqDbSteps().bidsSteps().getBidById(keywordId2);
        expectedBids.setCid(campaignId);
        expectedBids.setPid(adGroupId2);
        expectedBids.setId(keywordId2);
        assumeThat("вторая фраза создалась с минимальными ставками", bids,
                recordDiffer(expectedBids).useCompareStrategy(DefaultCompareStrategies.onlyExpectedFields()));

    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("1541")
    public void setAutoWithTwoAdGroups() {
        api.userSteps.bidsSteps().shouldGetBidResultOnSetAuto(
                new SetAutoRequestMap().withBids(
                        new BidSetAutoItemMap()
                                .withAdGroupId(adGroupId1)
                                .withPosition(PositionEnum.PREMIUMBLOCK)
                                .withContextCoverage(100)
                                .withScope(ScopeEnum.SEARCH, ScopeEnum.NETWORK),
                        new BidSetAutoItemMap()
                                .withAdGroupId(adGroupId2)
                                .withPosition(PositionEnum.PREMIUMFIRST)
                                .withContextCoverage(100)
                                .withScope(ScopeEnum.SEARCH, ScopeEnum.NETWORK)
                ),
                BidExpectedResult.successWithAdGroupId(),
                BidExpectedResult.successWithAdGroupId()
        );

        BidsRecord bids1 = api.userSteps.getDirectJooqDbSteps().useShard(shard).bidsSteps().getBidById(keywordId1);
        assertThat("у первой фразы обновилась ставка на поиске", bids1.getPrice(),
                not(comparesEqualTo(MoneyCurrency.get(Currency.RUB).getMinPrice().bigDecimalValue())));
        assertThat("у первой фразы обновилась ставка на сети", bids1.getPriceContext(),
                not(comparesEqualTo(MoneyCurrency.get(Currency.RUB).getMinPrice().bigDecimalValue())));
        BidsRecord bids2 = api.userSteps.getDirectJooqDbSteps().bidsSteps().getBidById(keywordId2);
        assertThat("у второй фразы обновилась ставка на поиске",
                bids2.getPrice(), allOf(
                        not(comparesEqualTo(MoneyCurrency.get(Currency.RUB).getMinPrice().bigDecimalValue())),
                        not(comparesEqualTo(bids1.getPrice()))
                ));
        assertThat("у второй фразы обновилась ставка на сети",
                bids2.getPrice(), allOf(
                        not(comparesEqualTo(MoneyCurrency.get(Currency.RUB).getMinPrice().bigDecimalValue())),
                        not(comparesEqualTo(bids1.getPriceContext()))
                ));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("1542")
    public void setAutoWithTwoKeywords() {
        api.userSteps.bidsSteps().shouldGetBidResultOnSetAuto(
                new SetAutoRequestMap().withBids(
                        new BidSetAutoItemMap()
                                .withKeywordId(keywordId1)
                                .withPosition(PositionEnum.PREMIUMBLOCK)
                                .withContextCoverage(100)
                                .withScope(ScopeEnum.SEARCH, ScopeEnum.NETWORK),
                        new BidSetAutoItemMap()
                                .withKeywordId(keywordId2)
                                .withPosition(PositionEnum.PREMIUMFIRST)
                                .withContextCoverage(100)
                                .withScope(ScopeEnum.SEARCH, ScopeEnum.NETWORK)
                ),
                BidExpectedResult.successWithKeywordId(),
                BidExpectedResult.successWithKeywordId()
        );

        BidsRecord bids1 = api.userSteps.getDirectJooqDbSteps().useShard(shard).bidsSteps().getBidById(keywordId1);
        assertThat("у первой фразы обновилась ставка на поиске", bids1.getPrice(),
                not(comparesEqualTo(MoneyCurrency.get(Currency.RUB).getMinPrice().bigDecimalValue())));
        assertThat("у первой фразы обновилась ставка на сети", bids1.getPriceContext(),
                not(comparesEqualTo(MoneyCurrency.get(Currency.RUB).getMinPrice().bigDecimalValue())));
        BidsRecord bids2 = api.userSteps.getDirectJooqDbSteps().bidsSteps().getBidById(keywordId2);
        assertThat("у второй фразы обновилась ставка на поиске",
                bids2.getPrice(), allOf(
                        not(comparesEqualTo(MoneyCurrency.get(Currency.RUB).getMinPrice().bigDecimalValue())),
                        not(comparesEqualTo(bids1.getPrice()))
                ));
        assertThat("у второй фразы обновилась ставка на сети",
                bids2.getPrice(), allOf(
                        not(comparesEqualTo(MoneyCurrency.get(Currency.RUB).getMinPrice().bigDecimalValue())),
                        not(comparesEqualTo(bids1.getPriceContext()))
                ));
    }
}
