package ru.yandex.autotests.direct.api.adgroups.add.negativekeywords;

import java.util.Arrays;
import java.util.Collection;

import org.apache.commons.lang3.RandomStringUtils;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import ru.yandex.aqua.annotations.project.Aqua;
import ru.yandex.autotests.direct.api.adgroups.AdGroupsFeatures;
import ru.yandex.autotests.direct.api.adgroups.AdGroupsLogins;
import ru.yandex.autotests.direct.utils.tags.TagDictionary;
import ru.yandex.autotests.directapi.apiclient.config.Semaphore;
import ru.yandex.autotests.directapi.apiclient.errors.Api5ErrorDetails;
import ru.yandex.autotests.directapi.apiclient.errors.Api5ErrorDetailsJava;
import ru.yandex.autotests.directapi.model.api5.adgroups.AdGroupAddItemMap;
import ru.yandex.autotests.directapi.model.api5.adgroups.AddRequestMap;
import ru.yandex.autotests.directapi.model.api5.general.ExpectedResult;
import ru.yandex.autotests.directapi.model.api5.general.Notification;
import ru.yandex.autotests.directapi.rules.ApiSteps;
import ru.yandex.autotests.directapi.rules.Trashman;
import ru.yandex.autotests.directapi.steps.banners.KeywordPhraseGenerator;
import ru.yandex.autotests.directapi.steps.banners.KeywordsSteps;
import ru.yandex.qatools.Tag;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.hazelcast.SemaphoreRule;

/**
 * Author pavryabov
 * Date 17.10.14
 * https://st.yandex-team.ru/TESTIRT-2022
 */
@Aqua.Test
@Features(AdGroupsFeatures.ADD)
@Tag(TagDictionary.TRUNK)
@RunWith(Parameterized.class)
public class AddNegativeKeywordsNegativeTest {

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

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

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

    @Parameterized.Parameter(0)
    public String description;

    @Parameterized.Parameter(1)
    public String[] negativeKeywords;

    @Parameterized.Parameter(2)
    public ExpectedResult expectedResultJava;

    private static final Integer[] manyMaxLengths;

    static {
        manyMaxLengths = new Integer[10];
        Arrays.fill(manyMaxLengths, KeywordsSteps.MINUS_WORD_MAX_LENGTH + 1);
    }

