package ru.yandex.canvas.service.direct;

import java.util.List;
import java.util.Map;
import java.util.Objects;

import one.util.streamex.StreamEx;

import ru.yandex.canvas.model.CreativeDocument;
import ru.yandex.canvas.model.direct.CreativeUploadData;
import ru.yandex.canvas.model.direct.ModerationInfo;
import ru.yandex.canvas.model.elements.Element;
import ru.yandex.canvas.model.elements.ElementType;
import ru.yandex.canvas.service.PreviewUrlBuilder;

import static java.util.Collections.emptyMap;
import static java.util.stream.Collectors.toList;

public abstract class AbstractDirectUploadHelper {
    private final PreviewUrlBuilder previewUrlBuilder;

    public AbstractDirectUploadHelper(PreviewUrlBuilder previewUrlBuilder) {
        this.previewUrlBuilder = previewUrlBuilder;
    }

    /**
     * {@inheritDoc}
     */
    public CreativeUploadData toCreativeUploadData(CreativeDocument creative, long clientId) {
        CreativeUploadData creativeUploadData = new CreativeUploadData();

        creativeUploadData.setCreativeId(creative.getId());
        creativeUploadData.setCreativeName(creative.getName());
        creativeUploadData.setHeight(creative.getData().getHeight());
        creativeUploadData.setWidth(creative.getData().getWidth());

        creativeUploadData.setPreviewUrl(creative.getScreenshotURL());
        creativeUploadData.setLivePreviewUrl(previewUrlBuilder.buildPreviewUrl(clientId, creative, true));
        creativeUploadData.setPresetId(creative.getPresetId());

        ModerationInfo moderationInfo = new ModerationInfo();
        moderationInfo.getHtml().setUrl(creative.getCreativeURL());

        // PRESET_IDS_WITH_TYPED_IMAGES - set of preset ids, which should contain typed images.
        // Image of other presets should not have type for back compatibility with perl-transported moderation.
        Map<String, String> mediaSetTypes = getMediaSetTypes(creative);

        moderationInfo.getImages().addAll(creative.getData().onlyVisibleData().getMediaSets().entrySet().stream()
                .flatMap(mediaSetEntry -> mediaSetEntry.getValue().getItems().stream()
                        //TODO include ElementType.LOGO as well: BANNERSTORAGE-5063
                        .filter(item -> ElementType.IMAGE.equalsIgnoreCase(item.getType()) || ElementType.SECOND_IMAGE.equalsIgnoreCase(item.getType()))
                        .flatMap(item -> item.getItems().stream())
                        .map(subitem -> new ModerationInfo.Image()
                                .setOriginalFileId(subitem.getFileId())
                                .setUrl(subitem.getUrl())
                                .setType(mediaSetTypes.get(mediaSetEntry.getKey()))
                        )
                ).collect(toList()));

        var videos =
                creative.getData().onlyVisibleData().getMediaSets().entrySet().stream()
                        .flatMap(mediaSetEntry -> mediaSetEntry.getValue().getItems().stream()
                                .filter(item -> ElementType.VIDEO.equalsIgnoreCase(item.getType()))
                                .flatMap(item -> item.getItems().stream())
                                .map(subitem -> new ModerationInfo.Video()
                                        .setOriginalFileId(subitem.getFileId())
                                        .setUrl(subitem.getUrl())
                                )
                        ).collect(toList());

        if (videos.size() > 0) {
            moderationInfo.setVideos(videos);
        }

        List<ModerationInfo.Text> texts = StreamEx.of(creative.getData().onlyVisibleData().getElements())
                .mapToEntry(Element::getType, Element::getOptions)
                .selectValues(Element.ColoredTextOptions.class)
                .flatMapKeyValue((type, options) -> options.getTexts().stream()
                        .filter(Objects::nonNull)
                        .map(text -> new ModerationInfo.Text(text, type, options.getColor())))
                .toList();
        if (moderationInfo.getTexts() != null) {
            moderationInfo.getTexts().addAll(texts);
        } else if (!texts.isEmpty()) {
            moderationInfo.setTexts(texts);
        }
        moderationInfo.setAdminRejectReason(creative.getAdminRejectReason());

        creativeUploadData.setModerationInfo(moderationInfo);
        if (creative.getData().getOptions().getIsAdaptive()) {
            creativeUploadData.setIsAdaptive(creative.getData().getOptions().getIsAdaptive());
        } else {
            creativeUploadData.setIsAdaptive(false);
        }

        return creativeUploadData;
    }

    protected Map<String, String> getMediaSetTypes(CreativeDocument creative) {
        return emptyMap();
    }

}
