package ru.yandex.autotests.directapi.keywordsresearch.deduplicate;

import com.yandex.direct.api.v5.general.IdsCriteria;
import com.yandex.direct.api.v5.keywordsresearch.DeduplicateOperationEnum;
import com.yandex.direct.api.v5.keywordsresearch.DeduplicateResponse;
import com.yandex.direct.api.v5.keywordsresearch.DeduplicateResponseAddItem;
import com.yandex.direct.api.v5.keywordsresearch.DeduplicateResponseUpdateItem;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;

import ru.yandex.aqua.annotations.project.Aqua;
import ru.yandex.autotests.directapi.keywordsresearch.KeywordsResearchFeatures;
import ru.yandex.autotests.directapi.keywordsresearch.KeywordsResearchLogins;
import ru.yandex.autotests.directapi.model.api5.keywordsresearch.DeduplicateRequestItemMap;
import ru.yandex.autotests.directapi.model.api5.keywordsresearch.DeduplicateRequestMap;
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 static java.util.Collections.singletonList;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assertThat;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assumeThat;
import static ru.yandex.autotests.irt.testutils.beandiffer.BeanDifferMatcher.beanEquivalent;

@Aqua.Test
@Features(KeywordsResearchFeatures.DEDUPLICATE)
@Description("Тест на общую корректность работы сервиса с операцией ELIMINATE_OVERLAPPING")
public class DeduplicateEliminateOverlappingModeTest {

    private static final String CLIENT = KeywordsResearchLogins.CLIENT;

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

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

    @Test
    public void convertToAddTest() {
        DeduplicateRequestMap request = new DeduplicateRequestMap()
                .withOperations(DeduplicateOperationEnum.ELIMINATE_OVERLAPPING)
                .withKeywords(new DeduplicateRequestItemMap().withKeyword("ключевая фраза"));

        DeduplicateResponse actual =
                api.userSteps.keywordsResearchSteps().keywordsResearchDeduplicateRawResponse(CLIENT, request);

        DeduplicateResponse expected = new DeduplicateResponse();
        DeduplicateResponseAddItem keyword = new DeduplicateResponseAddItem();
        keyword.setKeyword("ключевая фраза");
        expected.setAdd(singletonList(keyword));

        assertThat("Добавляется корректный текст", actual, beanEquivalent(expected));
    }

    @Test
    public void convertToUpdateTest() {
        DeduplicateRequestMap request = new DeduplicateRequestMap()
                .withOperations(DeduplicateOperationEnum.ELIMINATE_OVERLAPPING)
                .withKeywords(
                        new DeduplicateRequestItemMap().withKeyword("ключевая").withId(1L),
                        new DeduplicateRequestItemMap().withKeyword("ключевая фраза"));

        DeduplicateResponse actual =
                api.userSteps.keywordsResearchSteps().keywordsResearchDeduplicateRawResponse(CLIENT, request);

        DeduplicateResponse expected = new DeduplicateResponse();

        DeduplicateResponseUpdateItem keywordUpdate = new DeduplicateResponseUpdateItem();
        keywordUpdate.setKeyword("ключевая -фраза");
        keywordUpdate.setId(1L);

        DeduplicateResponseAddItem keywordAdd = new DeduplicateResponseAddItem();
        keywordAdd.setKeyword("ключевая фраза");

        expected.setUpdate(singletonList(keywordUpdate));
        expected.setAdd(singletonList(keywordAdd));

        assertThat("Обновляется текст на корректный", actual, beanEquivalent(expected));
    }

