package ru.yandex.autotests.directintapi.bstransport.main.banner.parameters.autovideo;

import java.util.Map;

import org.junit.AfterClass;
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.enums.BannerImagesFormatsImageType;
import ru.yandex.autotests.direct.db.models.jooq.ppc.enums.BannerImagesStatusmoderate;
import ru.yandex.autotests.direct.db.models.jooq.ppc.enums.ImagesStatusmoderate;
import ru.yandex.autotests.direct.db.steps.DirectJooqDbSteps;
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.Banner;
import ru.yandex.autotests.directapi.darkside.model.bslogs.clientdata.Campaign;
import ru.yandex.autotests.directapi.darkside.model.bslogs.clientdata.Context;
import ru.yandex.autotests.directapi.darkside.model.bslogs.clientdata.Resources;
import ru.yandex.autotests.directapi.enums.AdGroupType;
import ru.yandex.autotests.directapi.enums.BannerType;
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.directintapi.bstransport.TransportHelpSteps;
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.allOf;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static ru.yandex.autotests.directapi.darkside.model.ImageType.REGULAR;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assumeThat;
import static ru.yandex.autotests.irt.testutils.beandiffer2.BeanDifferMatcher.beanDiffer;

/**
 * Created by n-boy on 20.12.16.
 * https://st.yandex-team.ru/TESTIRT-10765
 * https://st.yandex-team.ru/TESTIRT-11994
 */
@Aqua.Test
@Tag(TagDictionary.RELEASE)
@Issue("https://st.yandex-team.ru/DIRECT-60092")
@Title("Транспорт: авто-видео версии баннеров, проверка общих условий отправки")
@Stories(StoriesNames.BANNER_PARAMS_VIDEO)
@Features(FeatureNames.BANNERS)

public class BsTransportOfAutoVideoTest {

    private static final String login = Logins.LOGIN_TRANSPORT;


    private static int shard;
    private static Long cid;
    private static Long pid;
    private static Long videoResourceId;
    private static Context context;
    private static Long bidWithoutVideo;
    private static Long bidWithLinkedImage;
    private static Long bidWithImageWithoutVideo;
    private static Long imageId;
    private static Long bidImageAd;
    private static RunBsTransportScriptResponse resp;

    private static DirectJooqDbSteps dbSteps;

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

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

    private static TransportHelpSteps helpSteps = new TransportHelpSteps(api);

    @BeforeClass
    public static void beforeClass() {
        String[] imageHashes = helpSteps.addImagesForUserIfNotExists(login, REGULAR);

        shard = api.userSteps.clientFakeSteps().getUserShard(login);
        dbSteps = api.userSteps.getDirectJooqDbSteps().useShard(shard);

        videoResourceId = dbSteps.mediaResourcesSteps().createDefaultVideoResource().getMediaResourceId();

        cid = api.userSteps.campaignSteps().addDefaultTextCampaign();
        pid = api.userSteps.adGroupsSteps().addDefaultGroup(cid);
        Long keywordId = api.userSteps.keywordsSteps().addDefaultKeyword(pid);

        api.userSteps.groupFakeSteps().makeGroupFullyModerated(pid);
        api.userSteps.phrasesFakeSteps().makeKeywordModerated(keywordId);

        // текстовый баннер без видео
        bidWithoutVideo = api.userSteps.adsSteps().addDefaultTextAd(pid);
        api.userSteps.bannersFakeSteps().makeBannerFullyModerated(bidWithoutVideo);

        // текстовый баннер с картинкой и подключенным видео
        bidWithLinkedImage = api.userSteps.adsSteps().addAdWithAdImageHash(pid, AdGroupType.BASE, BannerType.TEXT, imageHashes[0]);
        dbSteps.bannerResourcesSteps().createBannerResource(bidWithLinkedImage, videoResourceId);
        imageId = api.userSteps.getDirectJooqDbSteps().useShard(shard).
                imagesSteps().getBannerImagesByBid(bidWithLinkedImage).getImageId();
        api.userSteps.getDirectJooqDbSteps().useShard(shard).
                imagesSteps().setBannerImagesStatusModerate(imageHashes[0], BannerImagesStatusmoderate.Yes);
        api.userSteps.bannersFakeSteps().makeBannerFullyModerated(bidWithLinkedImage);

        // текстовый баннер с картинкой без видео
        bidWithImageWithoutVideo = api.userSteps.adsSteps().addAdWithAdImageHash(pid, AdGroupType.BASE, BannerType.TEXT, imageHashes[0]);
        api.userSteps.getDirectJooqDbSteps().useShard(shard).
                imagesSteps().setBannerImagesStatusModerate(imageHashes[0], BannerImagesStatusmoderate.Yes);
        api.userSteps.bannersFakeSteps().makeBannerFullyModerated(bidWithImageWithoutVideo);

        // ГО баннер
        String imageAdHash = api.userSteps.imagesStepsV5().adImagesGetAllHashes(login).get(0);
        if (!api.userSteps.getDirectJooqDbSteps().useShard(shard)
                .imagesSteps().getBannerImagesFormatsRecords(imageAdHash).getImageType().equals(BannerImagesFormatsImageType.image_ad)) {
            // создаем подходящую картинку у пользователя, если ее нет
            imageAdHash = api.userSteps.imagesStepsV5().addImageAdAdImage(login, 1);
        }
        bidImageAd = api.userSteps.adsSteps().addAdWithAdImageHash(pid, AdGroupType.BASE, BannerType.IMAGE_AD, imageAdHash);
        api.userSteps.getDirectJooqDbSteps().useShard(shard).
                imagesSteps().setImageStatusModerate(bidImageAd, imageAdHash, ImagesStatusmoderate.Yes);
        api.userSteps.bannersFakeSteps().makeBannerFullyModerated(bidImageAd);

        api.userSteps.campaignFakeSteps().makeNewCampaignReadyForSendingToBS(cid);

        // отправляем в БК
        resp = api.userSteps.getDarkSideSteps().getTransportSteps().sendNewCampaign(shard, cid);
        Campaign campaign = api.userSteps.getDarkSideSteps().getTransportSteps().getClientDataRequestCampaign(resp, 0, cid);
        assumeThat("новая кампания отправлена в БК", campaign, notNullValue());
        context = campaign.getContext(pid);
        assumeThat("группа отправлена в БК", context, notNullValue());
    }

