package ru.yandex.autotests.directintapi.bstransport.main.canvasad.queue;

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

import org.junit.Before;
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.aqua.annotations.project.Aqua;
import ru.yandex.autotests.direct.cmd.rules.CreativeBannerRule;
import ru.yandex.autotests.direct.cmd.rules.DirectCmdRule;
import ru.yandex.autotests.direct.db.models.jooq.ppc.enums.BannersPerformanceStatusmoderate;
import ru.yandex.autotests.direct.db.models.jooq.ppc.enums.PerfCreativesStatusmoderate;
import ru.yandex.autotests.direct.db.steps.DirectJooqDbSteps;
import ru.yandex.autotests.direct.utils.campaigns.CampaignTypeEnum;
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.datacontainers.jsonrpc.displaycanvas.ModerationInfo;
import ru.yandex.autotests.directapi.darkside.model.RunBsTransportScriptResponse;
import ru.yandex.autotests.directapi.darkside.model.Status;
import ru.yandex.autotests.directapi.darkside.tags.TestDomains;
import ru.yandex.autotests.directapi.rules.ApiSteps;
import ru.yandex.autotests.directapi.rules.Trashman;
import ru.yandex.autotests.directintapi.bstransport.FeatureNames;
import ru.yandex.autotests.directintapi.bstransport.StoriesNames;
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.allure.annotations.Step;
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.nullValue;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assume.assumeThat;
import static ru.yandex.autotests.directintapi.bstransport.TransportTestUtils.setBannerStatuses;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assertThat;

/**
 * Created by pashkus on 08.09.16.
 * https://st.yandex-team.ru/TESTIRT-10191
 */
@Aqua.Test
@Tag(TagDictionary.RELEASE)
@Tag(TagDictionary.TRUNK)
@Tag(TestDomains.BsTransport.EXPORT_QUEUE)
@Title("Проверяем постановку в очередь в зависимости от статусов модерации")
@Description("")
@Stories(StoriesNames.CANVAS_AD_SENDING)
@Features({FeatureNames.CANVAS_IMAGE_ADS, FeatureNames.NOT_FOR_FULL_EXPORT})
@Issue("https://st.yandex-team.ru/DIRECT-57413")
@RunWith(Parameterized.class)
public class CanvasBannerStatusModerateTest {
    public static final String LOGIN = Logins.LOGIN_TRANSPORT_IMG_AD;

    @ClassRule
    public static final ApiSteps api = new ApiSteps();

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

    @ClassRule
    public static final DirectCmdRule defaultClassRule = DirectCmdRule.defaultClassRule();

    private CreativeBannerRule bannersRule;

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

    @Rule
    public DirectCmdRule cmdRule;

    protected int shard;
    protected Long cid;
    protected Long pid;
    protected Long bid;
    protected Long creativeId;
    protected Long keywordId;

    private String bannerStatusModerate;
    private String bannerStatusPostModerate;
    private BannersPerformanceStatusmoderate bannersPerformanceStatusModerate;
    private Integer expectedObjStatus;

    public CanvasBannerStatusModerateTest(
            String bannerStatusModerate, String bannerStatusPostModerate,
            BannersPerformanceStatusmoderate bannersPerformanceStatusmoderate, Integer expectedObjStatus) {
        this.bannerStatusModerate = bannerStatusModerate;
        this.bannerStatusPostModerate = bannerStatusPostModerate;
        this.bannersPerformanceStatusModerate = bannersPerformanceStatusmoderate;
        this.expectedObjStatus = expectedObjStatus;
        bannersRule = new CreativeBannerRule(CampaignTypeEnum.TEXT).withUlogin(LOGIN);
        cmdRule = DirectCmdRule.defaultRule().withRules(bannersRule);
    }

