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

import java.util.Arrays;

import com.yandex.direct.api.v5.ads.AdFieldEnum;
import com.yandex.direct.api.v5.ads.AdGetItem;
import com.yandex.direct.api.v5.ads.GetResponse;
import org.junit.Before;
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.ads.AdsFeatures;
import ru.yandex.autotests.direct.api.ads.AdsLogins;
import ru.yandex.autotests.direct.utils.tags.TagDictionary;
import ru.yandex.autotests.directapi.apiclient.config.Semaphore;
import ru.yandex.autotests.directapi.model.api5.ads.AdGetItemMap;
import ru.yandex.autotests.directapi.model.api5.ads.AdsSelectionCriteriaMap;
import ru.yandex.autotests.directapi.model.api5.ads.GetRequestMap;
import ru.yandex.autotests.directapi.rules.ApiSteps;
import ru.yandex.autotests.directapi.rules.Trashman;
import ru.yandex.qatools.Tag;
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.hazelcast.SemaphoreRule;

import static org.apache.commons.lang.StringUtils.capitalize;
import static org.hamcrest.Matchers.hasSize;
import static ru.yandex.autotests.directapi.model.api5.general.JavaOrPerlApi5Error.Common.maxIdsInSelectionCriteria;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assertThat;
import static ru.yandex.autotests.irt.testutils.beandiffer.BeanDifferMatcher.beanEquivalent;

/**
 * Created by pavryabov on 28.04.15.
 * https://st.yandex-team.ru/TESTIRT-5331
 */
@Aqua.Test
@Features(AdsFeatures.GET)
@Description("Проверка фильтрации по CampaignIds")
@Issue("https://st.yandex-team.ru/DIRECT-34556")
@Tag(TagDictionary.TRUNK)
public class CampaignIdsTest {

    private static String client = AdsLogins.CLIENT;
    private static String otherClient = AdsLogins.CLIENT_ELSE;

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

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

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

    Long campaignId;
    Long adGroupId;
    Long adId;

    @Before
    public void initTest() {
        api.as(client);
        api.userSteps.clientFakeSteps().fakeClearClientSpentUnits(client);
        campaignId = api.userSteps.campaignSteps().addDefaultTextCampaign(client);
        adGroupId = api.userSteps.adGroupsSteps().addDefaultGroup(campaignId);
        adId = api.userSteps.adsSteps().addDefaultTextAd(adGroupId);
    }

