package ru.yandex.autotests.direct.api.bidmodifiers.get.regional;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

import com.yandex.direct.api.v5.bidmodifiers.BidModifierGetItem;
import com.yandex.direct.api.v5.bidmodifiers.BidModifierTypeEnum;
import org.junit.Before;
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.bidmodifiers.BidModifiersFeatures;
import ru.yandex.autotests.direct.api.bidmodifiers.BidModifiersLogins;
import ru.yandex.autotests.direct.db.models.jooq.ppc.tables.records.GeoMultiplierValuesRecord;
import ru.yandex.autotests.direct.db.models.jooq.ppc.tables.records.HierarchicalMultipliersRecord;
import ru.yandex.autotests.direct.db.steps.DirectJooqDbSteps;
import ru.yandex.autotests.direct.utils.model.RegionIDValues;
import ru.yandex.autotests.directapi.apiclient.config.Semaphore;
import ru.yandex.autotests.directapi.model.Logins;
import ru.yandex.autotests.directapi.model.api5.bidmodifiers.BidModifierAddMap;
import ru.yandex.autotests.directapi.model.api5.bidmodifiers.RegionalAdjustmentMap;
import ru.yandex.autotests.directapi.rules.ApiSteps;
import ru.yandex.autotests.directapi.rules.Trashman;
import ru.yandex.autotests.irt.testutils.allure.TestSteps;
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.hazelcast.SemaphoreRule;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.core.IsCollectionContaining.hasItem;
import static ru.yandex.autotests.directapi.model.api5.bidmodifiers.RegionalAdjustmentMap.REGIONAL_ADJUSTMENT_MAX;
import static ru.yandex.autotests.directapi.model.api5.bidmodifiers.RegionalAdjustmentMap.REGIONAL_ADJUSTMENT_MIN;
import static ru.yandex.autotests.irt.testutils.allure.TestSteps.assumeThat;

@Aqua.Test
@Features(BidModifiersFeatures.GET)
@RunWith(Parameterized.class)
@Issue("https://st.yandex-team.ru/DIRECT-67328")
@Description("Проверка невозможности получения скрытой корректировки для Крыма")
public class GetHiddenBidModifierForCrimeaTest {

    private static final Integer modifierIsHidden = 1;

    private static final Long russiaGeoId = Long.valueOf(RegionIDValues.RUSSIA.getId());
    private static final Long ukraineGeoId = Long.valueOf(RegionIDValues.UKRAINE.getId());
    private static final Long crimeaGeoId = Long.valueOf(RegionIDValues.CRIMEA.getId());

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

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

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

    @Parameterized.Parameter
    public String description;

    @Parameterized.Parameter(1)
    public String client;

    @Parameterized.Parameter(2)
    public Long homeRegionId;

    private Long campaignId;
    private Long hiddenGeoMultiplierId;
    private DirectJooqDbSteps jooqSteps;

    @Parameterized.Parameters(name = "{0}")
    public static Collection testData() {
        Object[][] data = new Object[][]{
                {"Клиент из России", BidModifiersLogins.SINGLE_CLIENT_ADD, russiaGeoId},
                {"Клиент из Украины", Logins.LOGIN_FOR_UAH, ukraineGeoId},
        };
        return Arrays.asList(data);
    }

    @Before
    public void prepare() {
        api.userSteps.clientFakeSteps().fakeClearClientSpentUnits(client);

        campaignId = api.userSteps.campaignSteps().addDefaultTextCampaign(client);

        List<Long> bmIds = api.as(client).userSteps.bidModifiersSteps().bidModifiersAdd(new BidModifierAddMap()
                .withRegionalAdjustment(new RegionalAdjustmentMap().withBidModifier(REGIONAL_ADJUSTMENT_MIN)
                        .withRegionId(homeRegionId)).withCampaignId(campaignId));
        assumeThat("добавлена 1 гео корректировка", bmIds, hasSize(1));

        jooqSteps = api.userSteps.getDirectJooqDbSteps();
        jooqSteps.useShardForLogin(client);

        List<HierarchicalMultipliersRecord> multipliers =
                jooqSteps.multipliersSteps().getHierarchicalMultipliersByCid(campaignId);
        assumeThat("в бд 1 иерархическая корректировка", multipliers, hasSize(1));

        Long hierarchicalMultiplierId = multipliers.get(0).getHierarchicalMultiplierId().longValue();

        List<GeoMultiplierValuesRecord> geoMultipliers = jooqSteps.multipliersSteps()
                .getGeoMultiplierValuesByHierarchicalMultipliersId(hierarchicalMultiplierId);
        assumeThat("в бд 2 гео корректировки", geoMultipliers, hasSize(2));
        assumeThat("есть корректировка для Крыма",
                geoMultipliers.stream().map(GeoMultiplierValuesRecord::getRegionId).collect(Collectors.toList()),
                hasItem(equalTo(crimeaGeoId)));
        TestSteps.assertThat("скрытая корректировка для Крыма",
                geoMultipliers.stream().filter(e -> e.getRegionId().equals(crimeaGeoId))
                        .map(GeoMultiplierValuesRecord::getIsHidden).collect(Collectors.toList()),
                contains(equalTo(modifierIsHidden)));

        Long hiddenGeoMultiplierInternalId =
                geoMultipliers.stream().filter(e -> e.getIsHidden() == 1)
                        .map(GeoMultiplierValuesRecord::getGeoMultiplierValueId).collect(Collectors.toList()).get(0)
                        .longValue();
        hiddenGeoMultiplierId = Long.valueOf("13" + Long.toString(hiddenGeoMultiplierInternalId));
    }

