package ru.yandex.autotests.direct.api.keywordbids.get;

import java.util.Arrays;
import java.util.Collection;

import com.yandex.direct.api.v5.general.PriorityEnum;
import com.yandex.direct.api.v5.general.ServingStatusEnum;
import com.yandex.direct.api.v5.keywordbids.GetResponse;
import com.yandex.direct.api.v5.keywordbids.KeywordBidFieldEnum;
import com.yandex.direct.api.v5.keywordbids.KeywordBidNetworkFieldEnum;
import com.yandex.direct.api.v5.keywordbids.KeywordBidSearchFieldEnum;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import ru.yandex.qatools.allure.annotations.TestCaseId;

import ru.yandex.aqua.annotations.project.Aqua;
import ru.yandex.autotests.direct.api.bids.BidsKeywords;
import ru.yandex.autotests.direct.api.bids.BidsLogins;
import ru.yandex.autotests.direct.api.keywordbids.KeywordBidsFeatures;
import ru.yandex.autotests.direct.utils.money.Currency;
import ru.yandex.autotests.direct.utils.money.MoneyCurrency;
import ru.yandex.autotests.directapi.apiclient.config.ProtocolType;
import ru.yandex.autotests.directapi.apiclient.config.Semaphore;
import ru.yandex.autotests.directapi.apiclient.errors.Api5Error;
import ru.yandex.autotests.directapi.apiclient.errors.Api5ErrorDetailsJava;
import ru.yandex.autotests.directapi.model.api5.keywordbids.GetRequestMap;
import ru.yandex.autotests.directapi.model.api5.keywordbids.KeywordBidsGetItemMap;
import ru.yandex.autotests.directapi.model.api5.keywordbids.KeywordBidsSelectionCriteriaMap;
import ru.yandex.autotests.directapi.model.api5.keywords.KeywordAddMap;
import ru.yandex.autotests.directapi.rules.ApiSteps;
import ru.yandex.autotests.directapi.rules.Trashman;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.hazelcast.SemaphoreRule;

import static org.apache.commons.lang.StringUtils.capitalize;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.core.IsEqual.equalTo;
import static ru.yandex.autotests.directapi.matchers.beandiffer2.BeanDifferMatcherV5.beanDifferV5;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assertThat;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assumeThat;

@Aqua.Test
@Features(KeywordBidsFeatures.GET)
@RunWith(Parameterized.class)
public class KeywordBidsGetTest {

    private static final String CLIENT_LOGIN = BidsLogins.BIDS_CLIENT;
    private static final String KEYWORD = BidsKeywords.WITH_POKAZOMETER_DATA;
    private static final Long DEFAULT_BID = MoneyCurrency.get(Currency.RUB).getLongMinPrice().longValue();

    @ClassRule
    public static ApiSteps api = new ApiSteps().as(CLIENT_LOGIN);
    @ClassRule
    public static SemaphoreRule semaphore = Semaphore.getSemaphore();

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

    @Parameterized.Parameter(0)
    public String testName;

    @Parameterized.Parameter(1)
    public Long campaignId;

    @Parameterized.Parameter(2)
    public Long adGroupId;

    @Parameterized.Parameter(3)
    public Long keywordId;

    @Parameterized.Parameters(name = "{0}, campaignId = {1}, adGroupId = {2}, keywordId = {3}")
    public static Collection testData() {
        api.userSteps.clientFakeSteps().enableAPI(CLIENT_LOGIN);

        Object[][] data = new Object[3][4];

        Long textCampaignId = api.userSteps.campaignSteps().addDefaultTextCampaignWithIndependentStrategies();
        Long textAdGroupId = api.userSteps.adGroupsSteps().addDefaultGroup(textCampaignId);
        api.userSteps.adsSteps().addDefaultTextAd(textAdGroupId);
        Long textKeywordId = api.userSteps.keywordsSteps().keywordsAdd(new KeywordAddMap()
                .withAdGroupId(textAdGroupId).withBid(DEFAULT_BID).withKeyword(KEYWORD)).get(0);

        data[0][0] = "Text Campaign";
        data[0][1] = textCampaignId;
        data[0][2] = textAdGroupId;
        data[0][3] = textKeywordId;

        Long textDeviceTargetingCampaignId = 
                api.userSteps.campaignSteps().addDefaultTextCampaignWithIndependentStrategies();
        api.userSteps.getDirectJooqDbSteps().useShardForLogin(CLIENT_LOGIN).campaignsSteps().addDeviceTargeting(
                textDeviceTargetingCampaignId, "iphone"
        );
        Long textDeviceTargetingAdGroupId = api.userSteps.adGroupsSteps().addDefaultGroup(
                textDeviceTargetingCampaignId
        );
        api.userSteps.adsSteps().addDefaultTextAd(textDeviceTargetingAdGroupId);
        Long textDeviceTargetingKeywordId = api.userSteps.keywordsSteps().keywordsAdd(new KeywordAddMap()
                .withAdGroupId(textDeviceTargetingAdGroupId).withBid(DEFAULT_BID).withKeyword(KEYWORD)).get(0);

        data[1][0] = "Text Campaign with DeviceTargeting";
        data[1][1] = textDeviceTargetingCampaignId;
        data[1][2] = textDeviceTargetingAdGroupId;
        data[1][3] = textDeviceTargetingKeywordId;

        Long mobileContentCampaignId = api.userSteps.campaignSteps().addDefaultMobileAppCampaign();
        Long mobileContentAdGroupId = api.userSteps.adGroupsSteps().addDefaultMobileGroup(mobileContentCampaignId);
        api.userSteps.adsSteps().addDefaultMobileAppAd(mobileContentAdGroupId);
        Long mobileContentKeywordId = api.userSteps.keywordsSteps().keywordsAdd(new KeywordAddMap()
                .withAdGroupId(mobileContentAdGroupId).withBid(DEFAULT_BID).withKeyword(KEYWORD)).get(0);

        data[2][0] = "MobileApp Campaign";
        data[2][1] = mobileContentCampaignId;
        data[2][2] = mobileContentAdGroupId;
        data[2][3] = mobileContentKeywordId;

        return Arrays.asList(data);
    }