    @Parameterized.Parameters(name = "{0}")
    public static Collection testData() {
        KeywordPhraseGenerator keywordPhraseGenerator =
                new KeywordPhraseGenerator(KeywordsSteps.CYRILLIC_CHARS_NO_SPACE);

        KeywordPhraseGenerator.Result oneKeywordWithTooManyCharacters =
                keywordPhraseGenerator.generatePhraseWithPlusAndMinusWords(
                        new Integer[0],
                        new Integer[]{KeywordsSteps.MINUS_WORD_MAX_LENGTH + 1});

        KeywordPhraseGenerator.Result twoKeywordsWithTooManyCharacters =
                keywordPhraseGenerator.generatePhraseWithPlusAndMinusWords(
                        new Integer[0],
                        new Integer[]{KeywordsSteps.MINUS_WORD_MAX_LENGTH + 1,
                                KeywordsSteps.MINUS_WORD_MAX_LENGTH + 1});

        KeywordPhraseGenerator.Result manyKeywordsWithTooManyCharacters =
                keywordPhraseGenerator.generatePhraseWithPlusAndMinusWords(
                        new Integer[0], manyMaxLengths);

        KeywordPhraseGenerator.Result manyKeywordsWithTotalLengthOneCharacterOverMaximum =
                keywordPhraseGenerator.generatePhraseWithPlusAndMinusWords(
                        new Integer[0],
                        KeywordPhraseGenerator.minusWordLengthsWithSpecificTotalLength(
                                KeywordsSteps.MINUS_WORD_MAX_LENGTH,
                                KeywordsSteps.MINUS_WORD_MAX_LENGTH,
                                AdGroupAddItemMap.MAX_NEGATIVE_KEYWORDS_LENGTH + 1
                        ).toArray(new Integer[0]));

        String negativeKeywordWithAverageLength =
                RandomStringUtils.randomAlphabetic(KeywordsSteps.ACCEPTABLE_KEYWORD_LENGTH);

        Object[][] data = new Object[][]{
                {"One keyword with too many characters",
                        oneKeywordWithTooManyCharacters.minusWordArray(),
                        ExpectedResult.errors(new Notification(5162,
                                Api5ErrorDetailsJava.LENGTH_OF_NEGATIVE_KEYWORDS_LONGER_THAN,
                                KeywordsSteps.KEYWORD_MAX_LENGTH,
                                oneKeywordWithTooManyCharacters.commaSeparatedMinusWords()))},
                {"Two keywords with too many characters",
                        twoKeywordsWithTooManyCharacters.minusWordArray(),
                        ExpectedResult.errors(new Notification(5162,
                                Api5ErrorDetailsJava.LENGTH_OF_NEGATIVE_KEYWORDS_LONGER_THAN,
                                KeywordsSteps.KEYWORD_MAX_LENGTH,
                                twoKeywordsWithTooManyCharacters.commaSeparatedMinusWords()))},

                // DIRECT-57575
                {"Many keywords with too many characters",
                        manyKeywordsWithTooManyCharacters.minusWordArray(),
                        ExpectedResult.errors(new Notification(5162,
                                Api5ErrorDetailsJava.LENGTH_OF_NEGATIVE_KEYWORDS_LONGER_THAN,
                                KeywordsSteps.KEYWORD_MAX_LENGTH,
                                manyKeywordsWithTooManyCharacters.commaSeparatedMinusWords()))},
                {"Many keywords with total length one character over maximum",
                        manyKeywordsWithTotalLengthOneCharacterOverMaximum.minusWordArray(),
                        ExpectedResult.errors(new Notification(5001,
                                Api5ErrorDetails.MINUS_PHRASES_LENGHT_MORE_THAN,
                                AdGroupAddItemMap.MAX_NEGATIVE_KEYWORDS_LENGTH))},
                {"One keyword with not many characters and [",
                        new String[]{negativeKeywordWithAverageLength + "["},
                        ExpectedResult.errors(new Notification(5002,
                                Api5ErrorDetails.INCORRECT_USE_OF_BRACKETS_IN_MINUS_PHRASE,
                                negativeKeywordWithAverageLength + "["))},
                {"[test", new String[]{"[test"},
                        ExpectedResult.errors(new Notification(5002,
                                Api5ErrorDetails.INCORRECT_USE_OF_BRACKETS_IN_MINUS_PHRASE, "[test"))},
                {"te+st", new String[]{"te+st"},
                        ExpectedResult.errors(new Notification(5002,
                                Api5ErrorDetails.INCORRECT_USE_OF_SYMBOL_IN_MINUS_PHRASE, "+", "te+st"))},
                {"te!st", new String[]{"te!st"},
                        ExpectedResult.errors(new Notification(5002,
                                Api5ErrorDetails.INCORRECT_USE_OF_SYMBOL_IN_MINUS_PHRASE, "!", "te!st"))},
                {"test+", new String[]{"test+"},
                        ExpectedResult.errors(new Notification(5002,
                                Api5ErrorDetails.INCORRECT_USE_OF_SYMBOL_IN_MINUS_PHRASE, "+", "test+"))},
                {"test!", new String[]{"test!"},
                        ExpectedResult.errors(new Notification(5002,
                                Api5ErrorDetails.INCORRECT_USE_OF_SYMBOL_IN_MINUS_PHRASE, "!", "test!"))},
                {"+ test", new String[]{"+ test"},
                        ExpectedResult.errors(new Notification(5002,
                                Api5ErrorDetails.INCORRECT_USE_OF_SYMBOL_IN_MINUS_PHRASE, "+", "+ test"))},
                {"++test", new String[]{"++test"},
                        ExpectedResult.errors(new Notification(5002,
                                Api5ErrorDetails.INCORRECT_USE_OF_SYMBOL_IN_MINUS_PHRASE, "+", "++test"))},
                {"te!st, te-st", new String[]{"te!st", "te-st"},
                        ExpectedResult.errors(new Notification(5002,
                                Api5ErrorDetails.INCORRECT_USE_OF_SYMBOL_IN_MINUS_PHRASE, "!", "te!st"))},
                {",test", new String[]{",test"},
                        ExpectedResult.errors(new Notification(5002,
                                Api5ErrorDetailsJava.MINUS_PHRASES_CAN_ONLY_CONSIST, ",test"))},
                {"te,st", new String[]{"te,st"},
                        ExpectedResult.errors(new Notification(5002,
                                Api5ErrorDetailsJava.MINUS_PHRASES_CAN_ONLY_CONSIST, "te,st"))},
                {"test,", new String[]{"test,"},
                        ExpectedResult.errors(new Notification(5002,
                                Api5ErrorDetailsJava.MINUS_PHRASES_CAN_ONLY_CONSIST, "test,"))},
                {"-test", new String[]{"-test"},
                        ExpectedResult.errors(new Notification(5002,
                                Api5ErrorDetails.INCORRECT_USE_OF_SYMBOL_IN_START_OR_END_OF_MINUS_PHRASE, "-",
                                "-test"))},
                {"test-", new String[]{"test-"},
                        ExpectedResult.errors(new Notification(5002,
                                Api5ErrorDetails.INCORRECT_USE_OF_SYMBOL_IN_START_OR_END_OF_MINUS_PHRASE, "-",
                                "test-"))},
                //DIRECT-60708
                {".test", new String[]{".test"},
                        ExpectedResult.errors(new Notification(5002,
                                Api5ErrorDetails.MINUS_PHRASES_COULD_NOT_START_WITH_DOT_OR_APOSTROPHE, ".test"))},
                {"10.10.10", new String[]{"10.10.10"},
                        ExpectedResult.errors(new Notification(5002,
                                Api5ErrorDetails.MINUS_PHRASES_CANNOT_CONTAIN_MORE_THAN_TWO_NUMBERS, "10.10.10"))}
        };
        return Arrays.asList(data);
    }

    private static AdGroupAddItemMap adGroupAddItemMap;

    @BeforeClass
    public static void createCampaign() {
        Long campaignId = api.userSteps.campaignSteps().addDefaultTextCampaign(AdGroupsLogins.CLIENT);
        adGroupAddItemMap = new AdGroupAddItemMap().defaultAdGroupAddItem(campaignId);
    }

    @Before
    public void clearSpentUnits() {
        api.userSteps.clientFakeSteps().fakeClearClientSpentUnits(AdGroupsLogins.CLIENT);
    }

    @Test
    @ru.yandex.qatools.allure.annotations.TestCaseId("1622")
    public void addGroupWithNegativeKeywords() {
        //DIRECT-34506
        //DIRECT-34529
        api.userSteps.adGroupsSteps().shouldGetResultOnAdd(
                new AddRequestMap().withAdGroups(
                        adGroupAddItemMap.withNegativeKeywords(negativeKeywords)),
                expectedResultJava);
    }
}