    @Test
    @Description("Скрытую корректировку на Крым нельзя получить по id кампании")
    public void testCantGetHiddenModifierForCrimeaByCid() {
        List<BidModifierGetItem> bidModifiers =
                api.as(client).userSteps.bidModifiersSteps().bidModifiersGetByCampaignId(campaignId);
        assumeThat("вернулась 1 гео корректировка", bidModifiers, hasSize(1));
        assertThat("нет корректировки для Крыма",
                bidModifiers.stream().filter(e -> e.getType().equals(BidModifierTypeEnum.REGIONAL_ADJUSTMENT))
                        .filter(e -> e.getRegionalAdjustment().getRegionId().equals(crimeaGeoId))
                        .collect(Collectors.toList()), hasSize(0));
    }

    @Test
    @Description("Cкрытую корректировку на Крым нельзя получить по id")
    public void testCantGetHiddenModifierForCrimeaById() {
        List<BidModifierGetItem> bidModifiers =
                api.as(client).userSteps.bidModifiersSteps().bidModifiersGetById(hiddenGeoMultiplierId);
        assertThat("не вернулось ни одной корректировки", bidModifiers, hasSize(0));
    }

    @Test
    @Description("Явную корректировку на Крым можно получить по id кампании")
    public void testCanGetModifierForCrimeaByCid() {
        List<Long> bmIds = api.as(client).userSteps.bidModifiersSteps().bidModifiersAdd(new BidModifierAddMap()
                .withRegionalAdjustment(new RegionalAdjustmentMap().withBidModifier(REGIONAL_ADJUSTMENT_MAX)
                        .withRegionId(crimeaGeoId)).withCampaignId(campaignId));
        assumeThat("добавлена 1 гео корректировка", bmIds, hasSize(1));

        List<BidModifierGetItem> bidModifiers =
                api.userSteps.bidModifiersSteps().bidModifiersGetByCampaignId(campaignId);
        assumeThat("вернулись 2 гео корректировки", bidModifiers, hasSize(2));
        assertThat("есть ожидаемая корректировки для Крыма",
                bidModifiers.stream().filter(e -> e.getType().equals(BidModifierTypeEnum.REGIONAL_ADJUSTMENT))
                        .filter(e -> e.getRegionalAdjustment().getRegionId().equals(crimeaGeoId))
                        .map(e -> e.getRegionalAdjustment().getBidModifier())
                        .collect(Collectors.toList()), contains(equalTo(REGIONAL_ADJUSTMENT_MAX)));
    }

    @Test
    @Description("Явную корректировку на Крым можно получить по id")
    public void testCanGetModifierForCrimeaById() {
        List<Long> bmIds = api.as(client).userSteps.bidModifiersSteps().bidModifiersAdd(new BidModifierAddMap()
                .withRegionalAdjustment(new RegionalAdjustmentMap().withBidModifier(REGIONAL_ADJUSTMENT_MAX)
                        .withRegionId(crimeaGeoId)).withCampaignId(campaignId));
        assumeThat("добавлена 1 гео корректировка", bmIds, hasSize(1));

        List<BidModifierGetItem> bidModifiers = api.userSteps.bidModifiersSteps().bidModifiersGetById(bmIds.get(0));
        assumeThat("вернулась 1 гео корректировка", bidModifiers, hasSize(1));
        assertThat("вернулась ожидаемая корректировки для Крыма",
                bidModifiers.stream().filter(e -> e.getType().equals(BidModifierTypeEnum.REGIONAL_ADJUSTMENT))
                        .filter(e -> e.getRegionalAdjustment().getRegionId().equals(crimeaGeoId))
                        .map(e -> e.getRegionalAdjustment().getBidModifier())
                        .collect(Collectors.toList()), contains(equalTo(REGIONAL_ADJUSTMENT_MAX)));
    }
}
