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

import java.util.Arrays;
import java.util.Collections;

import com.yandex.direct.api.v5.ads.AdFieldEnum;
import com.yandex.direct.api.v5.ads.AdGetItem;
import com.yandex.direct.api.v5.ads.AdStatusSelectionEnum;
import com.yandex.direct.api.v5.ads.GetResponse;
import com.yandex.direct.api.v5.general.StatusEnum;
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.ads.AdsFeatures;
import ru.yandex.autotests.direct.api.ads.AdsLogins;
import ru.yandex.autotests.direct.db.models.jooq.ppc.enums.BannersPerformanceStatusmoderate;
import ru.yandex.autotests.direct.db.models.jooq.ppc.enums.BannersStatusmoderate;
import ru.yandex.autotests.direct.db.models.jooq.ppc.enums.BannersStatuspostmoderate;
import ru.yandex.autotests.direct.db.models.jooq.ppc.tables.records.BannersRecord;
import ru.yandex.autotests.direct.db.steps.DirectJooqDbSteps;
import ru.yandex.autotests.directapi.apiclient.config.Semaphore;
import ru.yandex.autotests.directapi.darkside.model.CampaignsType;
import ru.yandex.autotests.directapi.model.User;
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.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.hamcrest.Matchers.hasSize;
import static ru.yandex.autotests.directapi.matchers.beans.version5.BeanDifferMatcherV5.beanDifferV5;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assertThat;

@Aqua.Test
@Features(AdsFeatures.GET)
@Description("Проверка выборки медийных объявлений по статусам")
@Issue("https://st.yandex-team.ru/DIRECT-83722")
public class GetCpmBannerAdByStatusTest {

    private static String CLIENT = AdsLogins.CLIENT43;

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

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

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

    private static Long campaignId;
    private static Long adGroupId;
    private static Long draftAdId, moderationAdId1, moderationAdId2, moderationAdId3, rejectedAdId1, rejectedAdId2,
            rejectedAdId3, acceptedAdId;
    private static Long creativeId;
    private static DirectJooqDbSteps jooqDbSteps;

    @BeforeClass
    public static void initTest() {
        api.userSteps.clientFakeSteps().fakeClearClientSpentUnits(CLIENT);
        campaignId = api.userSteps.campaignSteps().addDefaultTextCampaign();
        api.userSteps.campaignFakeSteps().setType(campaignId, CampaignsType.CPM_BANNER);
        adGroupId = api.userSteps.adGroupsSteps().addDefaultCpmBannerUserProfileAdGroup(campaignId);
        jooqDbSteps = api.userSteps.getDarkSideSteps().getDirectJooqDbSteps().useShardForLogin(CLIENT);
        creativeId = jooqDbSteps.perfCreativesSteps().saveDefaultCanvasCreativesForClient(
                Long.parseLong(User.get(CLIENT).getClientID()));

        draftAdId =
                addAd(BannersStatusmoderate.New, BannersStatuspostmoderate.Yes, BannersPerformanceStatusmoderate.New);
        moderationAdId1 =
                addAd(BannersStatusmoderate.Yes, BannersStatuspostmoderate.Yes, BannersPerformanceStatusmoderate.Sent);
        moderationAdId2 =
                addAd(BannersStatusmoderate.Sent, BannersStatuspostmoderate.No, BannersPerformanceStatusmoderate.Yes);
        moderationAdId3 =
                addAd(BannersStatusmoderate.Sent, BannersStatuspostmoderate.Yes, BannersPerformanceStatusmoderate.Yes);
        rejectedAdId1 =
                addAd(BannersStatusmoderate.Yes, BannersStatuspostmoderate.Yes, BannersPerformanceStatusmoderate.No);
        rejectedAdId2 =
                addAd(BannersStatusmoderate.No, BannersStatuspostmoderate.Yes, BannersPerformanceStatusmoderate.No);
        rejectedAdId3 =
                addAd(BannersStatusmoderate.Sent, BannersStatuspostmoderate.Yes, BannersPerformanceStatusmoderate.No);
        acceptedAdId =
                addAd(BannersStatusmoderate.Yes, BannersStatuspostmoderate.Yes, BannersPerformanceStatusmoderate.Yes);
    }

    private static Long addAd(BannersStatusmoderate bannerStatusmoderate,
            BannersStatuspostmoderate bannerStatuspostmoderate,
            BannersPerformanceStatusmoderate bannersPerformanceStatusmoderate)
    {
        Long adId = api.userSteps.adsSteps().addDefaultCpmBannerAdBuilderAd(adGroupId, creativeId);
        jooqDbSteps.bannersSteps().updateBanners(
                new BannersRecord().setBid(adId).setStatusmoderate(bannerStatusmoderate)
                        .setStatuspostmoderate(bannerStatuspostmoderate)
        );
        jooqDbSteps.bannersPerformanceSteps()
                .setCreativeStatusModerate(campaignId, adGroupId, adId, bannersPerformanceStatusmoderate);
        return adId;
    }

