package ru.yandex.autotests.direct.api.campaigns.unarchive;

import java.util.List;

import com.yandex.direct.api.v5.adgroups.AddResponse;
import com.yandex.direct.api.v5.campaigns.CampaignFieldEnum;
import com.yandex.direct.api.v5.campaigns.CampaignGetItem;
import com.yandex.direct.api.v5.campaigns.CampaignStateGetEnum;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Ignore;
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.db.models.jooq.ppc.enums.PhrasesAdgroupType;
import ru.yandex.autotests.direct.db.steps.DirectJooqDbSteps;
import ru.yandex.autotests.direct.utils.money.Currency;
import ru.yandex.autotests.direct.utils.tags.TagDictionary;
import ru.yandex.autotests.directapi.apiclient.config.Semaphore;
import ru.yandex.autotests.directapi.apiclient.errors.Api5ErrorDetails;
import ru.yandex.autotests.directapi.common.api45mng.CreateNewSubclientResponse;
import ru.yandex.autotests.directapi.model.Logins;
import ru.yandex.autotests.directapi.model.api5.Action;
import ru.yandex.autotests.directapi.model.api5.adgroups.AdGroupAddItemMap;
import ru.yandex.autotests.directapi.model.api5.adgroups.AddRequestMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.CampaignsSelectionCriteriaMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.GetRequestMap;
import ru.yandex.autotests.directapi.model.api5.campaigns.UnarchiveRequestMap;
import ru.yandex.autotests.directapi.model.api5.general.ExpectedResult;
import ru.yandex.autotests.directapi.model.api5.general.IdsCriteriaMap;
import ru.yandex.autotests.directapi.model.api5.general.Notification;
import ru.yandex.autotests.directapi.model.clients.ConvertType;
import ru.yandex.autotests.directapi.rules.ApiSteps;
import ru.yandex.autotests.directapi.rules.Trashman;
import ru.yandex.autotests.irt.testutils.allure.LogSteps;
import ru.yandex.qatools.Tag;
import ru.yandex.qatools.allure.annotations.Description;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.hazelcast.SemaphoreRule;

import static ch.lambdaj.Lambda.extract;
import static ch.lambdaj.Lambda.on;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assertThat;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assumeThat;

/**
 * Created by chicos on 25.08.15.
 */
@Aqua.Test
@Features(CampaignsFeatures.UNARCHIVE)
@Description("Проверка негативных сценариев разархивирования кампаний")
@Tag(TagDictionary.TRUNK)
public class UnarchiveCampaignsNegativeTest {
    private LogSteps log = LogSteps.getLogger(this.getClass());
    private static final String client = CampaignsLogins.SINGLE_CLIENT_UNARCHIVE;
    private static final String clientLimit = CampaignsLogins.SINGLE_CLIENT_CAMPAIGNS_LIMIT;
    private static final String FEATURE_CPM_GEO = "cpm_geoproduct_enabled";

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

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

    private static Long clientId;
    private static DirectJooqDbSteps directJooqDbSteps;

    private static Long campaignNonArchived;
    private static Long campaignID;
    private static Long campaignID1;
    private static Long campaignID2;

    private static String srvClient;
    private static final Currency currency = Currency.RUB;

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

