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

import org.apache.commons.lang.math.RandomUtils;
import org.junit.Before;
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.BannerPermalinksPermalinkAssignType;
import ru.yandex.autotests.direct.db.models.jooq.ppc.enums.BannersStatusbssynced;
import ru.yandex.autotests.direct.db.models.jooq.ppc.enums.OrganizationsStatusPublish;
import ru.yandex.autotests.direct.db.models.jooq.ppc.tables.records.BannersRecord;
import ru.yandex.autotests.direct.db.models.jooq.ppc.tables.records.OrganizationsRecord;
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.Campaign;
import ru.yandex.autotests.directapi.darkside.steps.TransportSteps;
import ru.yandex.autotests.directapi.model.api5.ads.AdAddItemMap;
import ru.yandex.autotests.directapi.model.api5.ads.TextImageAdAddMap;
import ru.yandex.autotests.directapi.rules.ApiSteps;
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.Features;
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.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static ru.yandex.autotests.direct.db.models.jooq.ppc.enums.BannerPermalinksPermalinkAssignType.manual;
import static ru.yandex.autotests.direct.db.models.jooq.ppc.enums.OrganizationsStatusPublish.published;
import static ru.yandex.autotests.direct.db.models.jooq.ppc.enums.OrganizationsStatusPublish.unpublished;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assumeThat;

@Aqua.Test
@Tag(TagDictionary.TRUNK)
@Tag(TagDictionary.RELEASE)
@Title("Транспорт: проверка отправки Stop при изменении Banner.Permalink")
@Stories(StoriesNames.BANNER_PARAMS_PERMALINK)
@Features(FeatureNames.BANNERS)
public class BsTransportOfPermalinkImageAdStopTest {
    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 long clientId;
    private static int shard;
    private static TransportSteps transportSteps;
    private static DirectJooqDbSteps jooqDbSteps;

    private long cid;
    private long pid;
    private long bid;
    private Long permalink;
    private Long chainId;

    @BeforeClass
    public static void beforeClass() {
        shard = api.userSteps.clientFakeSteps().getUserShard(login);
        clientId = Long.valueOf(api.userSteps.clientFakeSteps().getClientData(login).getClientID());
        transportSteps = api.userSteps.getDarkSideSteps().getTransportSteps();
        jooqDbSteps = api.userSteps.getDirectJooqDbSteps().useShard(shard);
    }

    @Before
    public void before() {
        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);

        String adImageHash = api.userSteps.imagesStepsV5().addImageAdAdImage(1);
        TextImageAdAddMap textImageAdAddMap = new TextImageAdAddMap()
                .defaultTextImageAd(adImageHash);

        AdAddItemMap adAddItemMap = new AdAddItemMap()
                .withAdGroupId(pid)
                .withTextImageAd(textImageAdAddMap);

        bid = api.userSteps.adsSteps().addAd(adAddItemMap);
        jooqDbSteps.bannersSteps().setBannersHref(bid, null);
        api.userSteps.bannersFakeSteps().makeBannerFullyModerated(bid);
    }

    @Title("удалили опубликованный пермалинк")
    @Test
    public void manualPermalinkDeleted_notSentToBs() {
        permalink = assignPermalinkOrChain(manual, false);
        addOrganization(permalink, published);
        sendToBsFirstTime();

        jooqDbSteps.bannerAdditionsSteps().updateOrganizationStatusPublish(permalink, unpublished);
        jooqDbSteps.bannerAdditionsSteps().deletePermalinkByBidAndType(bid, manual);
        Campaign campaign = sendToBsAndGetCampaign();
        assertThat("Отправка отработала корректно", campaign, nullValue());
    }

    @Title("распубликовали опубликованный пермалинк")
    @Test
    public void manualPermalinkBecameUnpublished_SentStopToBs() {
        permalink = assignPermalinkOrChain(manual, false);
        addOrganization(permalink, published);
        sendToBsFirstTime();

        jooqDbSteps.bannerAdditionsSteps().updateOrganizationStatusPublish(permalink, unpublished);
        Campaign campaign = sendToBsAndGetCampaign();
        assertThat("Отправка отработала корректно", campaign, notNullValue());
        assertThat("На баннере должен уйти Stop: 1",
                campaign.getContext(pid).getBanner(bid).getStop(), is(1));
    }

    @Title("распубликовали опубликованный пермалинк, осталась визитка")
    @Test
    public void manualPermalinkWithVcardBecameUnpublished_SentStopToBs() {
        permalink = assignPermalinkOrChain(manual, false);
        addOrganization(permalink, published);
        sendToBsFirstTime();

        jooqDbSteps.bannerAdditionsSteps().updateOrganizationStatusPublish(permalink, unpublished);
        Campaign campaign = sendToBsAndGetCampaign();
        assertThat("Отправка отработала корректно", campaign, notNullValue());
        assertThat("На баннере должен уйти Stop: 1",
                campaign.getContext(pid).getBanner(bid).getStop(), is(1));
    }

    @Title("распубликовали опубликованный пермалинк, осталась ссылка")
    @Test
    public void manualPermalinkWithHrefBecameUnpublished_SentUpdateToBs() {
        addHref();
        permalink = assignPermalinkOrChain(manual, false);
        addOrganization(permalink, published);
        sendToBsFirstTime();

        jooqDbSteps.bannerAdditionsSteps().updateOrganizationStatusPublish(permalink, unpublished);
        Campaign campaign = sendToBsAndGetCampaign();
        assertThat("Отправка отработала корректно", campaign, notNullValue());
        assertThat("На баннере должен уйти Stop: 1",
                campaign.getContext(pid).getBanner(bid).getStop(), is(0));
    }

    /**
     * Отправка в БК и получение контекста
     */
    private void sendToBsFirstTime() {
        api.userSteps.campaignFakeSteps().makeNewCampaignReadyForSendingToBS(cid);
        RunBsTransportScriptResponse resp = transportSteps.sendNewCampaign(shard, cid);
        Campaign campaign = transportSteps.getClientDataRequestCampaign(resp, 0, cid);
        assumeThat("новая кампания отправлена в БК", campaign, notNullValue());
    }

    private void addHref() {
        BannersRecord record = jooqDbSteps.bannersSteps().getBanner(bid);
        record.setHref("http://ya.ru");
        jooqDbSteps.bannersSteps().updateBanners(record);
    }

    private Long assignPermalinkOrChain(BannerPermalinksPermalinkAssignType permalinkType, boolean addChain) {
        Long permalink = addChain ? 0 : RandomUtils.nextLong();
        Long chainId = addChain ? RandomUtils.nextLong() : null;
        jooqDbSteps.bannerAdditionsSteps().setPermalink(bid, permalink, chainId, permalinkType);
        return permalink != 0 ? permalink : chainId;
    }

    private void addOrganization(Long permalink, OrganizationsStatusPublish pubStatus) {
        OrganizationsRecord record = new OrganizationsRecord()
                .setPermalinkId(permalink)
                .setStatusPublish(pubStatus)
                .setClientid(clientId);
        jooqDbSteps.bannerAdditionsSteps().addOrUpdateOrganization(record);
    }

    private Campaign sendToBsAndGetCampaign() {
        jooqDbSteps.bannersSteps().setBannerStatusBsSynced(bid, BannersStatusbssynced.No);
        transportSteps.runBsExportMasterScript(shard, cid);
        RunBsTransportScriptResponse resp = transportSteps.runBsClientDataScript(shard, cid);
        return resp != null ? transportSteps.getClientDataRequestCampaign(resp, 0, cid) : null;
    }
}
