package ru.yandex.autotests.direct.api.campaigns.update.textcampaign;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.yandex.direct.api.v5.campaigns.DailyBudgetModeEnum;
import com.yandex.direct.api.v5.campaigns.RelevantKeywordsModeEnum;
import com.yandex.direct.api.v5.general.YesNoEnum;
import org.joda.time.DateTime;
import org.junit.Before;
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.campaigns.CampaignsFeatures;
import ru.yandex.autotests.direct.api.campaigns.CampaignsLogins;
import ru.yandex.autotests.direct.utils.money.Currency;
import ru.yandex.autotests.direct.utils.money.MoneyCurrency;
import ru.yandex.autotests.direct.utils.tags.TagDictionary;
import ru.yandex.autotests.directapi.apiclient.config.Semaphore;
import ru.yandex.autotests.directapi.darkside.datacontainers.jsonrpc.fake.BannerFakeInfo;
import ru.yandex.autotests.directapi.darkside.datacontainers.jsonrpc.fake.BannerPhraseFakeInfo;
import ru.yandex.autotests.directapi.darkside.datacontainers.jsonrpc.fake.CampaignFakeInfo;
import ru.yandex.autotests.directapi.darkside.datacontainers.jsonrpc.fake.GroupFakeInfo;
import ru.yandex.autotests.directapi.model.api5.campaigns.CampaignAddItemMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.CampaignUpdateItemMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.DailyBudgetMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.EmailSettingsMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.NotificationMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.RelevantKeywordsSettingMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.SmsSettingsMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.TextCampaignUpdateItemMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.TimeTargetingMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.TimeTargetingOnPublicHolidaysMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.UpdateRequestMap;
import ru.yandex.autotests.directapi.model.api5.general.ExpectedResult;
import ru.yandex.autotests.directapi.model.campaigns.TimeTargetMap;
import ru.yandex.autotests.directapi.model.common.Value;
import ru.yandex.autotests.directapi.rules.ApiSteps;
import ru.yandex.autotests.directapi.rules.Trashman;
import ru.yandex.autotests.irt.testutils.RandomUtils;
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.hazelcast.SemaphoreRule;

import static org.hamcrest.Matchers.equalTo;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assertThat;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assumeThat;

/**
 * Created by pavryabov on 11.09.15.
 * https://st.yandex-team.ru/TESTIRT-6809
 */
@Aqua.Test
@Features(CampaignsFeatures.UPDATE)
@Description("Поверка StatusBsSynced после обновления текстовой кампании")
@Issue("https://st.yandex-team.ru/DIRECT-34570")
@Tag(TagDictionary.TRUNK)
public class CheckStatusBsSyncedAfterUpdateTextCampaignTest {

    //ToDo до починки DIRECT-46233 кампания переотправлется после любых изменений. После починки поправить часть кейсов

    private static final String SSP_PLATFORM_DEFAULT = "Rubicon";
    private static final String DOMAIN = "qwerty.ru";
    private static final String CLIENT = CampaignsLogins.UPDATE_CLIENT;

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

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

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

    private static Long id;
    private static Long adGroupId;
    private static Long adId;
    private static Long keywordId;

    @BeforeClass
    public static void initTest() {
        api.userSteps.getDirectJooqDbSteps().sspPlatformsSteps().saveSspPlatformsIfNotExist(SSP_PLATFORM_DEFAULT);
        api.userSteps.clientFakeSteps().fakeClearClientSpentUnits(CLIENT);
        id = api.userSteps.campaignSteps().addCampaign(new CampaignAddItemMap()
                .withName("name")
                .withStartDate(DateTime.now().toLocalDate().toString())
                .withDefaultTextCampaign());
        adGroupId = api.userSteps.adGroupsSteps().addDefaultGroup(id);
        adId = api.userSteps.adsSteps().addDefaultTextAd(adGroupId);
        keywordId = api.userSteps.keywordsSteps().addDefaultKeyword(adGroupId);
    }

