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

import java.util.List;

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.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.retargetinglists.AddRequestMap;
import ru.yandex.autotests.directapi.model.api5.retargetinglists.DeleteRequestMap;
import ru.yandex.autotests.directapi.model.api5.retargetinglists.RetargetingListAddItemMap;
import ru.yandex.autotests.directapi.model.retargeting.RetargetingGoalType;
import ru.yandex.autotests.directapi.retargetinglists.RetargetingListsFeatures;
import ru.yandex.autotests.directapi.retargetinglists.RetargetingListsLogins;
import ru.yandex.autotests.directapi.rules.ApiSteps;
import ru.yandex.autotests.directapi.rules.Trashman;
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 org.hamcrest.Matchers.greaterThan;
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;

/**
 * https://st.yandex-team.ru/TESTIRT-8519
 */
@Aqua.Test
@Features(RetargetingListsFeatures.DELETE)
@Description("Проверка списания баллов")
@Issue("https://st.yandex-team.ru/DIRECT-48447")
public class DeleteRetargetingListsUnitsTest {
    private static long goalId1;
    private static long goalId2;
    private static final String LOGIN = RetargetingListsLogins.LOGIN_RETARGETING25;

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

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

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

    private static final int CALL_COST = 10;
    private static final int RETARGETING_LIST_COST = 2;
    private static final int ERROR_COST = 20;
    private static final int COMMON_REQUEST_ERROR_COST = 50;

    @BeforeClass
    public static void prepare() {
        List<Long> goalIds =
                api.userSteps.retargetingSteps().getRetargetingGoalIDsByType(LOGIN, RetargetingGoalType.GOAL);
        assumeThat("у клиента должно быть > 1 цели", goalIds.size(), greaterThan(1));
        goalId1 = goalIds.get(0);
        goalId2 = goalIds.get(1);
    }

    @Before
    public void addUnitsToClient() {
        api.userSteps.clientFakeSteps().fakeClearClientSpentUnits(LOGIN);
        api.as(LOGIN);
    }

    @Test
    public void deleteOneRetargetingList() {
        Long id = api.userSteps.retargetingListsSteps().addDefaultRetargetingLists(goalId1);
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        api.userSteps.retargetingListsSteps().delete(id);
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        int actualCost = unitsBefore - unitsAfter;
        int expectedCost = CALL_COST + RETARGETING_LIST_COST;
        assertThat("списалось верное число баллов", actualCost, equalTo(expectedCost));
    }

    @Test
    public void deleteTwoRetargetingLists() {
        List<Long> idList = api.userSteps.retargetingListsSteps().add(new AddRequestMap()
                .withRetargetingLists(
                        new RetargetingListAddItemMap()
                                .defaultRetargetingListAddItemMap(goalId1),
                        new RetargetingListAddItemMap()
                                .defaultRetargetingListAddItemMap(goalId2)
                ));
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        api.userSteps.retargetingListsSteps().delete(idList);
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        int actualCost = unitsBefore - unitsAfter;
        int expectedCost = CALL_COST + RETARGETING_LIST_COST * 2;
        assertThat("списалось верное число баллов", actualCost, equalTo(expectedCost));
    }

    @Test
    public void deleteOneInvalidRetargetingLists() {
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        api.userSteps.retargetingListsSteps().shouldGetResultOnDelete(
                new DeleteRequestMap()
                        .withSelectionCriteria(new IdsCriteriaMap()
                                .withIds(-1L)),
                ExpectedResult.errors(new Notification(5005,
                        Api5ErrorDetailsJava.ID_MUST_BE_POSITIVE_INTEGER
                )));
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        int actualCost = unitsBefore - unitsAfter;
        int expectedCost = CALL_COST + ERROR_COST;
        assertThat("списалось верное число баллов", actualCost, equalTo(expectedCost));
    }

    @Test
    public void deleteTwoInvalidRetargetingLists() {
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        api.userSteps.retargetingListsSteps().shouldGetResultOnDelete(
                new DeleteRequestMap()
                        .withSelectionCriteria(new IdsCriteriaMap()
                                .withIds(0L, 1L)),
                ExpectedResult.errors(new Notification(5005,
                        Api5ErrorDetailsJava.ID_MUST_BE_POSITIVE_INTEGER
                )),
                ExpectedResult.errors(new Notification(8800)));
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        int actualCost = unitsBefore - unitsAfter;
        int expectedCost = CALL_COST + ERROR_COST * 2;
        assertThat("списалось верное число баллов", actualCost, equalTo(expectedCost));
    }

    @Test
    public void deleteOneValidAndOneInvalidRetargetingLists() {
        Long id = api.userSteps.retargetingListsSteps().addDefaultRetargetingLists(goalId2);
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        api.userSteps.retargetingListsSteps().shouldGetResultOnDelete(
                new DeleteRequestMap()
                        .withSelectionCriteria(new IdsCriteriaMap()
                                .withIds(id, 0L)),
                ExpectedResult.success(id),
                ExpectedResult.errors(new Notification(5005,
                        Api5ErrorDetailsJava.ID_MUST_BE_POSITIVE_INTEGER
                )));
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        int actualCost = unitsBefore - unitsAfter;
        int expectedCost = CALL_COST + ERROR_COST + RETARGETING_LIST_COST;
        assertThat("списалось верное число баллов", actualCost, equalTo(expectedCost));
    }

    @Test
    public void invalidRequest() {
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(LOGIN);
        api.userSteps.retargetingListsSteps().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
    public void deleteRetargetingListsWhenClientHasZeroUnits() {
        Long id = api.userSteps.retargetingListsSteps().addDefaultRetargetingLists(goalId1);
        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.retargetingListsSteps().expectErrorOnDelete(
                new DeleteRequestMap()
                        .withSelectionCriteria(new IdsCriteriaMap()
                                .withIds(id)),
                new Api5Error(152, Api5ErrorDetails.NOT_ENOUGH_UNITS_FOR_OPERATION));
    }
}
