package cn.axzo.msg.center.message.service.impl.v3;

import cn.axzo.msg.center.dal.CardStyleDao;
import cn.axzo.msg.center.dal.MessageTemplateButtonV3Dao;
import cn.axzo.msg.center.dal.MessageTemplateGroupV3Dao;
import cn.axzo.msg.center.dal.MessageTemplateV3Dao;
import cn.axzo.msg.center.domain.entity.CardStyle;
import cn.axzo.msg.center.domain.entity.MessageTemplateButtonV3;
import cn.axzo.msg.center.domain.entity.MessageTemplateGroupV3;
import cn.axzo.msg.center.domain.entity.MessageTemplateV3;
import cn.axzo.msg.center.message.domain.dto.TemplateModelV3;
import cn.axzo.msg.center.service.enums.StatusEnum;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.toSet;

/**
 * @author yanglin
 */
@Service
@RequiredArgsConstructor
public class ModelV3Service {

    private final MessageTemplateV3Dao messageTemplateV3Dao;
    private final MessageTemplateGroupV3Dao messageTemplateGroupV3Dao;
    private final MessageTemplateButtonV3Dao messageTemplateButtonV3Dao;
    private final CardStyleDao cardStyleDao;

    public Optional<TemplateModelV3> findEnabledByCode(String templateCode) {
        MessageTemplateV3 template = messageTemplateV3Dao.lambdaQuery()
                .eq(MessageTemplateV3::getCode, templateCode)
                .eq(MessageTemplateV3::getIsDelete, 0)
                .eq(MessageTemplateV3::getStatus, StatusEnum.ENABLE)
                .one();
        if (template == null)
            return Optional.empty();
        ModelBuilder builder = new ModelBuilder(template);
        return Optional.of(builder.build(template));
    }

    public List<TemplateModelV3> getByCodes(List<String> templateCodes) {
        if (CollectionUtils.isEmpty(templateCodes))
            return Collections.emptyList();
        List<MessageTemplateV3> templates = messageTemplateV3Dao.lambdaQuery()
                .in(MessageTemplateV3::getCode, templateCodes)
                .eq(MessageTemplateV3::getIsDelete, 0)
                .list();
        ModelBuilder builder = new ModelBuilder(templates.toArray(new MessageTemplateV3[0]));
        return templates.stream()
                .map(builder::build)
                .collect(toList());
    }

    @RequiredArgsConstructor
    private class ModelBuilder {

        final Map<String, List<MessageTemplateGroupV3>> templateCode2Groups;
        final Map<String, List<MessageTemplateButtonV3>> templateCode2Buttons;
        final Map<String, CardStyle> cardStyleCode2Style;

        ModelBuilder(MessageTemplateV3... templates) {
            if (templates.length > 0) {
                Set<String> templateCodes = Arrays.stream(templates)
                        .map(MessageTemplateV3::getCode)
                        .collect(toSet());
                Set<String> cardStyleCodes = Arrays.stream(templates)
                        .map(MessageTemplateV3::getCardStyleCode)
                        .filter(StringUtils::isNotBlank)
                        .collect(toSet());
                templateCode2Groups = messageTemplateGroupV3Dao.lambdaQuery()
                        .in(MessageTemplateGroupV3::getTemplateCode, templateCodes)
                        .list().stream()
                        .collect(groupingBy(MessageTemplateGroupV3::getTemplateCode));
                templateCode2Buttons = messageTemplateButtonV3Dao.lambdaQuery()
                        .in(MessageTemplateButtonV3::getTemplateCode, templateCodes)
                        .list().stream()
                        .collect(groupingBy(MessageTemplateButtonV3::getTemplateCode));
                cardStyleCode2Style = cardStyleCodes.isEmpty()
                        ? Collections.emptyMap()
                        : cardStyleDao.lambdaQuery()
                        .in(CardStyle::getCode, cardStyleCodes)
                        .list().stream()
                        .collect(toMap(CardStyle::getCode, Function.identity()));
            } else {
                templateCode2Groups = Collections.emptyMap();
                templateCode2Buttons = Collections.emptyMap();
                cardStyleCode2Style = Collections.emptyMap();
            }
        }

        TemplateModelV3 build(MessageTemplateV3 template) {
            TemplateModelV3 templateModel = new TemplateModelV3();
            templateModel.setTemplate(template);
            templateModel.setGroups(templateCode2Groups.getOrDefault(template.getCode(), Collections.emptyList()));
            templateModel.setButtons(templateCode2Buttons.getOrDefault(template.getCode(), Collections.emptyList()));
            templateModel.setCardStyle(cardStyleCode2Style.get(template.getCardStyleCode()));
            return templateModel;
        }

    }

}