    @BeforeClass
    public static void initTest() {
        api.userSteps.clientFakeSteps().fakeClearClientSpentUnits(client);
        directJooqDbSteps = api.userSteps.getDirectJooqDbSteps().useShardForLogin(client);
        clientId = directJooqDbSteps.shardingSteps().getClientIdByLogin(client);

        //удалим ранее созданные кампании пользователя clientLimit
        List<CampaignGetItem> campaigns = api.as(clientLimit).userSteps.campaignSteps().campaignsGet(
                new GetRequestMap()
                        .withFieldNames(CampaignFieldEnum.ID)
                        .withSelectionCriteria(new CampaignsSelectionCriteriaMap()))
                .getCampaigns();
        List<Long> existingCampaigns = extract(campaigns, on(CampaignGetItem.class).getId());
        if (existingCampaigns.size() > 0) {
            Long[] campaignsArray = existingCampaigns.toArray(new Long[existingCampaigns.size()]);
            api.userSteps.campaignSteps().campaignsDelete(campaignsArray);
        }

        campaignNonArchived = api.as(client).userSteps.campaignSteps().addDefaultTextCampaign();
        campaignID = api.userSteps.campaignSteps().addDefaultTextCampaign();
        campaignID1 = api.userSteps.campaignSteps().addDefaultTextCampaign();
        campaignID2 = api.userSteps.campaignSteps().addDefaultTextCampaign();
        api.userSteps.campaignSteps().campaignsSuspend(campaignID, campaignID1, campaignID2);
        api.userSteps.campaignSteps().campaignsArchive(campaignID, campaignID1, campaignID2);

        //Создадим сервисируемого клиента YE
        CreateNewSubclientResponse createNewSubclientResponse =
                api.as(Logins.MANAGER_GEO).wsdl(ru.yandex.autotests.directapi.common.api45mng.APIPort_PortType.class)
                        .userSteps.clientSteps().createServicedClient("subClient", Logins.MANAGER_GEO);
        assumeThat("клиент создан успешно", createNewSubclientResponse.getLogin(), notNullValue());
        srvClient = createNewSubclientResponse.getLogin();
        api.userSteps.clientFakeSteps().enableAPI(srvClient);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("674")
    public void nonArchivedCampaignTest() {
        api.as(client).userSteps.campaignSteps().shouldGetResultOn(
                Action.UNARCHIVE,
                new UnarchiveRequestMap().withSelectionCriteria(new IdsCriteriaMap()
                        .withIds(campaignNonArchived)),
                ExpectedResult.warnings(campaignNonArchived,
                        new Notification(10023, Api5ErrorDetails.CAMPAIGN_NOT_ARCHIVED)));
    }

    @Test
    @Description("Разархивация двух кампаний, идентификатор одной из которых - некорректен")
    @ru.yandex.qatools.allure.annotations.TestCaseId("675")
    public void unarchiveMultipleCampaignsOneInvalidTest() {
        api.as(client).userSteps.campaignSteps().shouldGetResultOn(
                Action.UNARCHIVE,
                new UnarchiveRequestMap().withSelectionCriteria(new IdsCriteriaMap()
                        .withIds(campaignID, 123456L)),
                ExpectedResult.success(campaignID),
                ExpectedResult.errors(new Notification(8800, Api5ErrorDetails.CAMPAIGN_NOT_FOUND)));
    }

    @Test
    @Description("Два однинаковых идентификатора кампании в запросе")
    @ru.yandex.qatools.allure.annotations.TestCaseId("673")
    public void sameIdsInRequestTest() {
        api.as(client).userSteps.campaignSteps().shouldGetResultOn(
                Action.UNARCHIVE,
                new UnarchiveRequestMap().withSelectionCriteria(new IdsCriteriaMap()
                        .withIds(campaignID1, campaignID1, campaignID2)),
                ExpectedResult.warnings(
                        new Notification(10000, Api5ErrorDetails.CAMPAIGN_ID_IS_PRESENTED_MORE_THAN_ONCE_IN_REQUEST)),
                ExpectedResult.warnings(
                        new Notification(10000, Api5ErrorDetails.CAMPAIGN_ID_IS_PRESENTED_MORE_THAN_ONCE_IN_REQUEST)),
                ExpectedResult.success(campaignID2));

        CampaignGetItem campaign = api.userSteps.campaignSteps().campaignsGet(campaignID1, CampaignFieldEnum.STATE);
        assertThat("кампания разархивирована несмотря на warning", campaign.getState(),
                equalTo(CampaignStateGetEnum.SUSPENDED));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("676")
    public void unarchivedCampaignsOverlimitTest() {
        //DIRECT-45609
        //DIRECT-53137
        Integer limit = 1;
        api.userSteps.clientFakeSteps().setUnarchivedCampaignCountLimit(clientLimit, limit);
        api.userSteps.clientFakeSteps().setCampaignCountLimit(clientLimit, 2);

        api.as(clientLimit);

        log.info("Создадим и заархивируем 1-ю кампанию");
        Long campaignID1 = api.userSteps.campaignSteps().addDefaultTextCampaign(clientLimit);
        api.userSteps.campaignSteps().campaignsSuspend(campaignID1);
        api.userSteps.campaignSteps().campaignsArchive(campaignID1);

        log.info("Создадим 2-ю кампании");
        api.userSteps.campaignSteps().addDefaultTextCampaign();

        log.info("Разархивируем 1-ю кампанию");
        api.userSteps.campaignSteps().shouldGetResultOn(
                Action.UNARCHIVE,
                new UnarchiveRequestMap().withSelectionCriteria(new IdsCriteriaMap()
                        .withIds(campaignID1)),
                ExpectedResult.errors(new Notification(8304, Api5ErrorDetails.UNARCHIVED_CAMPAIGNS_OVERLIMIT, limit)));
    }

    @Test
    public void unarchivedCampaignsPassLimitTest() {
        api.userSteps.clientFakeSteps().setUnarchivedCampaignCountLimit(clientLimit, 1);
        api.userSteps.clientFakeSteps().setCampaignCountLimit(clientLimit, 1);

        api.as(clientLimit);
        Long campaignID1 = api.userSteps.campaignSteps().addDefaultTextCampaign(clientLimit);
        api.userSteps.campaignSteps().campaignsSuspend(campaignID1);
        api.userSteps.campaignSteps().campaignsArchive(campaignID1);

        api.userSteps.campaignSteps().shouldGetResultOn(
                Action.UNARCHIVE,
                new UnarchiveRequestMap().withSelectionCriteria(new IdsCriteriaMap()
                        .withIds(1L, campaignID1+10000L, campaignID1, campaignID1+10001L)),
                ExpectedResult.errors(new Notification(8800, Api5ErrorDetails.CAMPAIGN_NOT_FOUND)),
                ExpectedResult.errors(new Notification(8800, Api5ErrorDetails.CAMPAIGN_NOT_FOUND)),
                ExpectedResult.success(),
                ExpectedResult.errors(new Notification(8800, Api5ErrorDetails.CAMPAIGN_NOT_FOUND))
        );
    }

    @Test
    @Description("Попробуем разархивировать кампанию созданную до конвертации методом COPY")
    @ru.yandex.qatools.allure.annotations.TestCaseId("677")
    @Ignore
    public void unarchiveOldCampaignAfterCopyConvertTest() {
        Long oldCampaignID = api.as(Logins.MANAGER_GEO).userSteps.campaignSteps().addDefaultTextCampaign(srvClient);

        log.info("Сконвертируем клиента методом COPY");
        api.userSteps.clientFakeSteps().convertCurrency(
                srvClient,
                currency.toString(),
                ConvertType.COPY);

        log.info("Попробуем разархивировать старую фишковую кампанию");
        api.userSteps.campaignSteps().shouldGetResultOn(
                srvClient,
                Action.UNARCHIVE,
                new UnarchiveRequestMap().withSelectionCriteria(new IdsCriteriaMap()
                        .withIds(oldCampaignID)),
                ExpectedResult.errors(new Notification(8304, Api5ErrorDetails.CAMPAIGN_IS_IN_SPECIAL_ARCHIVED_STATE,
                        oldCampaignID)));
    }

    @Test
    @Description("Попробуем разархивировать геопродуктовую кампанию без фичи cpm_geoproduct_enabled")
    public void unarchiveGeoproductCampaignTest() {
        Long campaignID = api.as(client).userSteps.campaignSteps().addDefaultTextCampaign();

        AddResponse addResponse = api.userSteps.adGroupsSteps().shouldGetResultOnAdd(
                new AddRequestMap().withAdGroups(new AdGroupAddItemMap().defaultAdGroupAddItem(campaignID)),
                ExpectedResult.success()
        );
        Long pid = addResponse.getAddResults().get(0).getId();
        directJooqDbSteps.adGroupsSteps().setType(pid, PhrasesAdgroupType.cpm_geoproduct);

        api.userSteps.campaignSteps().campaignsSuspend(campaignID);
        api.userSteps.campaignSteps().campaignsArchive(campaignID);

        directJooqDbSteps.featuresSteps().setClientFeature(clientId, FEATURE_CPM_GEO, false);

        api.userSteps.campaignSteps().shouldGetResultOn(
                Action.UNARCHIVE,
                new UnarchiveRequestMap().withSelectionCriteria(new IdsCriteriaMap().withIds(campaignID)),
                ExpectedResult.errors(new Notification(8304,
                        Api5ErrorDetails.CAMPAIGN_IS_IN_SPECIAL_ARCHIVED_STATE, campaignID)));

        directJooqDbSteps.featuresSteps().setClientFeature(clientId, FEATURE_CPM_GEO, true);

        api.userSteps.campaignSteps().shouldGetResultOn(
                Action.UNARCHIVE,
                new UnarchiveRequestMap().withSelectionCriteria(new IdsCriteriaMap().withIds(campaignID)),
                ExpectedResult.success());

        directJooqDbSteps.featuresSteps().setClientFeature(clientId, FEATURE_CPM_GEO, false);
    }
}
