package ru.yandex.autotests.directintapi.bstransport.main.phrase.actions.creation.queue;

import java.util.List;

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.tables.records.BsExportQueueRecord;
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.tags.TestDomains;
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.directintapi.bstransport.matchers.QueueRecordMatcher;
import ru.yandex.qatools.Tag;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Stories;
import ru.yandex.qatools.allure.annotations.Title;
import ru.yandex.qatools.hazelcast.SemaphoreRule;

import static ru.yandex.autotests.directapi.darkside.model.Status.NO;
import static ru.yandex.autotests.directapi.darkside.model.Status.YES;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assertThat;

@Aqua.Test
@Tag(TagDictionary.TRUNK)
@Tag(TagDictionary.RELEASE)
@Tag(TestDomains.BsTransport.EXPORT_QUEUE)
@Title("Транспорт: проверка постановки в очередь ppc.bs_export_queue " +
        "новой фразы в составе синхронизированной группы")
@Stories(StoriesNames.PHRASE_ACTION_CREATION)
@Features({FeatureNames.PHRASES, FeatureNames.NOT_FOR_FULL_EXPORT})
public class AddingToBsQueueNewPhraseInSyncedGroupTest {

    private static final String login = Logins.LOGIN_TRANSPORT;

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

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

    private static TransportHelpSteps helpSteps = new TransportHelpSteps(api);

    private static int shard;

    @BeforeClass
    public static void beforeClass() {
        shard = api.userSteps.clientFakeSteps().getUserShard(login);
    }

    @Test
    @Title("Добавление в очередь новой фразы в синхронизированной ранее группе с ретаргетингом")
    public void testAddingToBsQueueForNewPhraseInSyncedGroupWithNoPhrases() {
        Long retCondId = helpSteps.addRetargetingListsForUserIfNotExists(login).get(0);

        Long cid = api.userSteps.campaignSteps().addDefaultTextCampaign();
        Long pid = api.userSteps.adGroupsSteps().addDefaultGroup(cid);
        Long bid = api.userSteps.adsSteps().addDefaultTextAd(pid);
        api.userSteps.campaignFakeSteps().makeNewCampaignReadyForSendingToBS(cid);
        api.userSteps.groupFakeSteps().makeGroupFullyModerated(pid);
        api.userSteps.bannersFakeSteps().makeBannerFullyModerated(bid);

        api.userSteps.audienceTargetsSteps().addWithRetargetingList(login, pid, retCondId);

        api.userSteps.getDarkSideSteps().getTransportSteps().sendNewCampaign(shard, cid);

        /*
            После следующей операции у группы поменяются параметры следующим образом:
            1. statusModerate = "Ready"
            2. statusPostModerate = "No"
            3. statusBsSynced = "No"
         */

        Long keywordId = api.userSteps.keywordsSteps().addDefaultKeyword(pid);

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

        api.userSteps.getDarkSideSteps().getTransportSteps().runBsExportMasterScript(shard, cid);

        BsExportQueueRecord campInExportQueue =
                api.userSteps.getDirectJooqDbSteps().useShard(shard).transportSteps().getBsExportQueueRecord(cid);
        assertThat("в таблице ppc.bs_export_queue присутствует правильная запись " +
                        "для кампании с ретаргетингом и новой фразой",
                campInExportQueue,
                new QueueRecordMatcher()
                        .withoutCamps()
                        .withoutBanners()
                        .withContexts()
                        .withBids()
                        .withoutPrices());
    }

