package ru.yandex.autotests.directapi.sitelinks.delete;

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.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.apiclient.errors.Api5ErrorDetailsJava;
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.api5.sitelinks.DeleteRequestMap;
import ru.yandex.autotests.directapi.rules.ApiSteps;
import ru.yandex.autotests.directapi.rules.Trashman;
import ru.yandex.autotests.directapi.sitelinks.SitelinksFeatures;
import ru.yandex.autotests.directapi.sitelinks.SitelinksLogins;
import ru.yandex.qatools.allure.annotations.Description;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Step;
import ru.yandex.qatools.allure.annotations.Stories;
import ru.yandex.qatools.hazelcast.SemaphoreRule;

import static org.hamcrest.Matchers.equalTo;
import static ru.yandex.autotests.directapi.apiclient.errors.Path.path;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assertThat;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assumeThat;

/**
 * Created by semkagtn on 2/9/15.
 * https://st.yandex-team.ru/TESTIRT-4101
 */
@Aqua.Test
@Features(SitelinksFeatures.DELETE)
@Stories(ApiStories.UNITS)
@Description("Проверка снятия баллов при удалении сайтлинков")
public class DeleteUnitsTest {

    private static final String LOGIN = SitelinksLogins.UNITS_DELETE_CLIENT;

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

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

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

    private static final int CALL_COST = 10;
    private static final int SET_COST = 0;
    private static final int ERROR_COST = 20;
    private static final int COMMON_REQUEST_ERROR_COST = 50;

    @Before
    @Step("Подготовка данных для теста")
    public void addUnitsToClient() {
        api.userSteps.clientFakeSteps().fakeClearClientSpentUnits(LOGIN);
    }

    @Test
    @Description("Удаление одного набора сайтлинков")
    @ru.yandex.qatools.allure.annotations.TestCaseId("3868")
    public void deleteOneSitelinksSet() {
        long id = api.userSteps.sitelinksSteps().addDefaultSet(1);
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        api.userSteps.sitelinksSteps().shouldGetResultOnDelete(new DeleteRequestMap()
                        .withSelectionCriteria(new IdsCriteriaMap()
                                .withIds(id)),
                ExpectedResult.success(id));
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        int actualCost = unitsBefore - unitsAfter;
        int expectedCost = CALL_COST + SET_COST;
        assertThat("списалось верное число баллов", actualCost, equalTo(expectedCost));
    }

    @Test
    @Description("Удаление двух наборов сайтлинков")
    @ru.yandex.qatools.allure.annotations.TestCaseId("3869")
    public void deleteTwoSitelinksSets() {
        long firstId = api.userSteps.sitelinksSteps().addDefaultSet(1);
        long secondId = api.userSteps.sitelinksSteps().addDefaultSet(1);
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        api.userSteps.sitelinksSteps().shouldGetResultOnDelete(new DeleteRequestMap()
                        .withSelectionCriteria(new IdsCriteriaMap()
                                .withIds(firstId, secondId)),
                ExpectedResult.success(firstId),
                ExpectedResult.success(secondId));
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        int actualCost = unitsBefore - unitsAfter;
        int expectedCost = CALL_COST + 2 * SET_COST;
        assertThat("списалось верное число баллов", actualCost, equalTo(expectedCost));
    }

    @Test
    @Description("Удаление одного невалидного набора сайтлинков")
    @ru.yandex.qatools.allure.annotations.TestCaseId("3866")
    public void deleteOneInvalidSet() {
        long invalidId = -1;
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        api.userSteps.sitelinksSteps().shouldGetResultOnDelete(new DeleteRequestMap()
                        .withSelectionCriteria(new IdsCriteriaMap()
                                .withIds(invalidId)),
                ExpectedResult.errors(new Notification(8800)));
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        int actualCost = unitsBefore - unitsAfter;
        int expectedCost = CALL_COST + ERROR_COST;
        assertThat("списалось верное число баллов", actualCost, equalTo(expectedCost));
    }

    @Test
    @Description("Удаление двух невалидных наборов сайтлинков")
    @ru.yandex.qatools.allure.annotations.TestCaseId("3867")
    public void deleteTwoInvalidSets() {
        long firstInvalidId = -1;
        long secondInvalidId = 0;
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        api.userSteps.sitelinksSteps().shouldGetResultOnDelete(new DeleteRequestMap()
                        .withSelectionCriteria(new IdsCriteriaMap()
                                .withIds(firstInvalidId, secondInvalidId)),
                ExpectedResult.errors(new Notification(8800)),
                ExpectedResult.errors(new Notification(8800)));
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        int actualCost = unitsBefore - unitsAfter;
        int expectedCost = CALL_COST + 2 * ERROR_COST;
        assertThat("списалось верное число баллов", actualCost, equalTo(expectedCost));
    }

    @Test
    @Description("Удаление одного валидного и одного невалидного наборов сайтлинков")
    @ru.yandex.qatools.allure.annotations.TestCaseId("3870")
    public void deleteOneValidAndOneInvalidSitelinksSets() {
        long id = api.userSteps.sitelinksSteps().addDefaultSet(1);
        long invalidId = -1;
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        api.userSteps.sitelinksSteps().shouldGetResultOnDelete(new DeleteRequestMap()
                        .withSelectionCriteria(new IdsCriteriaMap()
                                .withIds(id, invalidId)),
                ExpectedResult.success(id),
                ExpectedResult.errors(new Notification(8800)));
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        int actualCost = unitsBefore - unitsAfter;
        int expectedCost = CALL_COST + SET_COST + ERROR_COST;
        assertThat("списалось верное число баллов", actualCost, equalTo(expectedCost));
    }

    @Test
    @Description("Невалидный запрос на удаление сайтлинков")
    @ru.yandex.qatools.allure.annotations.TestCaseId("3865")
    public void invalidRequest() {
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        api.userSteps.sitelinksSteps().expectErrorOnDelete(new DeleteRequestMap()
                        .withSelectionCriteria(null),
                new Api5Error(8000, Api5ErrorDetailsJava.MISSING_PARAMETER_VALUE,
                        path(DeleteRequestMap.SELECTION_CRITERIA)));
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        int actualCost = unitsBefore - unitsAfter;
        int expectedCost = COMMON_REQUEST_ERROR_COST;
        assertThat("списалось верное число баллов", actualCost, equalTo(expectedCost));
    }

    @Test
    @Description("Удаление наборов сайтлинков с нулевым числом баллов у клиента")
    @ru.yandex.qatools.allure.annotations.TestCaseId("3871")
    public void deleteSitelinksSetWhenClientHasZeroUnits() {
        long id = api.userSteps.sitelinksSteps().addDefaultSet(1);

        int units = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        api.userSteps.clientFakeSteps().fakeWithdrawClientUnits(LOGIN, units);
        units = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        assumeThat("у клиента нету баллов", units, equalTo(0));

        api.userSteps.sitelinksSteps().expectErrorOnDelete(new DeleteRequestMap()
                        .withSelectionCriteria(new IdsCriteriaMap()
                                .withIds(id)),
                new Api5Error(152, Api5ErrorDetails.NOT_ENOUGH_UNITS_FOR_OPERATION));
    }
}
