package cn.axzo.msg.center.notices.service.impl;

import cn.axzo.msg.center.common.enums.TableIsDeleteEnum;
import cn.axzo.msg.center.common.utils.PlaceholderResolver;
import cn.axzo.msg.center.dal.MNSMessageTemplateParamDao;
import cn.axzo.msg.center.dal.mapper.MNSChannelMessageTemplateMapper;
import cn.axzo.msg.center.dal.mapper.MNSMessageAppMapper;
import cn.axzo.msg.center.dal.mapper.MNSMessageTemplateMapper;
import cn.axzo.msg.center.domain.entity.MNSChannelMessageTemplate;
import cn.axzo.msg.center.domain.entity.MNSMessageApp;
import cn.axzo.msg.center.domain.entity.MNSMessageTemplate;
import cn.axzo.msg.center.domain.entity.MNSMessageTemplateParam;
import cn.axzo.msg.center.domain.enums.YesNoEnum;
import cn.axzo.msg.center.notices.common.enums.ChannelHandlerEnum;
import cn.axzo.msg.center.notices.common.enums.ReturnCodeEnum;
import cn.axzo.msg.center.notices.common.exception.BizException;
import cn.axzo.msg.center.notices.common.lang.Page;
import cn.axzo.msg.center.notices.manager.api.dto.request.plat.CreateTemplateRequestDto;
import cn.axzo.msg.center.notices.manager.api.dto.request.plat.QueryTemplateRequestDto;
import cn.axzo.msg.center.notices.manager.api.dto.response.plat.QueryTemplateResponseDto;
import cn.axzo.msg.center.notices.service.api.PlatService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import static cn.axzo.basics.common.util.Queries.query;

@Slf4j
@Service("platService")
public class PlatServiceImpl implements PlatService {

    @Resource
    private MNSChannelMessageTemplateMapper mnsChannelMessageTemplateMapper;

    @Resource
    private MNSMessageTemplateMapper mnsMessageTemplateMapper;

    @Resource
    private MNSMessageAppMapper mnsMessageAppMapper;

    @Resource
    private MNSMessageTemplateParamDao mnsMessageTemplateParamDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createTemplate(CreateTemplateRequestDto request) {
        ChannelHandlerEnum channel = parseChannel(request.getChannel());
        checkCreateTemplate(request, channel);

        insertMessageApp(request.getServiceName());

        insertMessageTemplate(request);

        insertChannelMessageTemplate(request, channel);

        insertMessageTemplateParam(request.getChannelTemplateCode(), request.getTemplateContent());
    }

    private ChannelHandlerEnum parseChannel(String channelCode) {
        ChannelHandlerEnum channel = ChannelHandlerEnum.getByCode(channelCode);
        if (channel != null)
            return channel;
        return ChannelHandlerEnum.ALI_YUN;
    }

    /**
     * 插入app
     */
    private void insertMessageApp(String serviceName) {
        LambdaQueryWrapper<MNSMessageApp> query = new LambdaQueryWrapper<>();
        query.eq(MNSMessageApp::getAppCode, serviceName);
        List<MNSMessageApp> messageApps = mnsMessageAppMapper.selectList(query);
        if (CollectionUtils.isNotEmpty(messageApps)) {
            return;
        }
        MNSMessageApp messageApp = new MNSMessageApp();
        messageApp.setAppCode(serviceName);
        messageApp.setAppName(serviceName);
        messageApp.setStatus(1);
        mnsMessageAppMapper.insert(messageApp);
    }