    @Test
    @Title("Добавление в очередь новой фразы в синхронизированной ранее группе с фразами")
    public void testAddingToBsQueueForNewPhraseInSyncedGroupWithPhrases() {
        Long cid = api.userSteps.campaignSteps().addDefaultTextCampaign();
        Long pid = api.userSteps.adGroupsSteps().addDefaultGroup(cid);
        Long bid = api.userSteps.adsSteps().addDefaultTextAd(pid);
        Long keywordId = api.userSteps.keywordsSteps().addDefaultKeyword(pid);
        api.userSteps.campaignFakeSteps().makeNewCampaignReadyForSendingToBS(cid);
        api.userSteps.groupFakeSteps().makeGroupFullyModerated(pid);
        api.userSteps.bannersFakeSteps().makeBannerFullyModerated(bid);
        api.userSteps.phrasesFakeSteps().makeKeywordModerated(keywordId);

        api.userSteps.getDarkSideSteps().getTransportSteps().sendNewCampaign(shard, cid);

        /*
            После следующей операции у группы поменяются параметры следующим образом:
            1. statusModerate = "Ready"
            2. statusPostModerate = "No"
            3. statusBsSynced = "No"
         */

        Long newKeywordId = api.userSteps.keywordsSteps().addDefaultKeyword(pid);

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

        api.userSteps.getDarkSideSteps().getTransportSteps().runBsExportMasterScript(shard, cid);
        BsExportQueueRecord campInExportQueue =
                api.userSteps.getDirectJooqDbSteps().useShard(shard).transportSteps().getBsExportQueueRecord(cid);
        assertThat("в таблице ppc.bs_export_queue присутствует правильная запись " +
                        "для кампании с новой фразой",
                campInExportQueue,
                new QueueRecordMatcher()
                        .withoutCamps()
                        .withoutBanners()
                        .withContexts()
                        .withBids()
                        .withoutPrices());
    }

    @Test
    @Title("Добавление в очередь нескольких новых фраз " +
            "в синхронизированной ранее группе без фраз")
    public void testAddingToBsQueueForNewPhrasesInSyncedGroupWithNoPhrases() {
        Long retCondId = helpSteps.addRetargetingListsForUserIfNotExists(login).get(0);

        Long cid = api.userSteps.campaignSteps().addDefaultTextCampaign();
        Long pid = api.userSteps.adGroupsSteps().addDefaultGroup(cid);
        Long bid = api.userSteps.adsSteps().addDefaultTextAd(pid);
        api.userSteps.campaignFakeSteps().makeNewCampaignReadyForSendingToBS(cid);
        api.userSteps.groupFakeSteps().makeGroupFullyModerated(pid);
        api.userSteps.bannersFakeSteps().makeBannerFullyModerated(bid);

        api.userSteps.audienceTargetsSteps().addWithRetargetingList(login, pid, retCondId);

        api.userSteps.getDarkSideSteps().getTransportSteps().sendNewCampaign(shard, cid);

        /*
            После следующей операции у группы поменяются параметры следующим образом:
            1. statusModerate = "Ready"
            2. statusPostModerate = "No"
            3. statusBsSynced = "No"
         */

        Long newKeywordId1 = api.userSteps.keywordsSteps().addDefaultKeyword(pid);
        Long newKeywordId2 = api.userSteps.keywordsSteps().addDefaultKeyword(pid);

        api.userSteps.phrasesFakeSteps().makeKeywordModerated(newKeywordId1);
        api.userSteps.phrasesFakeSteps().makeKeywordModerated(newKeywordId2);
        api.userSteps.groupFakeSteps().makeGroupFullyModerated(pid);


        api.userSteps.getDarkSideSteps().getTransportSteps().runBsExportMasterScript(shard, cid);
        BsExportQueueRecord campInExportQueue =
                api.userSteps.getDirectJooqDbSteps().useShard(shard).transportSteps().getBsExportQueueRecord(cid);
        assertThat("в таблице ppc.bs_export_queue присутствует правильная запись " +
                        "для кампании с 2 новыми фразами",
                campInExportQueue,
                new QueueRecordMatcher()
                        .withoutCamps()
                        .withoutBanners()
                        .withContexts()
                        .withBids()
                        .withoutPrices());
    }

