package ru.yandex.autotests.directapi.campaigns.getstatgoals;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.hamcrest.Matchers;
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.direct.utils.converter.BeanToBeanWrapperConverter;
import ru.yandex.autotests.directapi.apiclient.config.Semaphore;
import ru.yandex.autotests.directapi.apiclient.errors.AxisError;
import ru.yandex.autotests.directapi.apiclient.errors.AxisErrorDetails;
import ru.yandex.autotests.directapi.apiclient.methods.Method;
import ru.yandex.autotests.directapi.campaigns.CampaignFeatures;
import ru.yandex.autotests.directapi.common.api45.StatGoalInfo;
import ru.yandex.autotests.directapi.common.api45.StatGoalsCampaignIDInfo;
import ru.yandex.autotests.directapi.matchers.beans.EveryItem;
import ru.yandex.autotests.directapi.model.Logins;
import ru.yandex.autotests.directapi.model.campaigns.MetrikaGoals;
import ru.yandex.autotests.directapi.model.campaigns.StatGoalInfoMap;
import ru.yandex.autotests.directapi.model.campaigns.StatGoalsCampaignIDInfoMap;
import ru.yandex.autotests.directapi.model.common.Value;
import ru.yandex.autotests.directapi.rules.ApiSteps;
import ru.yandex.autotests.directapi.rules.Trashman;
import ru.yandex.autotests.directapi.steps.statistics.StatisticsSteps;
import ru.yandex.autotests.irt.testutils.allure.LogSteps;
import ru.yandex.autotests.irt.testutils.json.JsonUtils;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.hazelcast.SemaphoreRule;

import static ch.lambdaj.Lambda.convert;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assumeThat;


/**
 * User: mariabye
 * Date: 12.03.12
 * <p/>
 * Проверка вызова метода
 * https://jira.yandex-team.ru/browse/DIRECT-19085
 */
@Aqua.Test
@Features(CampaignFeatures.GET_STAT_GOALS)
public class StatGoalsResponseV4LiveTest {
    private LogSteps log = LogSteps.getLogger(this.getClass());
    public static String login = Logins.CLIENT_FREE_YE_DEFAULT;

    @ClassRule
    public static ApiSteps api = new ApiSteps().version(104);

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

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

    private static Long campaignWithNoGoals;
    private static Long campaignId;