    @Test
    public void getOneCampaignId() {
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(new AdsSelectionCriteriaMap().withCampaignIds(campaignId))
                .withFieldNames(AdFieldEnum.ID, AdFieldEnum.CAMPAIGN_ID));
        assertThat("вернулось правильное объявление", getResponse.getAds(), beanEquivalent(
                Arrays.asList((AdGetItem) new AdGetItemMap().withCampaignId(campaignId).withId(adId).getBean())));
    }

    @Test
    public void getTwoCampaignIds() {
        Long campaignIdElse = api.userSteps.campaignSteps().addDefaultTextCampaign(client);
        Long adGroupIdElse = api.userSteps.adGroupsSteps().addDefaultGroup(campaignIdElse);
        Long adIdElse = api.userSteps.adsSteps().addDefaultTextAd(adGroupIdElse);
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(new AdsSelectionCriteriaMap().withCampaignIds(campaignId, campaignIdElse))
                .withFieldNames(AdFieldEnum.ID, AdFieldEnum.CAMPAIGN_ID));
        assertThat("вернулись правильные объявления", getResponse.getAds(), beanEquivalent(
                Arrays.asList((AdGetItem) new AdGetItemMap().withCampaignId(campaignId).withId(adId).getBean(),
                        (AdGetItem) new AdGetItemMap().withCampaignId(campaignIdElse).withId(adIdElse).getBean())));
    }

    @Test
    public void getOneCampaignIdTwoTimes() {
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(new AdsSelectionCriteriaMap().withCampaignIds(campaignId, campaignId))
                .withFieldNames(AdFieldEnum.ID, AdFieldEnum.CAMPAIGN_ID));
        assertThat("вернулось правильное объявление", getResponse.getAds(), beanEquivalent(
                Arrays.asList((AdGetItem) new AdGetItemMap().withCampaignId(campaignId).withId(adId).getBean())));
    }

    @Test
    public void getWithMaxLengthOfCampaignIds() {
        Long[] campaignIds = new Long[AdsSelectionCriteriaMap.CAMPAIGN_IDS_MAX_LENGTH];
        Arrays.fill(campaignIds, campaignId);
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(new AdsSelectionCriteriaMap().withCampaignIds(campaignIds))
                .withFieldNames(AdFieldEnum.ID, AdFieldEnum.CAMPAIGN_ID));
        assertThat("вернулось правильное объявление", getResponse.getAds(), beanEquivalent(
                Arrays.asList((AdGetItem) new AdGetItemMap().withCampaignId(campaignId).withId(adId).getBean())));
    }

    @Test
    public void getWithOverMaxLengthOfCampaignIds() {
        Long[] campaignIds = new Long[AdsSelectionCriteriaMap.CAMPAIGN_IDS_MAX_LENGTH + 1];
        Arrays.fill(campaignIds, campaignId);
        api.userSteps.adsSteps().expectErrorOnAdsGet(
                new GetRequestMap()
                        .withSelectionCriteria(new AdsSelectionCriteriaMap().withCampaignIds(campaignIds))
                        .withFieldNames(AdFieldEnum.ID),
                maxIdsInSelectionCriteria(
                        capitalize(AdsSelectionCriteriaMap.CAMPAIGN_IDS),
                        AdsSelectionCriteriaMap.CAMPAIGN_IDS_MAX_LENGTH));
    }

    @Test
    public void getNonExistentCampaignId() {
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(new AdsSelectionCriteriaMap().withCampaignIds(campaignId + 10000))
                .withFieldNames(AdFieldEnum.ID));
        assertThat("не вернулось ни одного объявления", getResponse.getAds(), hasSize(0));
    }

    @Test
    public void getZeroCampaignId() {
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(new AdsSelectionCriteriaMap().withCampaignIds(0))
                .withFieldNames(AdFieldEnum.ID));
        assertThat("не вернулось ни одного объявления", getResponse.getAds(), hasSize(0));
    }

    @Test
    public void getNegativeCampaignId() {
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(new AdsSelectionCriteriaMap().withCampaignIds(-campaignId))
                .withFieldNames(AdFieldEnum.ID));
        assertThat("не вернулось ни одного объявления", getResponse.getAds(), hasSize(0));
    }

    @Test
    public void getCampaignIdWithDeletedAd() {
        api.userSteps.adsSteps().adsDelete(adId);
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(new AdsSelectionCriteriaMap().withCampaignIds(campaignId))
                .withFieldNames(AdFieldEnum.ID));
        assertThat("не вернулось ни одного объявления", getResponse.getAds(), hasSize(0));
    }

    @Test
    public void getDeletedCampaignId() {
        ////DIRECT-41575
        api.userSteps.campaignSteps().campaignsDelete(campaignId);
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(new AdsSelectionCriteriaMap().withCampaignIds(campaignId))
                .withFieldNames(AdFieldEnum.ID));
        assertThat("не вернулось ни одного объявления", getResponse.getAds(), hasSize(0));
    }

    @Test
    public void getNotMyCampaign() {
        //DIRECT-41573
        api.as(otherClient);
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(new AdsSelectionCriteriaMap().withCampaignIds(campaignId))
                .withFieldNames(AdFieldEnum.ID));
        assertThat("не вернулось ни одного объявления", getResponse.getAds(), hasSize(0));
    }

    @Test
    public void getCampaignIdWithArchivedAd() {
        api.userSteps.bannersFakeSteps().makeBannersModerated(adId);
        api.userSteps.adsSteps().adsArchive(adId);
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(new AdsSelectionCriteriaMap().withCampaignIds(campaignId))
                .withFieldNames(AdFieldEnum.ID, AdFieldEnum.CAMPAIGN_ID));
        assertThat("вернулось правильное объявление", getResponse.getAds(), beanEquivalent(
                Arrays.asList((AdGetItem) new AdGetItemMap().withCampaignId(campaignId).withId(adId).getBean())));
    }

    @Test
    public void getArchivedCampaignId() {
        api.userSteps.archiveCampaign(campaignId);
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(new AdsSelectionCriteriaMap().withCampaignIds(campaignId))
                .withFieldNames(AdFieldEnum.ID, AdFieldEnum.CAMPAIGN_ID));
        assertThat("вернулось правильное объявление", getResponse.getAds(), beanEquivalent(
                Arrays.asList((AdGetItem) new AdGetItemMap().withCampaignId(campaignId).withId(adId).getBean())));
    }

    @Test
    public void getCampaignIdWithTwoAds() {
        Long adIdElse = api.userSteps.adsSteps().addDefaultTextAd(adGroupId);
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(new AdsSelectionCriteriaMap().withCampaignIds(campaignId))
                .withFieldNames(AdFieldEnum.ID, AdFieldEnum.CAMPAIGN_ID));
        assertThat("вернулись правильные объявления", getResponse.getAds(), beanEquivalent(
                Arrays.asList((AdGetItem) new AdGetItemMap().withCampaignId(campaignId).withId(adId).getBean(),
                        (AdGetItem) new AdGetItemMap().withCampaignId(campaignId).withId(adIdElse).getBean())));
    }
}
