package ru.yandex.direct.api.v5.entity.smartadtargets.converter;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

import javax.annotation.ParametersAreNonnullByDefault;

import com.yandex.direct.api.v5.smartadtargets.SmartAdTargetAddItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import ru.yandex.direct.api.v5.common.ConverterUtils;
import ru.yandex.direct.core.entity.feed.model.BusinessType;
import ru.yandex.direct.core.entity.feed.model.Feed;
import ru.yandex.direct.core.entity.feed.model.FeedType;
import ru.yandex.direct.core.entity.feed.model.Source;
import ru.yandex.direct.core.entity.feed.service.FeedService;
import ru.yandex.direct.core.entity.performancefilter.model.PerformanceFilter;
import ru.yandex.direct.core.entity.performancefilter.model.PerformanceFilterCondition;
import ru.yandex.direct.core.entity.performancefilter.model.PerformanceFilterTab;
import ru.yandex.direct.core.entity.performancefilter.model.TargetFunnel;
import ru.yandex.direct.core.entity.performancefilter.schema.FilterSchema;
import ru.yandex.direct.core.entity.performancefilter.service.PerformanceFilterStorage;
import ru.yandex.direct.dbutil.model.ClientId;

import static ru.yandex.direct.api.v5.common.ConverterUtils.convertToDbPrice;
import static ru.yandex.direct.api.v5.entity.smartadtargets.converter.CommonConverters.FUNNEL_BY_AUDIENCE;
import static ru.yandex.direct.api.v5.entity.smartadtargets.converter.RequestConverter.getPerformanceFilterConditions;
import static ru.yandex.direct.api.v5.entity.smartadtargets.converter.RequestConverter.getTab;
import static ru.yandex.direct.utils.CommonUtils.ifNotNull;
import static ru.yandex.direct.utils.FunctionalUtils.mapList;

@ParametersAreNonnullByDefault
@Service
public class AddRequestConverterService {

    private final FeedService feedService;
    private final PerformanceFilterStorage performanceFilterStorage;

    @Autowired
    public AddRequestConverterService(FeedService feedService, PerformanceFilterStorage performanceFilterStorage) {
        this.feedService = feedService;
        this.performanceFilterStorage = performanceFilterStorage;
    }


    public List<PerformanceFilter> convertItemsToModels(ClientId clientId, List<SmartAdTargetAddItem> smartAdTargets) {
        List<Long> adGroupIds = mapList(smartAdTargets, SmartAdTargetAddItem::getAdGroupId);
        Map<Long, Feed> feedByAdGroupId = feedService.getFeedByPerformanceAdGroupId(clientId, adGroupIds);
        return mapList(smartAdTargets, item -> convertItemToModel(feedByAdGroupId, item));
    }

    private PerformanceFilter convertItemToModel(Map<Long, Feed> feedByAdGroupId, SmartAdTargetAddItem item) {
        Feed feed = feedByAdGroupId.get(item.getAdGroupId());
        BusinessType businessType = feed.getBusinessType();
        FeedType feedType = feed.getFeedType();
        Source source = feed.getSource();
        FilterSchema filterSchema = performanceFilterStorage.getFilterSchema(businessType, feedType, source);
        List<PerformanceFilterCondition> conditions =
                getPerformanceFilterConditions(filterSchema, item.getAvailableItemsOnly(), item.getConditions());
        PerformanceFilterTab tab = getTab(conditions);
        TargetFunnel targetFunnel = ifNotNull(item.getAudience(), FUNNEL_BY_AUDIENCE::get);
        Integer autoBudgetPriority = ifNotNull(item.getStrategyPriority(), ConverterUtils::convertStrategyPriority);
        BigDecimal priceCpc = convertToDbPrice(item.getAverageCpc());
        BigDecimal priceCpa = convertToDbPrice(item.getAverageCpa());
        return new PerformanceFilter()
                .withPid(item.getAdGroupId())
                .withName(item.getName())
                .withTargetFunnel(targetFunnel)
                .withPriceCpc(priceCpc)
                .withPriceCpa(priceCpa)
                .withAutobudgetPriority(autoBudgetPriority)
                .withBusinessType(businessType)
                .withFeedType(feedType)
                .withSource(source)
                .withConditions(conditions)
                .withTab(tab)
                .withIsDeleted(false)
                .withIsSuspended(false);
    }

}