    @Test
    public void getAdsAndCheckStatuses() {
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(new AdsSelectionCriteriaMap()
                        .withIds(
                                draftAdId,
                                moderationAdId1,
                                moderationAdId2,
                                moderationAdId3,
                                rejectedAdId1,
                                rejectedAdId2,
                                rejectedAdId3,
                                acceptedAdId
                        ))

                .withFieldNames(AdFieldEnum.ID, AdFieldEnum.STATUS)
        );
        assertThat("объявления имеют правильный статус модерации", getResponse.getAds(),
                beanDifferV5(
                        Arrays.asList(
                                (AdGetItem) new AdGetItemMap().withId(draftAdId).withStatus(StatusEnum.DRAFT).getBean(),
                                (AdGetItem) new AdGetItemMap().withId(moderationAdId1).withStatus(StatusEnum.MODERATION)
                                        .getBean(),
                                (AdGetItem) new AdGetItemMap().withId(moderationAdId2).withStatus(StatusEnum.MODERATION)
                                        .getBean(),
                                (AdGetItem) new AdGetItemMap().withId(moderationAdId3).withStatus(StatusEnum.MODERATION)
                                        .getBean(),
                                (AdGetItem) new AdGetItemMap().withId(rejectedAdId1).withStatus(StatusEnum.REJECTED)
                                        .getBean(),
                                (AdGetItem) new AdGetItemMap().withId(rejectedAdId2).withStatus(StatusEnum.REJECTED)
                                        .getBean(),
                                (AdGetItem) new AdGetItemMap().withId(rejectedAdId3).withStatus(StatusEnum.REJECTED)
                                        .getBean(),
                                (AdGetItem) new AdGetItemMap().withId(acceptedAdId).withStatus(StatusEnum.ACCEPTED)
                                        .getBean()
                        )
                )
        );
    }

    @Test
    public void getAdsWithDraftStatus() {
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(
                        new AdsSelectionCriteriaMap().withAdGroupIds(adGroupId)
                                .withStatuses(AdStatusSelectionEnum.DRAFT)
                )
                .withFieldNames(AdFieldEnum.ID, AdFieldEnum.STATUS)
        );
        assertThat("вернулись правильные объявления", getResponse.getAds(), beanDifferV5(
                Collections.singletonList((AdGetItem) new AdGetItemMap()
                        .withId(draftAdId)
                        .withStatus(StatusEnum.DRAFT).getBean())));
    }

    @Test
    public void getAdsWithModerationStatus() {
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(
                        new AdsSelectionCriteriaMap().withAdGroupIds(adGroupId)
                                .withStatuses(AdStatusSelectionEnum.MODERATION)
                )
                .withFieldNames(AdFieldEnum.ID, AdFieldEnum.STATUS)
        );
        assertThat("вернулись правильные объявления", getResponse.getAds(),
                beanDifferV5(
                        Arrays.asList(
                                (AdGetItem) new AdGetItemMap()
                                        .withId(moderationAdId1)
                                        .withStatus(StatusEnum.MODERATION).getBean(),
                                (AdGetItem) new AdGetItemMap()
                                        .withId(moderationAdId2)
                                        .withStatus(StatusEnum.MODERATION).getBean(),
                                (AdGetItem) new AdGetItemMap()
                                        .withId(moderationAdId3)
                                        .withStatus(StatusEnum.MODERATION).getBean()
                        )
                )
        );
    }

    @Test
    public void getAdsWithPreacceptedStatus() {
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(
                        new AdsSelectionCriteriaMap().withAdGroupIds(adGroupId)
                                .withStatuses(AdStatusSelectionEnum.PREACCEPTED)
                )
                .withFieldNames(AdFieldEnum.ID, AdFieldEnum.STATUS)
        );
        assertThat("вернулись правильные объявления", getResponse.getAds(), hasSize(0));
    }

    @Test
    public void getAdsWithAcceptedStatus() {
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(
                        new AdsSelectionCriteriaMap().withAdGroupIds(adGroupId)
                                .withStatuses(AdStatusSelectionEnum.ACCEPTED)
                )
                .withFieldNames(AdFieldEnum.ID, AdFieldEnum.STATUS)
        );
        assertThat("вернулись правильные объявления", getResponse.getAds(),
                beanDifferV5(
                        Collections.singletonList(
                                (AdGetItem) new AdGetItemMap()
                                        .withId(acceptedAdId)
                                        .withStatus(StatusEnum.ACCEPTED).getBean()
                        )
                )
        );
    }

    @Test
    public void getAdsWithRejectedStatus() {
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(
                        new AdsSelectionCriteriaMap().withAdGroupIds(adGroupId)
                                .withStatuses(AdStatusSelectionEnum.REJECTED)
                )
                .withFieldNames(AdFieldEnum.ID, AdFieldEnum.STATUS)
        );
        assertThat("вернулись правильные объявления", getResponse.getAds(),
                beanDifferV5(
                        Arrays.asList(
                                (AdGetItem) new AdGetItemMap()
                                        .withId(rejectedAdId1)
                                        .withStatus(StatusEnum.REJECTED).getBean(),
                                (AdGetItem) new AdGetItemMap()
                                        .withId(rejectedAdId2)
                                        .withStatus(StatusEnum.REJECTED).getBean(),
                                (AdGetItem) new AdGetItemMap()
                                        .withId(rejectedAdId3)
                                        .withStatus(StatusEnum.REJECTED).getBean()
                        )
                )
        );
    }

    @Test
    public void getAdsWithDraftAndRejectedStatus() {
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(
                        new AdsSelectionCriteriaMap().withAdGroupIds(adGroupId)
                                .withStatuses(AdStatusSelectionEnum.REJECTED, AdStatusSelectionEnum.DRAFT)
                )
                .withFieldNames(AdFieldEnum.ID, AdFieldEnum.STATUS)
        );
        assertThat("вернулись правильные объявления", getResponse.getAds(),
                beanDifferV5(
                        Arrays.asList(
                                (AdGetItem) new AdGetItemMap()
                                        .withId(draftAdId)
                                        .withStatus(StatusEnum.DRAFT).getBean(),
                                (AdGetItem) new AdGetItemMap()
                                        .withId(rejectedAdId1)
                                        .withStatus(StatusEnum.REJECTED).getBean(),
                                (AdGetItem) new AdGetItemMap()
                                        .withId(rejectedAdId2)
                                        .withStatus(StatusEnum.REJECTED).getBean(),
                                (AdGetItem) new AdGetItemMap()
                                        .withId(rejectedAdId3)
                                        .withStatus(StatusEnum.REJECTED).getBean()
                        )
                )
        );
    }

    @Test
    public void getAdsWithModerationAndPreacceptedAndAcceptedStatus() {
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(
                        new AdsSelectionCriteriaMap()
                                .withAdGroupIds(adGroupId)
                                .withStatuses(AdStatusSelectionEnum.MODERATION, AdStatusSelectionEnum.PREACCEPTED,
                                        AdStatusSelectionEnum.ACCEPTED)
                )
                .withFieldNames(AdFieldEnum.ID, AdFieldEnum.STATUS)
        );
        assertThat("вернулись правильные объявления", getResponse.getAds(),
                beanDifferV5(
                        Arrays.asList(
                                (AdGetItem) new AdGetItemMap()
                                        .withId(moderationAdId1)
                                        .withStatus(StatusEnum.MODERATION).getBean(),
                                (AdGetItem) new AdGetItemMap()
                                        .withId(moderationAdId2)
                                        .withStatus(StatusEnum.MODERATION).getBean(),
                                (AdGetItem) new AdGetItemMap()
                                        .withId(moderationAdId3)
                                        .withStatus(StatusEnum.MODERATION).getBean(),
                                (AdGetItem) new AdGetItemMap()
                                        .withId(acceptedAdId)
                                        .withStatus(StatusEnum.ACCEPTED).getBean()
                        )
                )
        );
    }

    @Test
    public void getAdsWithAllStatus() {
        GetResponse getResponse = api.userSteps.adsSteps().adsGet(new GetRequestMap()
                .withSelectionCriteria(
                        new AdsSelectionCriteriaMap()
                                .withAdGroupIds(adGroupId)
                                .withStatuses(
                                        AdStatusSelectionEnum.DRAFT,
                                        AdStatusSelectionEnum.MODERATION,
                                        AdStatusSelectionEnum.PREACCEPTED,
                                        AdStatusSelectionEnum.ACCEPTED,
                                        AdStatusSelectionEnum.REJECTED
                                )
                )
                .withFieldNames(AdFieldEnum.ID, AdFieldEnum.STATUS)
        );
        assertThat("вернулись правильные объявления", getResponse.getAds(),
                beanDifferV5(
                        Arrays.asList(
                                (AdGetItem) new AdGetItemMap()
                                        .withId(draftAdId)
                                        .withStatus(StatusEnum.DRAFT).getBean(),
                                (AdGetItem) new AdGetItemMap()
                                        .withId(moderationAdId1)
                                        .withStatus(StatusEnum.MODERATION).getBean(),
                                (AdGetItem) new AdGetItemMap()
                                        .withId(moderationAdId2)
                                        .withStatus(StatusEnum.MODERATION).getBean(),
                                (AdGetItem) new AdGetItemMap()
                                        .withId(moderationAdId3)
                                        .withStatus(StatusEnum.MODERATION).getBean(),
                                (AdGetItem) new AdGetItemMap()
                                        .withId(rejectedAdId1)
                                        .withStatus(StatusEnum.REJECTED).getBean(),
                                (AdGetItem) new AdGetItemMap()
                                        .withId(rejectedAdId2)
                                        .withStatus(StatusEnum.REJECTED).getBean(),
                                (AdGetItem) new AdGetItemMap()
                                        .withId(rejectedAdId3)
                                        .withStatus(StatusEnum.REJECTED).getBean(),
                                (AdGetItem) new AdGetItemMap()
                                        .withId(acceptedAdId)
                                        .withStatus(StatusEnum.ACCEPTED).getBean()
                        )
                )
        );
    }
}