    /**
     * 参数校验
     */
    private void checkCreateTemplate(CreateTemplateRequestDto request, ChannelHandlerEnum channel) {
        if (request == null) {
            throw new BizException(ReturnCodeEnum.FAIL, "参数不能为空");
        }
        if (request.getServiceName() == null) {
            throw new BizException(ReturnCodeEnum.FAIL, "服务名称不能为空");
        }
        if (request.getMessageTemplateType() == null) {
            throw new BizException(ReturnCodeEnum.FAIL, "模板类型不能为空");
        }
        if (StringUtils.isBlank(request.getInnerTemplateNo())) {
            throw new BizException(ReturnCodeEnum.FAIL, "内部短信模板编码不能为空");
        }
        if (StringUtils.isBlank(request.getChannelTemplateCode())) {
            throw new BizException(ReturnCodeEnum.FAIL, "渠道短信模板编码不能为空");
        }
        if (StringUtils.isBlank(request.getTitle())) {
            throw new BizException(ReturnCodeEnum.FAIL, "标题不能为空");
        }
        if (StringUtils.isBlank(request.getTemplateContent())) {
            throw new BizException(ReturnCodeEnum.FAIL, "模板内容不能为空");
        }
        // 判断短信编码是否存在
        LambdaQueryWrapper<MNSChannelMessageTemplate> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MNSChannelMessageTemplate::getChannelCode, channel.getCode());
        queryWrapper.eq(MNSChannelMessageTemplate::getTemplateNo, request.getChannelTemplateCode());
        // 一个内部模板可以映射多个渠道商
        queryWrapper.eq(MNSChannelMessageTemplate::getInnerTemplateNo, request.getInnerTemplateNo());
        List<MNSChannelMessageTemplate> list = mnsChannelMessageTemplateMapper.selectList(queryWrapper);
        if (CollectionUtils.isNotEmpty(list)) {
            MNSChannelMessageTemplate channelMessageTemplate = list.get(0);
            String templateNo = channelMessageTemplate.getTemplateNo();
            String innerTemplateNo = channelMessageTemplate.getInnerTemplateNo();
            String templatNo = templateNo.equals(request.getChannelTemplateCode()) ? templateNo : innerTemplateNo;
            throw new BizException(ReturnCodeEnum.FAIL, "模板编码已存在：" + templatNo);
        }
    }

    /**
     * 插入 MessageTemplate
     */
    private void insertMessageTemplate(CreateTemplateRequestDto request) {
        LambdaQueryWrapper<MNSMessageTemplate> query = new LambdaQueryWrapper<>();
        query.eq(MNSMessageTemplate::getTemplateNo, request.getInnerTemplateNo())
                .eq(MNSMessageTemplate::getIsDelete, YesNoEnum.NO.getCode());
        List<MNSMessageTemplate> messageTemplates = mnsMessageTemplateMapper.selectList(query);
        if (CollectionUtils.isNotEmpty(messageTemplates)) {
            return;
        }
        MNSMessageTemplate messageTemplate = new MNSMessageTemplate();
        messageTemplate.setTemplateNo(request.getInnerTemplateNo());
        messageTemplate.setTitle(request.getTitle());
        messageTemplate.setType(request.getMessageTemplateType());
        messageTemplate.setTemplateContent(request.getTemplateContent());
        messageTemplate.setStatus(1);
        messageTemplate.setHasParam(1);
        messageTemplate.setReason(request.getTitle());
        messageTemplate.setRemark("短信模板统一入库-plat" + (StringUtils.isBlank(request.getRemark()) ? "" : ": " + request.getRemark()));
        mnsMessageTemplateMapper.insert(messageTemplate);
    }


    /**
     * 插入 ChannelMessageTemplate
     */
    private void insertChannelMessageTemplate(CreateTemplateRequestDto request, ChannelHandlerEnum channel) {
        List<MNSChannelMessageTemplate> templates = mnsChannelMessageTemplateMapper.selectList(
                query(MNSChannelMessageTemplate.class)
                        .eq(MNSChannelMessageTemplate::getChannelCode, channel.getCode())
                        .eq(MNSChannelMessageTemplate::getTemplateNo, request.getChannelTemplateCode())
                        .eq(MNSChannelMessageTemplate::getInnerTemplateNo, request.getInnerTemplateNo()));
        if (CollectionUtils.isNotEmpty(templates)) return;
        MNSChannelMessageTemplate channelMessageTemplate = new MNSChannelMessageTemplate();
        channelMessageTemplate.setInnerTemplateNo(request.getInnerTemplateNo());
        channelMessageTemplate.setTemplateNo(request.getChannelTemplateCode());
        channelMessageTemplate.setChannelCode(channel.getCode());
        channelMessageTemplate.setChannelName(channel.getDesc());
        channelMessageTemplate.setTitle(request.getTitle());
        channelMessageTemplate.setTemplateContent(request.getTemplateContent());
        channelMessageTemplate.setType(request.getMessageTemplateType());
        channelMessageTemplate.setStatus(1);
        channelMessageTemplate.setHasParam(1);
        channelMessageTemplate.setRemark("短信模板统一入库-plat" + (StringUtils.isBlank(request.getRemark()) ? "" : ": " + request.getRemark()));
        channelMessageTemplate.setReason(request.getTitle());
        mnsChannelMessageTemplateMapper.insert(channelMessageTemplate);
    }

    private void insertMessageTemplateParam(String channelTemplateCode, String templateContent) {
        PlaceholderResolver placeholderResolver = PlaceholderResolver.getDefaultResolver();
        List<String> paramNames = placeholderResolver.resolveSequenceParamName(templateContent);
        if (CollectionUtils.isEmpty(paramNames)) {
            return;
        }
        final AtomicInteger order = new AtomicInteger(1);
        List<MNSMessageTemplateParam> params = paramNames.stream()
                .map(e -> {
                    MNSMessageTemplateParam templateParam = new MNSMessageTemplateParam();
                    templateParam.setTemplateNo(channelTemplateCode);
                    templateParam.setParamName(e);
                    templateParam.setParamDesc(e);
                    templateParam.setRemark(e);
                    templateParam.setParamOrder(order.getAndIncrement());
                    return templateParam;
                }).collect(Collectors.toList());

        mnsMessageTemplateParamDao.saveBatch(params);
    }


    @Override
    public QueryTemplateResponseDto getByTemplateNo(String templateNo) {
        LambdaQueryWrapper<MNSChannelMessageTemplate> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MNSChannelMessageTemplate::getInnerTemplateNo, templateNo);
        // TODO: [cold_blade] 注意渠道编码的问题
        queryWrapper.eq(MNSChannelMessageTemplate::getChannelCode, ChannelHandlerEnum.ALI_YUN.getCode());
        MNSChannelMessageTemplate channelMessageTemplate = mnsChannelMessageTemplateMapper.selectOne(queryWrapper);
        return channelMessageTemplate == null ? null : QueryTemplateResponseDto.builder()
                .id(channelMessageTemplate.getId())
                .messageTemplateStatus(channelMessageTemplate.getStatus())
                .messageTemplateType(channelMessageTemplate.getType())
                .reason(channelMessageTemplate.getReason())
                .remark(channelMessageTemplate.getRemark())
                .serviceName(channelMessageTemplate.getInnerTemplateNo().split("_")[0])
                .templateAliNo(channelMessageTemplate.getTemplateNo())
                .templateContent(channelMessageTemplate.getTemplateContent())
                .templateNo(channelMessageTemplate.getInnerTemplateNo())
                .title(channelMessageTemplate.getTitle())
                .build();
    }

    @Override
    public Page<QueryTemplateResponseDto> list(QueryTemplateRequestDto request) {
        // TODO: [cold_blade] 这里渠道编码应该作为一个入参而非写死
        LambdaQueryWrapper<MNSChannelMessageTemplate> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(MNSChannelMessageTemplate::getChannelCode, ChannelHandlerEnum.ALI_YUN.getCode());
        queryWrapper.eq(request.getMessageTemplateType() != null, MNSChannelMessageTemplate::getType, request.getMessageTemplateType());
        queryWrapper.like(StringUtils.isNoneBlank(request.getServiceName()), MNSChannelMessageTemplate::getInnerTemplateNo, request.getServiceName());
        queryWrapper.like(StringUtils.isNoneBlank(request.getTemplateAliNo()), MNSChannelMessageTemplate::getTemplateNo, request.getTemplateAliNo());
        queryWrapper.like(StringUtils.isNoneBlank(request.getTemplateNo()), MNSChannelMessageTemplate::getInnerTemplateNo, request.getTemplateNo());
        queryWrapper.like(StringUtils.isNoneBlank(request.getTitle()), MNSChannelMessageTemplate::getTitle, request.getTitle());
        queryWrapper.orderByDesc(MNSChannelMessageTemplate::getCreateAt);

        com.baomidou.mybatisplus.extension.plugins.pagination.Page<MNSChannelMessageTemplate> page = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>();
        page.setCurrent(request.getPageNum());
        page.setSize(request.getPageSize());

        com.baomidou.mybatisplus.extension.plugins.pagination.Page<MNSChannelMessageTemplate> messagePage = mnsChannelMessageTemplateMapper.selectPage(page, queryWrapper);

        Page<QueryTemplateResponseDto> result = new Page<>();
        result.setPageNum(messagePage.getCurrent());
        result.setPageSize(messagePage.getSize());
        result.setTotalElements(messagePage.getTotal());
        result.setList(messagePage.getRecords().stream().map(data -> QueryTemplateResponseDto.builder()
                .id(data.getId())
                .messageTemplateStatus(data.getStatus())
                .messageTemplateType(data.getType())
                .reason(data.getReason())
                .remark(data.getRemark())
                .serviceName(data.getInnerTemplateNo().split("_")[0])
                .templateAliNo(data.getTemplateNo())
                .templateContent(data.getTemplateContent())
                .templateNo(data.getInnerTemplateNo())
                .title(data.getTitle())
                .build()).collect(Collectors.toList()));
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(String templateNo) {
        if (StringUtils.isBlank(templateNo)) {
            throw new BizException(ReturnCodeEnum.FAIL, "短信模板编码不能为空");
        }
        mnsMessageTemplateMapper.deleteByTemplateNo(templateNo);

        mnsChannelMessageTemplateMapper.deleteByTemplateNo(templateNo);
    }

    @Override
    public List<MNSMessageApp> listAllApps() {
        return mnsMessageAppMapper.selectList(query(MNSMessageApp.class).
                eq(MNSMessageApp::getIsDelete, TableIsDeleteEnum.NORMAL.value));
    }
}