    @Test
    public void convertToDeleteTest() {
        DeduplicateRequestMap request = new DeduplicateRequestMap()
                .withOperations(DeduplicateOperationEnum.ELIMINATE_OVERLAPPING)
                .withKeywords(
                    new DeduplicateRequestItemMap().withKeyword("ключевая фраза").withId(1L),
                    new DeduplicateRequestItemMap().withKeyword("ключевая").withId(2L),
                    new DeduplicateRequestItemMap().withKeyword("ключевая -фраза").withId(3L));

        DeduplicateResponse actual =
                api.userSteps.keywordsResearchSteps().keywordsResearchDeduplicateRawResponse(CLIENT, request);

        DeduplicateResponse expected = new DeduplicateResponse();

        IdsCriteria ids = new IdsCriteria();
        ids.setIds(singletonList(3L));

        DeduplicateResponseUpdateItem keywordUpdate = new DeduplicateResponseUpdateItem();
        keywordUpdate.setKeyword("ключевая -фраза");
        keywordUpdate.setId(2L);

        expected.setUpdate(singletonList(keywordUpdate));
        expected.setDelete(ids);

        assertThat("Удаляется корректная фраза", actual, beanEquivalent(expected));
    }

    @Test
    public void convertToFailureTest() {
        DeduplicateRequestMap request = new DeduplicateRequestMap()
                .withOperations(DeduplicateOperationEnum.ELIMINATE_OVERLAPPING)
                .withKeywords(
                        new DeduplicateRequestItemMap().withKeyword("ключевая++ фраза"));

        DeduplicateResponse actual =
                api.userSteps.keywordsResearchSteps().keywordsResearchDeduplicateRawResponse(CLIENT, request);

        assumeThat("Ответ Failure из сервиса получен", actual.getFailure(),
                hasSize(1));
        assertThat("Возвращается корректная позиция ошибки", actual.getFailure().get(0).getPosition(),
                equalTo(1L));
    }

    @Test
    public void unglueTest() {
        DeduplicateRequestMap request = new DeduplicateRequestMap()
                .withOperations(DeduplicateOperationEnum.ELIMINATE_OVERLAPPING)
                .withKeywords(
                    new DeduplicateRequestItemMap().withKeyword("дача квартира -ремонт").withId(1L),
                    new DeduplicateRequestItemMap().withKeyword("квартира машина дача").withId(2L));

        DeduplicateResponse actual =
                api.userSteps.keywordsResearchSteps().keywordsResearchDeduplicateRawResponse(CLIENT, request);

        DeduplicateResponse expected = new DeduplicateResponse();

        DeduplicateResponseUpdateItem keyword = new DeduplicateResponseUpdateItem();

        keyword.setKeyword("дача квартира -ремонт -машина");
        keyword.setId(1L);

        expected.setUpdate(singletonList(keyword));

        assertThat("Ключевые фразы расклеены", actual, beanEquivalent(expected));
    }

    @Test
    public void noGlueWhenSamePlusWordsTest() {
        DeduplicateRequestMap request = new DeduplicateRequestMap()
                .withOperations(DeduplicateOperationEnum.ELIMINATE_OVERLAPPING)
                .withKeywords(
                        new DeduplicateRequestItemMap().withKeyword("дача квартира -ремонт").withId(1L),
                        new DeduplicateRequestItemMap().withKeyword("дача квартира -гостиница").withId(2L));

        DeduplicateResponse actual =
                api.userSteps.keywordsResearchSteps().keywordsResearchDeduplicateRawResponse(CLIENT, request);

        DeduplicateResponse expected = new DeduplicateResponse();

        assertThat("Ключевые фразы не должны склеиваться", actual, beanEquivalent(expected));
    }

    @Test
    public void noGlueWhenDifferentPlusWordsWithSameNormalizedValueTest() {
        DeduplicateRequestMap request = new DeduplicateRequestMap()
                .withOperations(DeduplicateOperationEnum.ELIMINATE_OVERLAPPING)
                .withKeywords(
                    new DeduplicateRequestItemMap().withKeyword("окна на заказ -дешево").withId(1L),
                    new DeduplicateRequestItemMap().withKeyword("заказ окон -жалюзи").withId(2L));

        DeduplicateResponse actual =
                api.userSteps.keywordsResearchSteps().keywordsResearchDeduplicateRawResponse(CLIENT, request);

        DeduplicateResponse expected = new DeduplicateResponse();

        assertThat("Ключевые фразы не должны склеиваться", actual, beanEquivalent(expected));
    }

