package ru.yandex.autotests.directapi.retargetinglists;

import java.lang.reflect.Field;
import java.util.List;
import java.util.stream.Stream;

import com.yandex.direct.api.v5.general.IdsCriteria;
import com.yandex.direct.api.v5.retargetinglists.GetResponse;
import com.yandex.direct.api.v5.retargetinglists.RetargetingListFieldEnum;
import com.yandex.direct.api.v5.retargetinglists.RetargetingListGetItem;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

import ru.yandex.autotests.directapi.apiclient.config.Semaphore;
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.retargetinglists.DeleteRequestMap;
import ru.yandex.autotests.directapi.model.api5.retargetinglists.GetRequestMap;
import ru.yandex.autotests.directapi.model.api5.retargetinglists.RetargetingListSelectionCriteriaMap;
import ru.yandex.autotests.directapi.rules.ApiSteps;
import ru.yandex.autotests.directapi.rules.Trashman;
import ru.yandex.qatools.hazelcast.SemaphoreRule;

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;

/**
 * Класс для очистки всех клиентов, чьи логины перечислены в {@link RetargetingListsLogins}.
 *
 * Если у клиента есть ретаргетинги, все его кампании, доступные к удалению, будут удалены,
 * затем будут удалены ретаргетинги.
 *
 * Если у клиента отсутствуют ретаргетинги, с ним ничего не произойдёт.
 */
@RunWith(Parameterized.class)
public class ClearAllRetargetingListsTestClients {

    @ClassRule
    public static ApiSteps api = new ApiSteps();

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

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

    @Parameter
    public String login;

    @Parameters(name = "login = {0}")
    public static Iterable<Object[]> params() {
        return getAllRetargetingLogins()
                .map(clientLogin -> new Object[]{clientLogin})
                .collect(toSet());
    }

    private static Stream<String> getAllRetargetingLogins() {
        return Stream.of(RetargetingListsLogins.class.getDeclaredFields())
                .filter(f -> f.getType().equals(String.class))
                .map(ClearAllRetargetingListsTestClients::getValueOfStaticStringField);
    }

    private static String getValueOfStaticStringField(Field field) {
        try {
            return String.class.cast(field.get(null));
        } catch (IllegalAccessException ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * ACHTUNG! Все кампании клиентов, доступные к удалению, будут удалены.
     */
    @Test
    public void deleteUserRetargetings() {
        List<Long> ids = getUserRetargetingsIds();
        if (ids.isEmpty()) {
            return;
        }

        flushAllCampaignsWithNoAssumptionsAndSuppressingExceptions();

        api.userSteps.retargetingListsSteps().shouldGetResultOnDelete(
                deleteRequest(ids),
                ids.stream().map(ExpectedResult::success).toArray(ExpectedResult[]::new));
    }

    private static DeleteRequestMap deleteRequest(List<Long> ids) {
        IdsCriteria ic = new IdsCriteria();
        ic.setIds(ids);
        return new DeleteRequestMap().withSelectionCriteria(new IdsCriteriaMap(ic));
    }

    private List<Long> getUserRetargetingsIds() {
        GetResponse getResponse = api.as(login).userSteps.retargetingListsSteps().retargetingListsGet(
                new GetRequestMap()
                        .withFieldNames(RetargetingListFieldEnum.ID)
                        .withSelectionCriteria(new RetargetingListSelectionCriteriaMap()));
        return getResponse.getRetargetingLists().stream().map(RetargetingListGetItem::getId).collect(toList());
    }

    private void flushAllCampaignsWithNoAssumptionsAndSuppressingExceptions() {
        try {
            List<Long> ids = api.as(login).userSteps.campaignSteps().getAllCampaignIds();
            if (!ids.isEmpty()) {
                Long[] idsArray = ids.toArray(new Long[ids.size()]);
                api.userSteps.campaignSteps().campaignsDelete(login, idsArray);
            }
        } catch (RuntimeException ex) {
            // ignore
        }
    }

}
