package ru.yandex.autotests.directapi.changes.check;

import com.yandex.direct.api.v5.adgroups.AdGroupFieldEnum;
import com.yandex.direct.api.v5.changes.CheckFieldEnum;
import org.json.simple.JSONObject;
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.apiclient.errors.Api5ErrorMessageJava;
import ru.yandex.autotests.directapi.changes.ChangesFeatures;
import ru.yandex.autotests.directapi.changes.ChangesLogins;
import ru.yandex.autotests.directapi.model.api5.adgroups.AdGroupsSelectionCriteriaMap;
import ru.yandex.autotests.directapi.model.api5.adgroups.GetRequestMap;
import ru.yandex.autotests.directapi.model.api5.changes.CheckRequestMap;
import ru.yandex.autotests.directapi.model.api5.general.JavaOrPerlApi5Error;
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.allure.annotations.Step;
import ru.yandex.qatools.hazelcast.SemaphoreRule;

import static org.apache.commons.lang.StringUtils.capitalize;
import static org.hamcrest.Matchers.equalTo;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assertThat;

/**
 * Created by ginger on 04.04.15.
 * https://st.yandex-team.ru/TESTIRT-4916
 */
@Aqua.Test
@Features(ChangesFeatures.CHECK)
@Issue("https://st.yandex-team.ru/DIRECT-35862")
@Description("Проверка списания баллов API метода.")
public class CheckUnitsTest {

    private static String login = ChangesLogins.CHECK_UNITS_CLIENT;
    private String paramsString = "params";
    int CHECK_COST = 10;
    int DEFAULT_ERROR_COST = 20;
    int COMMON_ERROR_COST = 50;

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

    @ClassRule
    public static SemaphoreRule semaphore = Semaphore.getSemaphore();
    private static Long campaignId;
    private static Long bannerId;
    private static Long adGroupId;
    private static String timestamp;

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


    @BeforeClass
    public static void createData(){
        campaignId = api.userSteps.campaignSteps().addDefaultTextCampaign(login);
        adGroupId = api.userSteps.adGroupsSteps().addDefaultGroup(campaignId);
        bannerId = api.userSteps.adsSteps().addDefaultTextAd(adGroupId);
        adGroupId = api.userSteps.adGroupsSteps().adGroupsGet(new GetRequestMap()
                .withSelectionCriteria(
                        new AdGroupsSelectionCriteriaMap()
                                .withCampaignIds((long)campaignId)
                )
                .withFieldNames(
                        AdGroupFieldEnum.ID)).getAdGroups().get(0).getId();

        timestamp = api.userSteps.changesSteps().getTimestamp();
    }

    @Before
    @Step("подготовка логина")
    public void clearSpentUnits() {
        api.userSteps.clientFakeSteps().fakeClearClientSpentUnits(login);
        api.as(login);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("3461")
    public void tryCallCheckWithoutMethod() {
        //DIRECT-40769
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(login);
        JSONObject params = new JSONObject();
        api.userSteps.changesSteps().shouldGetJSONErrorOnCheck(
                params, login,
                JavaOrPerlApi5Error
                    .java(new Api5Error(8000,
                            Api5ErrorDetailsJava.MISSING_PARAMETER_VALUE,
                            capitalize(CheckRequestMap.TIMESTAMP)))
                    .perl(new Api5Error(8000,
                            Api5ErrorDetails.MISSING_REQUIRED_FIELD,
                            paramsString,
                            capitalize(CheckRequestMap.TIMESTAMP)))
        );
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(login);
        assertThat("списалось правильное количество баллов",
                unitsBefore - unitsAfter, equalTo(COMMON_ERROR_COST));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("3459")
    public void tryCallCheckWithAdIDAndGroupID(){
        //DIRECT-40769
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(login);
        api.userSteps.changesSteps().shouldGetErrorOnCheck(
                new CheckRequestMap()
                        .withAdGroupIds(adGroupId)
                        .withAdIds((long) bannerId)
                        .withFieldNames(CheckFieldEnum.CAMPAIGN_IDS, CheckFieldEnum.CAMPAIGNS_STAT)
                        .withTimestamp(timestamp),
                JavaOrPerlApi5Error
                        .java(new Api5Error(4004,
                                Api5ErrorDetailsJava.ONLY_ONE_OF_FIELDS_CAN_BE_SPECIFIED,
                                "CampaignIds, AdGroupIds, AdIds")
                            .withMessageFromResource(Api5ErrorMessageJava.PUT_MORE_THAN_ONE_PARAMETER))
                        .perl(new Api5Error(4004,
                                Api5ErrorDetails.ONLY_ONE_OF_FIELDS_CAN_BE_SPECIFIED,
                                "CampaignIds, AdGroupIds, AdIds"))
        );
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(login);
        assertThat("списалось правильное количество баллов",
                unitsBefore - unitsAfter, equalTo(DEFAULT_ERROR_COST + CHECK_COST));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("3460")
    public void callChangesCheck(){
        Long campaignId = api.userSteps.campaignSteps().addDefaultTextCampaign(login);
        Long adGroupId = api.userSteps.adGroupsSteps().addDefaultGroup(campaignId, login);
        api.userSteps.adsSteps().addDefaultTextAd(adGroupId, login);
        String timestamp = api.userSteps.changesSteps().getTimestamp();
        int unitsBefore = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(login);
        api.userSteps.changesSteps().changesCheck(
                new CheckRequestMap()
                        .withCampaignIds((long) campaignId)
                        .withTimestamp(timestamp)
                        .withFieldNames(CheckFieldEnum.CAMPAIGN_IDS, CheckFieldEnum.CAMPAIGNS_STAT)
        );
        int unitsAfter = api.userSteps.clientFakeSteps().fakeClientUnitsBalance(login);
        assertThat("списалось правильное количество баллов",
                unitsBefore - unitsAfter, equalTo(CHECK_COST));
    }

}