    @Test
    @Title("Добавление в очередь нескольких новых фраз " +
            "в синхронизированной ранее группе с фразами")
    public void testAddingToBsQueueForNewPhrasesInSyncedGroupWithPhrases() {
        Long cid = api.userSteps.campaignSteps().addDefaultTextCampaign();
        Long pid = api.userSteps.adGroupsSteps().addDefaultGroup(cid);
        Long bid = api.userSteps.adsSteps().addDefaultTextAd(pid);
        Long keywordId = api.userSteps.keywordsSteps().addDefaultKeyword(pid);
        api.userSteps.campaignFakeSteps().makeNewCampaignReadyForSendingToBS(cid);
        api.userSteps.groupFakeSteps().makeGroupFullyModerated(pid);
        api.userSteps.bannersFakeSteps().makeBannerFullyModerated(bid);
        api.userSteps.phrasesFakeSteps().makeKeywordModerated(keywordId);

        api.userSteps.getDarkSideSteps().getTransportSteps().sendNewCampaign(shard, cid);

        /*
            После следующей операции у группы поменяются параметры следующим образом:
            1. statusModerate = "Ready"
            2. statusPostModerate = "No"
            3. statusBsSynced = "No"
         */

        Long newKeywordId1 = api.userSteps.keywordsSteps().addDefaultKeyword(pid);
        Long newKeywordId2 = api.userSteps.keywordsSteps().addDefaultKeyword(pid);

        api.userSteps.phrasesFakeSteps().makeKeywordModerated(newKeywordId1);
        api.userSteps.phrasesFakeSteps().makeKeywordModerated(newKeywordId2);
        api.userSteps.groupFakeSteps().makeGroupFullyModerated(pid);

        api.userSteps.getDarkSideSteps().getTransportSteps().runBsExportMasterScript(shard, cid);
        BsExportQueueRecord campInExportQueue =
                api.userSteps.getDirectJooqDbSteps().useShard(shard).transportSteps().getBsExportQueueRecord(cid);
        assertThat("в таблице ppc.bs_export_queue присутствует правильная запись " +
                        "для кампании с 2 новыми фразами",
                campInExportQueue,
                new QueueRecordMatcher()
                        .withoutCamps()
                        .withoutBanners()
                        .withContexts()
                        .withBids()
                        .withoutPrices());

    }

    @Test
    @Title("Добавление в очередь нескольких новых фраз " +
            "в синхронизированной ранее группе (присутствуют отклоненные новые фразы)")
    public void testAddingToBsQueueForNewPhraseInSyncedGroupWithDeclinedPhrases() {
        Long cid = api.userSteps.campaignSteps().addDefaultTextCampaign();
        Long pid = api.userSteps.adGroupsSteps().addDefaultGroup(cid);
        Long bid = api.userSteps.adsSteps().addDefaultTextAd(pid);
        Long keywordId = api.userSteps.keywordsSteps().addDefaultKeyword(pid);
        api.userSteps.campaignFakeSteps().makeNewCampaignReadyForSendingToBS(cid);
        api.userSteps.groupFakeSteps().makeGroupFullyModerated(pid);
        api.userSteps.bannersFakeSteps().makeBannerFullyModerated(bid);
        api.userSteps.phrasesFakeSteps().makeKeywordModerated(keywordId);

        api.userSteps.getDarkSideSteps().getTransportSteps().sendNewCampaign(shard, cid);

        List<Long> newKeywords = api.userSteps.keywordsSteps().addDefaultKeywords(pid, 4);

        for (Long keyword : newKeywords) {
            api.userSteps.phrasesFakeSteps()
                    .setStatusModerate(keyword, newKeywords.indexOf(keyword) % 2 == 0 ? YES : NO);
        }
        api.userSteps.getDarkSideSteps().getBannersFakeSteps().makeBannerFullyModerated(bid);
        api.userSteps.groupFakeSteps().makeGroupFullyModerated(pid);

        api.userSteps.getDarkSideSteps().getTransportSteps().runBsExportMasterScript(shard, cid);
        BsExportQueueRecord campInExportQueue =
                api.userSteps.getDirectJooqDbSteps().useShard(shard).transportSteps().getBsExportQueueRecord(cid);
        assertThat("в таблице ppc.bs_export_queue присутствует правильная запись " +
                        "для кампании с несколькими новыми принятыми и несколькими не принятыми фразами",
                campInExportQueue,
                new QueueRecordMatcher()
                        .withoutCamps()
                        .withoutBanners()
                        .withContexts()
                        .withBids()
                        .withoutPrices());
    }
}