    @BeforeClass
    public static void initTest() {
        int goalID = MetrikaGoals.getRandom();
        int goalIDNotAvailable = MetrikaGoals.getRandom();
        campaignWithNoGoals = api.as(login).userSteps.addDraftCampaign();
        campaignId = api.userSteps.campaignSteps().addDefaultTextCampaign(login);
        api.userSteps.getDirectJooqDbSteps().useShardForLogin(login).campMetrikaGoalsSteps().addOrUpdateMetrikaGoals(
                campaignId, (long) goalID, 200L, 200L);
        api.userSteps.getDirectJooqDbSteps().useShardForLogin(login).campMetrikaGoalsSteps().addOrUpdateMetrikaGoals(
                3318329L, (long) goalID, 200L, 200L);
        api.userSteps.getDirectJooqDbSteps().useShardForLogin(login).campMetrikaGoalsSteps().addOrUpdateMetrikaGoals(
                3318329L, (long) goalIDNotAvailable, 1L, 1L);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5628")
    public void forCampaignShouldNotContainCampaignIDKey() {
        log.info("Запросим цели для одной кампании: " + campaignId);
        StatGoalsCampaignIDInfo request = new StatGoalsCampaignIDInfo();
        request.setCampaignID(campaignId.intValue());
        StatGoalInfo[] goals = api.as(login).userSteps.statisticsSteps().getStatGoals(request);
        assumeThat("у кампании есть цели", goals.length, Matchers.greaterThan(0));
        assertThat("Получен номер кампании в ответе метода", goals[0].getCampaignID(), nullValue());
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5629")
    public void forCampaignsShouldContainCampaignIDKey() {
        log.info("Запросим цели для нескольких кампаний: " + campaignId);
        StatGoalsCampaignIDInfo request = new StatGoalsCampaignIDInfo();
        request.setCampaignIDS(new int[]{campaignId.intValue()});
        log.info(JsonUtils.toString(request));
        StatGoalInfo[] goals = api.as(login).userSteps.statisticsSteps().getStatGoals(request);
        assumeThat("у кампании есть цели", goals.length, Matchers.greaterThan(0));
        assertThat("Не вернулся номер кампании", goals[0].getCampaignID(), equalTo(request.getCampaignIDS()[0]));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5630")
    public void forZeroCampaignsProvideError() {
        log.info("Запросим цели для массива кампаний с campaignId=0");
        StatGoalsCampaignIDInfo request = new StatGoalsCampaignIDInfo();
        request.setCampaignIDS(new int[]{0});
        api.as(login).userSteps.statisticsSteps().shouldGetErrorOn(Method.GET_STAT_GOALS, request,
                new AxisError(1, AxisErrorDetails.EMPTY_STRING));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5631")
    public void forZeroCampaignProvideError() {
        log.info("Запросим цели для кампании с campaignId=0");
        StatGoalsCampaignIDInfo request = new StatGoalsCampaignIDInfo();
        request.setCampaignID(0);
        api.as(login).userSteps.statisticsSteps().shouldGetErrorOn(Method.GET_STAT_GOALS, request,
                new AxisError(1, AxisErrorDetails.EMPTY_STRING));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5632")
    public void forCampaignIDAndCampaignIDSSpecified() {
        log.info("Запросим цели");
        StatGoalsCampaignIDInfo request = new StatGoalsCampaignIDInfo();
        request.setCampaignID(campaignId.intValue());
        request.setCampaignIDS(new int[]{campaignId.intValue()});
        log.info(JsonUtils.toString(request));
        StatGoalInfo[] goals = api.as(login).userSteps.statisticsSteps().getStatGoals(request);
        assumeThat("у кампании есть цели", goals.length, Matchers.greaterThan(0));
        assertThat("не вернулся номер кампании", goals[0].getCampaignID(), equalTo(request.getCampaignIDS()[0]));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5633")
    public void getSearchStatGoalsForCampaignWithNoGoals() {
        log.info("Запросим цели");
        StatGoalsCampaignIDInfo request = new StatGoalsCampaignIDInfo();
        request.setCampaignID(campaignWithNoGoals.intValue());
        log.info(JsonUtils.toString(request));
        StatGoalInfo[] goals = api.as(login).userSteps.statisticsSteps().getStatGoals(request);
        assertThat("Получен список целей для кампании", goals.length, equalTo(0));

    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5634")
    public void getSearchStatGoalsForCampaignsWithNoGoals() {
        log.info("Запросим цели");
        StatGoalsCampaignIDInfo request = new StatGoalsCampaignIDInfo();
        request.setCampaignIDS(new int[]{campaignWithNoGoals.intValue()});
        log.info(JsonUtils.toString(request));
        StatGoalInfo[] goals = api.as(login).userSteps.statisticsSteps().getStatGoals(request);
        assertThat("Получен список целей для кампании", goals.length, equalTo(0));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5635")
    public void getSearchStatGoalsForCampaignsWithGoalsAndNoGoals() {
        log.info("Запросим цели");
        StatGoalsCampaignIDInfo request = new StatGoalsCampaignIDInfo();
        request.setCampaignIDS(new int[]{campaignWithNoGoals.intValue(), campaignId.intValue()});
        log.info(JsonUtils.toString(request));
        StatGoalInfo[] goals = api.as(login).userSteps.statisticsSteps().getStatGoals(request);
        assumeThat("у кампании есть цели", goals.length, Matchers.greaterThan(0));
        assertThat("не вернулся номер кампании",
                goals[0].getCampaignID().longValue(), equalTo(campaignId));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5636")
    public void getSearchStatGoalsForCampaignAndCampaignsWithNoGoals() {
        log.info("Запросим цели");
        StatGoalsCampaignIDInfo request = new StatGoalsCampaignIDInfo();
        request.setCampaignID(campaignId.intValue());
        request.setCampaignIDS(new int[]{campaignWithNoGoals.intValue()});
        log.info(JsonUtils.toString(request));
        StatGoalInfo[] goals = api.as(login).userSteps.statisticsSteps().getStatGoals(request);
        assertThat("Получен список целей для кампании", goals.length, equalTo(0));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5637")
    public void getSearchStatGoalsForCampaignWithNoGoalsAndCampaigns() {
        log.info("Запросим цели");
        StatGoalsCampaignIDInfo request = new StatGoalsCampaignIDInfo();
        request.setCampaignID(campaignWithNoGoals.intValue());
        request.setCampaignIDS(new int[]{campaignId.intValue()});
        log.info(JsonUtils.toString(request));
        StatGoalInfo[] goals = api.as(login).userSteps.statisticsSteps().getStatGoals(request);

        assumeThat("у кампании есть цели", goals.length, Matchers.greaterThan(0));
        assertThat("не вернулся номер кампании",
                goals[0].getCampaignID().longValue(), equalTo(campaignId));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5638")
    public void getSearchStatGoalsForDuplicatedCampaigns() {
        log.info("Запросим цели");
        StatGoalsCampaignIDInfo request = new StatGoalsCampaignIDInfo();
        int[] campaignIdS = new int[0];
        for (int i = 0; i < 100; i++) {
            campaignIdS = ArrayUtils.add(campaignIdS, campaignId.intValue());
        }

        request.setCampaignIDS(campaignIdS);
        log.info(JsonUtils.toString(request));
        StatGoalInfo[] goals = api.as(login).userSteps.statisticsSteps().getStatGoals(request);
        assumeThat("у кампании есть цели", goals.length, Matchers.greaterThan(0));
        assertThat("не вернулся номер кампании", goals[0].getCampaignID().longValue(),
                equalTo(campaignId));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5639")
    public void returnErrorIfCampaignsRequestedMoreThanLimit() {
        StatGoalsCampaignIDInfo request = new StatGoalsCampaignIDInfo();
        int[] campaignIdS = new int[0];
        for (int i = 0; i < StatisticsSteps.GET_STAT_GOALS_ITEMS_LIMIT + 1; i++) {
            campaignIdS = ArrayUtils.add(campaignIdS, campaignId.intValue());
        }
        request.setCampaignIDS(campaignIdS);
        api.as(login).userSteps.shouldGetErrorOn(Method.GET_STAT_GOALS, request,
                new AxisError(241, AxisErrorDetails.THE_ARRAY_MUST_CONTAIN_NO_MORE_THAN_N_ELEMENTS,
                        StringUtils.capitalize(StatGoalsCampaignIDInfoMap.CAMPAIGN_IDS),
                        StatisticsSteps.GET_STAT_GOALS_ITEMS_LIMIT));
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("5640")
    public void getSearchStatGoalsIfExists() {
        StatGoalsCampaignIDInfo request = new StatGoalsCampaignIDInfo();
        request.setCampaignID(campaignId.intValue());
        log.info(JsonUtils.toString(request));
        StatGoalInfo[] goals = api.as(login).userSteps.statisticsSteps().getStatGoals(request);

        assumeThat("у кампании есть цели", goals.length, Matchers.greaterThan(0));
        log.info("Для каждой цели проверяем поля");
        assertThat(convert(goals, new BeanToBeanWrapperConverter<StatGoalInfo>()).toArray(), EveryItem.everyItem(
                allOf(
                        hasProperty(StringUtils.uncapitalize(StatGoalInfoMap.GOAL_ID), Matchers.greaterThan(0L)),
                        hasProperty(StringUtils.uncapitalize(StatGoalInfoMap.NAME), not(Matchers.isEmptyOrNullString())),
                        hasProperty(StringUtils.uncapitalize(StatGoalInfoMap.AVAILABLE_FOR_STRATEGY),
                                anyOf(equalTo(Value.NO), equalTo(Value.YES))),
                        hasProperty(StringUtils.uncapitalize(StatGoalInfoMap.AVAILABLE_FOR_CONTEXT_STRATEGY),
                                anyOf(equalTo(Value.NO), equalTo(Value.YES))),
                        hasProperty(StringUtils.uncapitalize(StatGoalInfoMap.GOALS_REACHED), Matchers.greaterThanOrEqualTo(0)),
                        hasProperty(StringUtils.uncapitalize(StatGoalInfoMap.CONTEXT_GOALS_REACHED), Matchers.greaterThanOrEqualTo(0))
                )
        ));
    }
}