    @Before
    public void setStatuses() {
        api.userSteps.campaignFakeSteps().setBSSynced(id, true);
        CampaignFakeInfo campaignFakeInfo = api.userSteps.campaignFakeSteps().fakeGetCampaignParams(id);
        assumeThat("у кампании StatusBsSynced = Yes", campaignFakeInfo.getStatusBsSynced(), equalTo(Value.YES));

        api.userSteps.groupFakeSteps().setGroupFakeStatusBsSynced(adGroupId, Value.YES);
        GroupFakeInfo groupFakeInfo = api.userSteps.groupFakeSteps().getGroupParams(adGroupId);
        assumeThat("у группы StatusBsSynced = Yes", groupFakeInfo.getStatusBsSynced(), equalTo(Value.YES));

        api.userSteps.bannersFakeSteps().setStatusBsSynced(adId, Value.YES);
        BannerFakeInfo bannerFakeInfo = api.userSteps.bannersFakeSteps().getBannerParams(adId);
        assumeThat("у объявления StatusBsSynced = Yes", bannerFakeInfo.getStatusBsSynced(), equalTo(Value.YES));

        api.userSteps.phrasesFakeSteps().setStatusBsSynced(keywordId.longValue(), Value.YES);
        BannerPhraseFakeInfo bannerPhraseFakeInfo =
                api.userSteps.phrasesFakeSteps().getBannerPhraseParams(keywordId.longValue());
        assumeThat("у фразы StatusBsSynced = Yes", bannerPhraseFakeInfo.getStatusBsSynced(), equalTo(Value.YES));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("830")
    public void updateClientInfo() {
        //DIRECT-46233
        api.userSteps.campaignSteps().shouldGetResultOnUpdate(new UpdateRequestMap()
                        .withCampaigns(new CampaignUpdateItemMap()
                                .withId(id)
                                .withClientInfo("someNewClientInfo")),
                ExpectedResult.success(id));
        checkStatuses(Value.NO, Value.YES, Value.YES, Value.YES);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("831")
    public void updateNotification() {
        //DIRECT-46233
        api.userSteps.campaignSteps().shouldGetResultOnUpdate(new UpdateRequestMap()
                        .withCampaigns(new CampaignUpdateItemMap()
                                .withId(id)
                                .withNotification(new NotificationMap()
                                        .withSmsSettings(new SmsSettingsMap()
                                                .withTimeFrom("20:00")
                                                .withTimeTo("20:15"))
                                        .withEmailSettings(new EmailSettingsMap().withEmail("somenewemail@mail.ru")))),
                ExpectedResult.success(id));
        checkStatuses(Value.NO, Value.YES, Value.YES, Value.YES);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("832")
    public void updateEndDate() {
        api.userSteps.campaignSteps().shouldGetResultOnUpdate(new UpdateRequestMap()
                        .withCampaigns(new CampaignUpdateItemMap()
                                .withId(id)
                                .withEndDate(DateTime.now().plusDays(23).toLocalDate().toString())),
                ExpectedResult.success(id));
        checkStatuses(Value.NO, Value.YES, Value.YES, Value.YES);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("833")
    public void updateStartDate() {
        api.userSteps.campaignSteps().shouldGetResultOnUpdate(new UpdateRequestMap()
                        .withCampaigns(new CampaignUpdateItemMap()
                                .withId(id)
                                .withStartDate(DateTime.now().plusDays(1).toLocalDate().toString())),
                ExpectedResult.success(id));
        checkStatuses(Value.NO, Value.YES, Value.YES, Value.YES);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("834")
    public void updateTimeTargeting() {
        //DIRECT-45952
        api.userSteps.campaignSteps().shouldGetResultOnUpdate(new UpdateRequestMap()
                        .withCampaigns(new CampaignUpdateItemMap()
                                .withId(id)
                                .withTimeTargeting(new TimeTargetingMap()
                                        .withConsiderWorkingWeekends(YesNoEnum.YES)
                                        .withHolidaysSchedule(new TimeTargetingOnPublicHolidaysMap()
                                                .withSuspendOnHolidays(YesNoEnum.NO)
                                                .withStartHour(15)
                                                .withEndHour(16)))),
                ExpectedResult.success(id));
        checkStatuses(Value.NO, Value.YES, Value.YES, Value.YES);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("835")
    public void updateTimeZone() {
        api.userSteps.campaignSteps().shouldGetResultOnUpdate(new UpdateRequestMap()
                        .withCampaigns(new CampaignUpdateItemMap()
                                .withId(id)
                                .withTimeZone(TimeTargetMap.TimeZone.ASIA_VIENTIANE)),
                ExpectedResult.success(id));
        checkStatuses(Value.NO, Value.YES, Value.YES, Value.YES);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("836")
    public void updateNegativeKeywords() {
        api.userSteps.campaignSteps().shouldGetResultOnUpdate(new UpdateRequestMap()
                        .withCampaigns(new CampaignUpdateItemMap()
                                .withId(id)
                                .withNegativeKeywords("newNegativeKeyword")),
                ExpectedResult.success(id));
        checkStatuses(Value.NO, Value.YES, Value.YES, Value.YES);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("837")
    public void updateBlockedIps() {
        api.userSteps.campaignSteps().shouldGetResultOnUpdate(new UpdateRequestMap()
                        .withCampaigns(new CampaignUpdateItemMap()
                                .withId(id)
                                .withBlockedIps("12.32.32.21")),
                ExpectedResult.success(id));
        checkStatuses(Value.NO, Value.YES, Value.YES, Value.YES);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("838")
    public void updateExcludedSitesDomain() {
        api.userSteps.campaignSteps().shouldGetResultOnUpdate(new UpdateRequestMap()
                        .withCampaigns(new CampaignUpdateItemMap()
                                .withId(id)
                                .withExcludedSites(DOMAIN)),
                ExpectedResult.success(id));
        checkStatuses(Value.NO, Value.YES, Value.YES, Value.YES);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("839")
    public void updateExcludedSitesSSPPlatform() {
        api.userSteps.campaignSteps().shouldGetResultOnUpdate(new UpdateRequestMap()
                        .withCampaigns(new CampaignUpdateItemMap()
                                .withId(id)
                                .withExcludedSites(SSP_PLATFORM_DEFAULT)),
                ExpectedResult.success(id));
        checkStatuses(Value.NO, Value.YES, Value.YES, Value.YES);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("840")
    public void updateName() {
        //DIRECT-46233
        api.userSteps.campaignSteps().shouldGetResultOnUpdate(new UpdateRequestMap()
                        .withCampaigns(new CampaignUpdateItemMap()
                                .withId(id)
                                .withName("someNewName")),
                ExpectedResult.success(id));
        checkStatuses(Value.NO, Value.YES, Value.YES, Value.YES);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("841")
    public void updateDailyBudget() {
        api.userSteps.campaignSteps().shouldGetResultOnUpdate(new UpdateRequestMap()
                        .withCampaigns(new CampaignUpdateItemMap()
                                .withId(id)
                                .withDailyBudget(new DailyBudgetMap()
                                        .withAmount(
                                                MoneyCurrency.get(Currency.RUB).getMinDayBudgetAmount().bidLong().longValue())
                                        .withMode(DailyBudgetModeEnum.DISTRIBUTED))),
                ExpectedResult.success(id));
        checkStatuses(Value.NO, Value.YES, Value.YES, Value.YES);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("842")
    public void updateCounterIds() {
        //DIRECT-46233
        //DIRECT-46474
        api.userSteps.campaignSteps().shouldGetResultOnUpdate(new UpdateRequestMap()
                        .withCampaigns(new CampaignUpdateItemMap()
                                .withId(id)
                                .withTextCampaign(new TextCampaignUpdateItemMap()
                                        .withCounterIds(RandomUtils.getRandomInteger(0, 10000000)))),
                ExpectedResult.success(id));
        checkStatuses(Value.NO, Value.YES, Value.NO, Value.YES);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("843")
    public void updateRelevantKeywordsSetting() {
        api.userSteps.campaignSteps().shouldGetResultOnUpdate(new UpdateRequestMap()
                        .withCampaigns(new CampaignUpdateItemMap()
                                .withId(id)
                                .withTextCampaign(new TextCampaignUpdateItemMap()
                                        .withRelevantKeywords(new RelevantKeywordsSettingMap()
                                                .withBudgetPercent(100)
                                                .withMode(RelevantKeywordsModeEnum.OPTIMAL)))),
                ExpectedResult.success(id));
        checkStatuses(Value.NO, Value.YES, Value.YES, Value.YES);
    }

    public void checkStatuses(String campaignStatus, String adGroupStatus, String adStatus, String keywordStatus) {
        List<String> statuses = new ArrayList<String>();
        CampaignFakeInfo campaignFakeInfo = api.userSteps.campaignFakeSteps().fakeGetCampaignParams(id);
        statuses.add(campaignFakeInfo.getStatusBsSynced());
        GroupFakeInfo groupFakeInfo = api.userSteps.groupFakeSteps().getGroupParams(adGroupId);
        statuses.add(groupFakeInfo.getStatusBsSynced());
        BannerFakeInfo bannerFakeInfo = api.userSteps.bannersFakeSteps().getBannerParams(adId);
        statuses.add(bannerFakeInfo.getStatusBsSynced());
        BannerPhraseFakeInfo bannerPhraseFakeInfo =
                api.userSteps.phrasesFakeSteps().getBannerPhraseParams(keywordId.longValue());
        statuses.add(bannerPhraseFakeInfo.getStatusBsSynced());
        assertThat("объекты имеют правильные статусы (campaign, adGroup, ad, keyword)",
                statuses, equalTo(Arrays.asList(campaignStatus, adGroupStatus, adStatus, keywordStatus)));
    }
}
