package ru.yandex.direct.web.entity.useractionlog;

import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.annotation.ParametersAreNonnullByDefault;

import org.dataloader.DataLoader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;

import ru.yandex.direct.core.entity.retargeting.repository.RetargetingGoalsPpcDictRepository;
import ru.yandex.direct.core.entity.retargeting.service.common.GoalUtilsService;

/**
 * DataLoader, который получает GoalView на основе ppcdict.metrika_goals.goal_id.
 */
@Component
@ParametersAreNonnullByDefault
// Обязательно должен иметь какой-нибудь Scope, не связанный с постоянно живущими синглтонами. Внутри DataLoader'ов
// встроен топорный вечный невытесняющий кеш, который, впрочем, полезен в пределах одного HTTP-запроса.
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class GoalViewByIdDataLoader extends DataLoader<Long, GoalView> {
    @Autowired
    public GoalViewByIdDataLoader(RetargetingGoalsPpcDictRepository retargetingGoalsPpcDictRepository) {
        super(ids -> {
            Map<Long, GoalView> goalViewById = retargetingGoalsPpcDictRepository
                    .getMetrikaGoalsFromPpcDict(ids.stream().filter(i -> i != 0).collect(Collectors.toSet()))
                    .stream()
                    .map(GoalUtilsService::changeEcommerceGoalName)
                    .map(GoalView::new)
                    .collect(Collectors.toMap(g -> g.id, Function.identity()));
            return CompletableFuture.completedFuture(ids.stream()
                    // Непонятно как быть в случае, если объект ссылается на цель, которой нет в базе.
                    // Такое случается на тестовой среде, где база неконсистентная.
                    .map(id -> goalViewById.getOrDefault(id, GoalView.NO_GOAL))
                    .collect(Collectors.toList()));
        });
    }
}