    @Test
    @TestCaseId("2820")
    public void callKeywordBidsGet_smokeTest() {
        GetResponse getResponse = api.protocol(ProtocolType.SOAP).userSteps.keywordBidsSteps().keywordBidsGet(
                new GetRequestMap()
                        .withSelectionCriteria(new KeywordBidsSelectionCriteriaMap().withKeywordIds(keywordId))
                        .withFieldNames(KeywordBidFieldEnum.KEYWORD_ID)
                        .withSearchFieldNames(KeywordBidSearchFieldEnum.BID),
                CLIENT_LOGIN
        );
        assumeThat("вернулся один элемент KeywordBids", getResponse.getKeywordBids(), hasSize(1));
        assertThat("вернулось корректное Bid", getResponse.getKeywordBids().get(0).getSearch().getBid(),
                equalTo(DEFAULT_BID));
    }

    @Test
    @TestCaseId("2824")
    public void callKeywordBidsGet_withKeywordBidFieldsTest() {
        GetResponse getResponse = api.protocol(ProtocolType.SOAP).userSteps.keywordBidsSteps().keywordBidsGet(
                new GetRequestMap()
                        .withSelectionCriteria(new KeywordBidsSelectionCriteriaMap().withKeywordIds(keywordId))
                        .withFieldNames(KeywordBidFieldEnum.class.getEnumConstants()),
                CLIENT_LOGIN
        );
        assumeThat("вернулся один элемент KeywordBids", getResponse.getKeywordBids(), hasSize(1));
        assertThat("значения полей в ответе соответствуют ожидаемым",
                getResponse.getKeywordBids().get(0),
                beanDifferV5(new KeywordBidsGetItemMap()
                        .withKeywordId(keywordId)
                        .withAdGroupId(adGroupId)
                        .withCampaignId(campaignId)
                        .withStrategyPriority(PriorityEnum.NORMAL)
                        .withServingStatus(ServingStatusEnum.ELIGIBLE)
                        .getBean()));
    }

    @Test
    @TestCaseId("2823")
    public void callKeywordBidsGet_withAuctionBidsTest() {
        GetResponse getResponse = api.protocol(ProtocolType.SOAP).userSteps.keywordBidsSteps().keywordBidsGet(
                new GetRequestMap()
                        .withSelectionCriteria(new KeywordBidsSelectionCriteriaMap().withKeywordIds(keywordId))
                        .withFieldNames(KeywordBidFieldEnum.KEYWORD_ID)
                        .withSearchFieldNames(KeywordBidSearchFieldEnum.AUCTION_BIDS),
                CLIENT_LOGIN
        );
        assumeThat("вернулся один элемент KeywordBids", getResponse.getKeywordBids(), hasSize(1));
        assertThat("вернулась структура Search.AuctionBids.AuctionBidItems",
                getResponse.getKeywordBids().get(0).getSearch().getAuctionBids().getValue().getAuctionBidItems()
                        .isEmpty(),
                equalTo(false));
    }

    @Test
    @TestCaseId("2821")
    public void callKeywordBidsGet_withCoverageTest() {
        GetResponse getResponse = api.protocol(ProtocolType.SOAP).userSteps.keywordBidsSteps().keywordBidsGet(
                new GetRequestMap()
                        .withSelectionCriteria(new KeywordBidsSelectionCriteriaMap().withKeywordIds(keywordId))
                        .withFieldNames(KeywordBidFieldEnum.KEYWORD_ID)
                        .withNetworkFieldNames(KeywordBidNetworkFieldEnum.COVERAGE),
                CLIENT_LOGIN
        );
        assumeThat("вернулся один элемент KeywordBids", getResponse.getKeywordBids(), hasSize(1));
        assertThat("вернулась структура Network.Coverage.CoverageItems",
                getResponse.getKeywordBids().get(0).getNetwork().getCoverage().getValue().getCoverageItems().isEmpty(),
                equalTo(false));
    }

    @Test
    @TestCaseId("2822")
    public void callKeywordBidsGet_withEmptyFieldNames() {
        api.protocol(ProtocolType.SOAP).userSteps.keywordBidsSteps().shouldGetErrorOnKeywordBidsGet(
                new GetRequestMap()
                        .withSelectionCriteria(new KeywordBidsSelectionCriteriaMap().withKeywordIds(keywordId)),
                CLIENT_LOGIN,
                new Api5Error(8000,
                        Api5ErrorDetailsJava.MISSING_PARAMETER_VALUE,
                        capitalize(GetRequestMap.FIELD_NAMES))
        );
    }
}
