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

import org.junit.Before;
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.directapi.ApiStories;
import ru.yandex.autotests.directapi.apiclient.config.Semaphore;
import ru.yandex.autotests.directapi.apiclient.errors.Api5Error;
import ru.yandex.autotests.directapi.apiclient.errors.Api5ErrorDetails;
import ru.yandex.autotests.directapi.model.api5.Action;
import ru.yandex.autotests.directapi.model.api5.campaigns.SuspendRequestMap;
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.rules.ApiSteps;
import ru.yandex.autotests.directapi.rules.Trashman;
import ru.yandex.autotests.irt.testutils.allure.LogSteps;
import ru.yandex.qatools.allure.annotations.Description;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Stories;
import ru.yandex.qatools.hazelcast.SemaphoreRule;

import static org.apache.commons.lang3.StringUtils.capitalize;
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 chicos on 18.08.15.
 */
@Aqua.Test
@Features(CampaignsFeatures.SUSPEND)
@Stories(ApiStories.UNITS)
@Description("Списание баллов при остановке кампании")
public class SuspendCampaignsUnitsTest {
    private LogSteps log = LogSteps.getLogger(this.getClass());
    private static final String client = CampaignsLogins.CLIENT_UNITS_SUSPEND;

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

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

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

    private static final int SUSPEND_COST = 10;
    private static final int ITEM_COST_ON_SUSPEND = 5;
    private static final int ITEM_COST_ON_SUSPEND_FAULT = 20;
    private static final int GENERAL_FAULT_COST = 50;

    private static final Long INVALID_ID = 123456L;
    private static final Long INVALID_ID_2 = 123457L;

    @Before
    public void clearUnits() {
        api.userSteps.clientFakeSteps().fakeClearClientSpentUnits(client);
    }

    @Test
    @Description("Остановка одиночной кампании")
    @ru.yandex.qatools.allure.annotations.TestCaseId("639")
    public void suspendSingleCampaignTest() {
        Long campaignID = api.userSteps.campaignSteps().addDefaultTextCampaign();
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(client);
        api.userSteps.campaignSteps().campaignsSuspend(campaignID);
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(client);

        assertThat("стоимость остановки одной кампании", unitsBefore - unitsAfter,
                equalTo(SUSPEND_COST + ITEM_COST_ON_SUSPEND));
    }

    @Test
    @Description("Остановка нескольких кампаний")
    @ru.yandex.qatools.allure.annotations.TestCaseId("640")
    public void suspendSeveralCampaignsTest() {
        Long campaignID1 = api.userSteps.campaignSteps().addDefaultTextCampaign();
        Long campaignID2 = api.userSteps.campaignSteps().addDefaultTextCampaign();

        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(client);
        api.userSteps.campaignSteps().campaignsSuspend(campaignID1, campaignID2);
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(client);

        assertThat("стоимость остановки двух кампаний", unitsBefore - unitsAfter,
                equalTo(SUSPEND_COST + ITEM_COST_ON_SUSPEND * 2));
    }

    @Test
    @Description("Остановка одной невалидной кампании")
    @ru.yandex.qatools.allure.annotations.TestCaseId("641")
    public void suspendInvalidCampaignTest() {
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(client);
        api.userSteps.campaignSteps().shouldGetResultOn(
                Action.SUSPEND,
                new SuspendRequestMap().withSelectionCriteria(new IdsCriteriaMap()
                        .withIds(INVALID_ID)),
                ExpectedResult.errors(new Notification(8800, Api5ErrorDetails.CAMPAIGN_NOT_FOUND)));
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(client);

        assertThat("стоимость ошибки при остановке кампании", unitsBefore - unitsAfter,
                equalTo(SUSPEND_COST + ITEM_COST_ON_SUSPEND_FAULT));
    }

    @Test
    @Description("Остановка двух невалидных кампаний")
    @ru.yandex.qatools.allure.annotations.TestCaseId("642")
    public void suspendFewInvalidCampaignsTest() {
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(client);
        api.userSteps.campaignSteps().shouldGetResultOn(
                Action.SUSPEND,
                new SuspendRequestMap()
                        .withSelectionCriteria(new IdsCriteriaMap()
                                .withIds(INVALID_ID, INVALID_ID_2)),
                ExpectedResult.errors(new Notification(8800, Api5ErrorDetails.CAMPAIGN_NOT_FOUND)),
                ExpectedResult.errors(new Notification(8800, Api5ErrorDetails.CAMPAIGN_NOT_FOUND)));
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(client);

        assertThat("стоимость ошибки при остановке двух кампаний", unitsBefore - unitsAfter,
                equalTo(SUSPEND_COST + ITEM_COST_ON_SUSPEND_FAULT * 2));
    }

    @Test
    @Description("Остановка одной корректной и одной невалидной кампании")
    @ru.yandex.qatools.allure.annotations.TestCaseId("638")
    public void suspendOneValidAndOneInvalidCampaignsTest() {
        Long campaignID = api.userSteps.campaignSteps().addDefaultTextCampaign();

        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(client);
        api.userSteps.campaignSteps().shouldGetResultOn(
                Action.SUSPEND,
                new SuspendRequestMap().withSelectionCriteria(new IdsCriteriaMap()
                        .withIds(campaignID, INVALID_ID)),
                ExpectedResult.success(campaignID),
                ExpectedResult.errors(new Notification(8800, Api5ErrorDetails.CAMPAIGN_NOT_FOUND)));
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(client);

        assertThat("стоимость ошибки при остановке нескольких кампаний",
                unitsBefore - unitsAfter, equalTo(SUSPEND_COST + ITEM_COST_ON_SUSPEND + ITEM_COST_ON_SUSPEND_FAULT));
    }

    @Test
    @Description("Невалидный запрос на остановку кампании")
    @ru.yandex.qatools.allure.annotations.TestCaseId("643")
    public void generalErrorOnSuspendCampaignTest() {
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(client);
        api.userSteps.campaignSteps().shouldGetCampaignErrorOn(
                Action.SUSPEND,
                new SuspendRequestMap().withSelectionCriteria(null),
                new Api5Error(8000, Api5ErrorDetails.MISSING_REQUIRED_FIELD,
                        "params",
                        capitalize(SuspendRequestMap.SELECTION_CRITERIA)));
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(client);

        assertThat("стоимость общей ошибки при остановке кампании", unitsBefore - unitsAfter,
                equalTo(GENERAL_FAULT_COST));
    }

    @Test
    @Description("Недостаточное колличество баллов при остановке кампании")
    @ru.yandex.qatools.allure.annotations.TestCaseId("644")
    public void notEnoughUnitsOnSuspendCampaignTest() {
        Long campaignID = api.userSteps.campaignSteps().addDefaultTextCampaign();

        log.info("Обнулим колличество доступных пользователю баллов");
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(client);
        api.userSteps.clientFakeSteps().fakeWithdrawClientUnits(client, unitsBefore);
        unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(client);
        assumeThat("доступные баллы пользователя", unitsBefore, equalTo(0));

        api.userSteps.campaignSteps().shouldGetCampaignErrorOn(
                Action.SUSPEND,
                new SuspendRequestMap().withSelectionCriteria(new IdsCriteriaMap()
                        .withIds(campaignID)),
                new Api5Error(152, Api5ErrorDetails.NOT_ENOUGH_UNITS_FOR_OPERATION));
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(client);
        assertThat("доступные баллы пользователя после ошибки", unitsAfter, equalTo(0));
    }
}