    @Parameterized.Parameters(name = "СМ баннера: {0}, СПМ баннера: {1}; СМ креатива: {2}")
    public static Collection<Object[]> data() {
        Object[][] data = new Object[][]{
                {Status.NO, Status.YES, BannersPerformanceStatusmoderate.Yes, null},
                {Status.NO, Status.NO, BannersPerformanceStatusmoderate.No, null},
                {Status.NEW, Status.NEW, BannersPerformanceStatusmoderate.New, 0},
                {Status.SENT, Status.SENT, BannersPerformanceStatusmoderate.Sent, 0},
                {Status.SENDING, Status.SENDING, BannersPerformanceStatusmoderate.Sending, 0},
                {Status.YES, Status.YES, BannersPerformanceStatusmoderate.Yes, 1},
                {Status.YES, Status.YES, BannersPerformanceStatusmoderate.No, 0},
                {Status.YES, Status.YES, BannersPerformanceStatusmoderate.New, 0},
                {Status.YES, Status.YES, BannersPerformanceStatusmoderate.Sent, 0},
                {Status.YES, Status.YES, BannersPerformanceStatusmoderate.Sending, 0},
                {Status.YES, Status.NO, BannersPerformanceStatusmoderate.Yes, 0},
        };
        return Arrays.asList(data);
    }

    @Before
    @Step("Подготовка: создаем кампанию с креативным баннером.")
    public void basicInit() {
        api.as(LOGIN);
        shard = api.userSteps.clientFakeSteps().getUserShard(LOGIN);

        cid = bannersRule.getCampaignId();
        creativeId = bannersRule.getCreativeId();
        bid = bannersRule.getBannerId();
        pid = bannersRule.getGroupId();
        assumeThat("у баннера есть хотя бы одна ключевая фраза",
                bannersRule.getCurrentGroup().getPhrases().size(), notNullValue());
        keywordId = bannersRule.getCurrentGroup().getPhrases().get(0).getId();

        api.userSteps.campaignFakeSteps().makeNewCampaignReadyForSendingToBS(cid);
        api.userSteps.groupFakeSteps().makeGroupFullyModerated(pid);
        setBannerStatuses(api, bid, bannerStatusModerate, bannerStatusPostModerate, cid);

        api.userSteps.phrasesFakeSteps().makeKeywordModerated(keywordId);

        DirectJooqDbSteps jooqDbSteps = api.userSteps.getDirectJooqDbSteps().useShard(shard);
        jooqDbSteps.bannersPerformanceSteps()
                .setCreativeStatusModerate(cid, pid, bid, bannersPerformanceStatusModerate);
        jooqDbSteps.perfCreativesSteps().setModerateInfo(creativeId,
                new ModerationInfo().generateTestData().asJson());
        jooqDbSteps.perfCreativesSteps().setStatusModerate(creativeId, PerfCreativesStatusmoderate.Yes);
    }

    @Test
    @Title("Постановка в очередь при модерации всех объектов")
    @Description("Проставляем статус модерации yes в campaigns, phrases, banners, banners_performance")
    public void testAllModerated() {
        api.userSteps.transportSteps().runBsExportMasterScript(shard, cid);
        RunBsTransportScriptResponse resp = api.userSteps.transportSteps().runBsClientDataScript(shard, cid);
        if (expectedObjStatus == null) {
            assertThat("Кампания не была отправлена в БК", resp, nullValue());
        } else {
            Map campaign = api.userSteps.transportSteps().getRawClientDataLogRequestForCampaign(resp, cid);
            Map context = api.userSteps.transportSteps().getRawClientDataLogRequestForContext(resp, cid, pid);
            Map banner = api.userSteps.transportSteps().getRawClientDataLogRequestForBanner(resp, cid, pid, bid);
            Map keyword = api.userSteps.transportSteps().getRawClientDataLogRequestForKeyword(resp, cid, pid);

            assertThat("Ожидаем, что в БК была отправлена новая кампания", campaign, notNullValue());
            if (expectedObjStatus.equals(0)) {
                assertThat("Ожидаем, что в БК не была отправлена новая группа", context, nullValue());
            } else {
                assertThat("Ожидаем, что в БК была отправлена новая группа", context, notNullValue());
                assertThat("Ожидаем, что в БК был отправлен новый баннер", banner, notNullValue());
                assertThat("Ожидаем, что в БК была отправлена новая фраза", keyword, notNullValue());
            }
        }
    }
}