    @Test
    public void minusWordsReturnInOriginalStateTest() {
        DeduplicateRequestMap request = new DeduplicateRequestMap()
                .withOperations(DeduplicateOperationEnum.ELIMINATE_OVERLAPPING)
                .withKeywords(new DeduplicateRequestItemMap().withKeyword("куплю -слона"));

        DeduplicateResponse actual =
                api.userSteps.keywordsResearchSteps().keywordsResearchDeduplicateRawResponse(CLIENT, request);

        DeduplicateResponse expected = new DeduplicateResponse();

        DeduplicateResponseAddItem keyword = new DeduplicateResponseAddItem();
        keyword.setKeyword("куплю -слона");

        expected.setAdd(singletonList(keyword));

        assertThat("Минус-слова возвращаются в исходной форме", actual, beanEquivalent(expected));
    }

    @Test
    public void minusWordsReturnInOriginalStateWhenUngluedTest() {
        DeduplicateRequestMap request = new DeduplicateRequestMap()
                .withOperations(DeduplicateOperationEnum.ELIMINATE_OVERLAPPING)
                .withKeywords(
                        new DeduplicateRequestItemMap().withKeyword("куплю слона").withId(1L),
                        new DeduplicateRequestItemMap().withKeyword("куплю индийского слона").withId(2L));

        DeduplicateResponse actual =
                api.userSteps.keywordsResearchSteps().keywordsResearchDeduplicateRawResponse(CLIENT, request);

        DeduplicateResponse expected = new DeduplicateResponse();

        DeduplicateResponseUpdateItem keyword = new DeduplicateResponseUpdateItem();

        keyword.setKeyword("куплю слона -индийского");
        keyword.setId(1L);

        expected.setUpdate(singletonList(keyword));

        assertThat("Минус-слова возвращаются в исходной форме после расклейки", actual,
                beanEquivalent(expected));
    }

    @Test
    public void weightTest() {
        DeduplicateRequestMap request = new DeduplicateRequestMap()
                .withOperations(DeduplicateOperationEnum.ELIMINATE_OVERLAPPING)
                .withKeywords(
                    new DeduplicateRequestItemMap().withKeyword("ключевая").withId(1L).withWeight(3L),
                    new DeduplicateRequestItemMap().withKeyword("ключевая фраза").withId(2L).withWeight(2L),
                    new DeduplicateRequestItemMap().withKeyword("ключевая -фраза").withId(3L).withWeight(1L));

        DeduplicateResponse actual =
                api.userSteps.keywordsResearchSteps().keywordsResearchDeduplicateRawResponse(CLIENT, request);

        DeduplicateResponse expected = new DeduplicateResponse();

        DeduplicateResponseUpdateItem update = new DeduplicateResponseUpdateItem();
        update.setKeyword("ключевая -фраза");
        update.setId(1L);

        IdsCriteria ids = new IdsCriteria();
        ids.setIds(singletonList(3L));

        expected.setUpdate(singletonList(update));
        expected.setDelete(ids);

        assertThat("Веса обрабатываются корректно", actual, beanEquivalent(expected));
    }

    @Test
    public void anotherWeightsWeightTest() {
        DeduplicateRequestMap request = new DeduplicateRequestMap()
                .withOperations(DeduplicateOperationEnum.ELIMINATE_OVERLAPPING)
                .withKeywords(
                        new DeduplicateRequestItemMap().withKeyword("ключевая").withId(1L).withWeight(1L),
                        new DeduplicateRequestItemMap().withKeyword("ключевая фраза").withId(2L).withWeight(2L),
                        new DeduplicateRequestItemMap().withKeyword("ключевая -фраза").withId(3L).withWeight(3L));

        DeduplicateResponse actual =
                api.userSteps.keywordsResearchSteps().keywordsResearchDeduplicateRawResponse(CLIENT, request);

        DeduplicateResponse expected = new DeduplicateResponse();

        IdsCriteria ids = new IdsCriteria();
        ids.setIds(singletonList(1L));

        expected.setDelete(ids);

        assertThat("Веса обрабатываются корректно", actual, beanEquivalent(expected));
    }
}
