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

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;

import com.yandex.direct.api.v5.audiencetargets.AddResponse;
import com.yandex.direct.api.v5.audiencetargets.AudienceTargetAddItem;
import com.yandex.direct.api.v5.audiencetargets.AudienceTargetSetBidsItem;
import com.yandex.direct.api.v5.audiencetargets.SetBidsRequest;
import com.yandex.direct.api.v5.audiencetargets.SetBidsResponse;
import com.yandex.direct.api.v5.general.ActionResult;
import com.yandex.direct.api.v5.general.SetBidsActionResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import ru.yandex.direct.api.v5.converter.ResultConverter;
import ru.yandex.direct.api.v5.result.ApiResult;
import ru.yandex.direct.core.entity.bids.container.SetBidItem;
import ru.yandex.direct.core.entity.bids.container.ShowConditionType;
import ru.yandex.direct.core.entity.retargeting.model.TargetInterest;
import ru.yandex.direct.validation.result.PathConverter;

import static ru.yandex.direct.api.v5.common.ConverterUtils.convertStrategyPriority;
import static ru.yandex.direct.api.v5.common.ConverterUtils.convertToDbPrice;
import static ru.yandex.direct.utils.FunctionalUtils.mapList;

@Component
@ParametersAreNonnullByDefault
public class AudienceTargetsHelperConverter {
    private static final Logger logger = LoggerFactory.getLogger(AudienceTargetsHelperConverter.class);
    private final ResultConverter resultConverter;

    @Autowired
    public AudienceTargetsHelperConverter(ResultConverter resultConverter) {
        this.resultConverter = resultConverter;
    }

    public List<TargetInterest> convertAddRequest(List<AudienceTargetAddItem> audienceTargets) {
        return mapList(audienceTargets,
                at -> at == null ? null : new TargetInterest()
                        .withAdGroupId(at.getAdGroupId())
                        .withRetargetingConditionId(at.getRetargetingListId())
                        .withInterestId(at.getInterestId())
                        .withPriceContext(convertToDbPrice(at.getContextBid()))
                        .withAutobudgetPriority(convertStrategyPriority(at.getStrategyPriority()))
        );
    }

    /**
     * Конвертирует запрос из объектного представления JSON'а во внутренние сущности-контейнеры
     *
     * @param setBidsRequest Запрос, пришедший от пользователя
     * @return Набор бидов, содержащих данные запроса польлзователя
     */
    public List<SetBidItem> convertSetBidsRequest(SetBidsRequest setBidsRequest) {
        if (setBidsRequest.getBids() == null) {
            return new ArrayList<>();
        }
        return mapList(setBidsRequest.getBids(), this::convertSetBidsItem);
    }

    /**
     * Конвертирует ответ сервиса из внутренних сущностей в объектное представление JSON
     *
     * @param result           результат выполнения операции внутренним сервисом
     * @param apiPathConverter конвертер путей
     * @return ответ, отправляемый пользователю
     */
    public SetBidsResponse convertToSetBidsResponse(ApiResult<List<ApiResult<SetBidItem>>> result,
                                                    PathConverter apiPathConverter) {
        List<SetBidsActionResult> results = mapList(result.getResult(),
                r -> convertSetBidsResult(r, apiPathConverter));
        logger.debug("list of SetBids results: {}", results);
        return new SetBidsResponse().withSetBidsResults(results);
    }

    public AddResponse convertAddResponse(
            ApiResult<List<ApiResult<Long>>> result,
            PathConverter apiPathConverter) {
        List<ActionResult> addResults = mapList(result.getResult(), r -> convertAddResult(r, apiPathConverter));
        logger.debug("list of AddResult: {}", addResults);
        return new AddResponse().withAddResults(addResults);
    }

    private ActionResult convertAddResult(ApiResult<Long> source,
                                          PathConverter apiPathConverter) {
        return resultConverter.convertToActionResult(source, apiPathConverter);
    }

    private SetBidItem convertSetBidsItem(@Nullable AudienceTargetSetBidsItem item) {
        if (item == null) {
            return null;
        }

        return new SetBidItem()
                .withShowConditionType(ShowConditionType.AUDIENCE_TARGET)
                .withPriceContext(convertToDbPrice(item.getContextBid()))
                .withId(item.getId())
                .withAdGroupId(item.getAdGroupId())
                .withCampaignId(item.getCampaignId())
                .withAutobudgetPriority(convertStrategyPriority(item.getStrategyPriority()));
    }

    private SetBidsActionResult convertSetBidsResult(ApiResult<SetBidItem> result,
                                                     PathConverter apiPathConverter) {
        return resultConverter.convertToSetBidsActionResult(result, apiPathConverter);
    }
}