    @Test
    @Title("Отправка в БК текстового баннера без привязанной картинки с неподключенным видео")
    public void testBannerAutoVideoWithoutAV() {
        Map<String, Map> bannerWithoutVideoRawRequest = api.userSteps.getDarkSideSteps().getTransportSteps().getRawClientDataLogRequestForBanner(resp, cid, pid, bidWithoutVideo);
        assumeThat("текстовый баннер с неподключенным видео отправлен в БК",
                bannerWithoutVideoRawRequest, notNullValue());
        Banner banner = context.getBanner(bidWithoutVideo);
        Banner expectedBannerWithVideo = new Banner()
                .withIsVideoCreative(null);
        assertThat("текстовый баннер с неподключенным видео и без картинки отправился без авто видео",
                banner, beanDiffer(expectedBannerWithVideo).useCompareStrategy(DefaultCompareStrategies.onlyExpectedFields()));
    }

    @Test
    @Title("Отправка в БК текстового баннера с картинкой с неподключенным видео")
    public void testBannerAutoVideoWithoutAVWithImage() {
        Map<String, Map> bannerWithoutVideoRawRequest
                = api.userSteps.getDarkSideSteps().getTransportSteps().getRawClientDataLogRequestForBanner(resp, cid, pid, bidWithImageWithoutVideo);
        assumeThat("текстовый баннер с неподключенным видео отправлен в БК",
                bannerWithoutVideoRawRequest, notNullValue());
        Banner banner = context.getBanner(bidWithImageWithoutVideo);
        Banner expectedBannerWithVideo = new Banner()
                .withIsVideoCreative(null);
        assertThat("текстовый баннер с неподключенным видео с картинкой отправился с авто видео",
                banner, beanDiffer(expectedBannerWithVideo).useCompareStrategy(DefaultCompareStrategies.onlyExpectedFields()));
    }

    @Test
    @Title("Отправка в БК текстового баннера c привязанной картинкой, версия баннера - без картинки, без видео")
    public void testBannerAutoVideoWithLinkedImageNoImageVersionWithAV() {
        Banner bannerWithImageNoImageVersion = context.getBanner(bidWithLinkedImage);
        assumeThat("текстовый баннер c привязанной картинкой, но версией для БК без картинки, отправлен в БК",
                bannerWithImageNoImageVersion, notNullValue());
        Banner expectedBannerWithVideo = new Banner()
                .withIsVideoCreative(null)
                .withResources(null);
        assertThat("текстовая часть картиночного баннера отправился без видео",
                bannerWithImageNoImageVersion, beanDiffer(expectedBannerWithVideo).useCompareStrategy(DefaultCompareStrategies.onlyExpectedFields()));
    }

    @Test
    @Title("Отправка в БК текстового баннера c привязанной картинкой, версия баннера - с картинкой, с подключенным видео")
    public void testBannerAutoVideoWithLinkedImageWithAV() {
        Map<String, Map> bannerWithImageRawRequest = api.userSteps.getDarkSideSteps().getTransportSteps().getRawClientDataLogRequestForBanner(resp, cid, pid, imageId);
        assumeThat("текстовый баннер c привязанной картинкой, версией для БК с картинкой, с подключенным видео, отправлен в БК",
                bannerWithImageRawRequest, notNullValue());
        assumeThat("это картиночный баннер", bannerWithImageRawRequest.get("Images"), notNullValue());
        assertThat("текстовый баннер  c привязанной картинкой, версия баннера - с картинкой, с подключенным видео, отправился с видео",
                bannerWithImageRawRequest.keySet(), allOf(
                        hasItem(Banner.IS_AUTO_VIDEO),
                        hasItem(Banner.RESOURCES)));
    }

    @Test
    @Title("Отправка в БК ГО баннера с неподключенным видео")
    public void testBannerAutoVideoImageAdWithoutAV() {
        Map<String, Map> bannerImageAdRawRequest = api.userSteps.getDarkSideSteps().getTransportSteps().getRawClientDataLogRequestForBanner(resp, cid, pid, bidImageAd);
        Banner bannerImageAd = context.getBanner(bidImageAd);
        assumeThat("ГО баннер с неподключенным видео отправлен в БК",
                bannerImageAd, notNullValue());
        assumeThat("ГО баннер с неподключенным видео отправился без поля IsAutoVideo",
                bannerImageAdRawRequest.keySet().contains(Banner.IS_AUTO_VIDEO), is(false));
        Resources res = bannerImageAd.getResources();
        assumeThat("ГО баннер с неподключенным видео отправился с непустым полем Resources->MediaImage",
                res != null ? res.getMediaImage() : null, notNullValue());
        assertThat("ГО баннер с неподключенным видео отправился без поля Resources->AutoVideoCreative",
                bannerImageAdRawRequest.get(Banner.RESOURCES).keySet().contains(Resources.AUTO_VIDEO_CREATIVE), is(false));
    }

    @AfterClass
    public static void afterClass() {
        dbSteps.mediaResourcesSteps().deleteMediaResource(videoResourceId);
    }

}
