package cn.axzo.msg.center.message.xxl;

import cn.axzo.basics.common.constant.enums.TableIsDeleteEnum;
import cn.axzo.maokai.api.util.Ref;
import cn.axzo.msg.center.dal.MessageTemplateV3Dao;
import cn.axzo.msg.center.domain.entity.MessageTemplateV3;
import cn.axzo.msg.center.service.domain.card.AppVersionConfig;
import cn.axzo.msg.center.service.enums.MessageChannel;
import cn.axzo.msg.center.service.pending.card.domain.CardElementConfig;
import com.alibaba.fastjson.JSON;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.job.core.log.XxlJobLogger;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;

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

@Slf4j
@Component
@RequiredArgsConstructor
public class UpdateTemplateV3ChannelStyleVersionJob  extends IJobHandler {

    private final MessageTemplateV3Dao messageTemplateV3Dao;

    /**
     * 通道
     */
    private final static List<MessageChannel> channels = JSON.parseArray("[\"IM\"]", MessageChannel.class);
    /**
     * 卡片样式编码
     */
    private final static String cardStyleCode = "";//TODO 待产品提供
    /**
     * 卡片样式扩展字段
     */
    private final static List<CardElementConfig> cardExtFields = JSON.parseArray("[{\"type\":\"\",\"name\":\"\",\"code\":\"\",\"value\":\"\"}]", CardElementConfig.class);
    /**
     * app最低版本控制
     */
    private final static List<AppVersionConfig> appVersionConfigs = JSON.parseArray("[{\"appType\":\"\",\"minVersion\":\"\"}]", AppVersionConfig.class);

    @XxlJob("updateTemplateV3ChannelStyleVersionJob")
    @Override
    public ReturnT<String> execute(String param) throws Exception {
        //1 解析参数
        ParamParse paramParse = null;
        if (StringUtils.hasText(param)) {
            paramParse = JSON.parseObject(param, ParamParse.class);
        }
        // 2-1 根据指定的code更新
        if (Objects.nonNull(paramParse) && !CollectionUtils.isEmpty(paramParse.getCodes())) {
            this.doUpdateByCodes(paramParse);
            return ReturnT.SUCCESS;
        }
        // 2-2 全量更新
        this.doUpdateAll();

        return ReturnT.SUCCESS;
    }

    /**
     * 全量更新
     */
    private void doUpdateAll() {
        Supplier<List<MessageTemplateV3>> cursor = templateV3sCursor();
        int count = 0;
        for (List<MessageTemplateV3> templateV3List = cursor.get(); !templateV3List.isEmpty(); templateV3List = cursor.get()) {
            XxlJobLogger.log("update MessageTemplateV3 info, count: {}", count += templateV3List.size());

            //更新逻辑
            this.updateTemplateV3ChannelStyleVersion(templateV3List, channels, cardStyleCode, cardExtFields, appVersionConfigs);
        }
    }

    /**
     * 根据指定的code更新
     */
    public void doUpdateByCodes(ParamParse paramParse) {
        XxlJobLogger.log("根据codes更新im账号-start,ids:{}", paramParse.getCodes());
        List<MessageTemplateV3> templateV3List = messageTemplateV3Dao
                .lambdaQuery()
                .in(MessageTemplateV3::getCode, paramParse.getCodes())
                .eq(MessageTemplateV3::getIsDelete, TableIsDeleteEnum.NORMAL.value)
                .orderByAsc(MessageTemplateV3::getId)
                .list();
        //更新逻辑
        this.updateTemplateV3ChannelStyleVersion(templateV3List, channels, cardStyleCode, cardExtFields, appVersionConfigs);
        XxlJobLogger.log("根据codes更新-end,codes:{}", CollectionUtils.isEmpty(templateV3List) ? "" : templateV3List.stream().map(MessageTemplateV3::getCode).collect(toList()));
    }

    public void updateTemplateV3ChannelStyleVersion(List<MessageTemplateV3> templateV3List, List<MessageChannel> channels
            , String cardStyleCode, List<CardElementConfig> cardExtFields
            , List<AppVersionConfig> appVersionConfigs) {
        if (CollectionUtils.isEmpty(templateV3List)) {
            return;
        }
        for (MessageTemplateV3 templateV3 : templateV3List) {

            //
            List<MessageChannel> updateChannels = !CollectionUtils.isEmpty(templateV3.getChannels()) ? templateV3.getChannels() : channels;
            String updateCardStyleCode = StringUtils.hasText(templateV3.getCardStyleCode()) ? templateV3.getCardStyleCode() : cardStyleCode;
            List<CardElementConfig> updateCardExtFields = !CollectionUtils.isEmpty(templateV3.getCardExtFields()) ? templateV3.getCardExtFields() : cardExtFields;
            List<AppVersionConfig> updateAppVersionConfigs = !CollectionUtils.isEmpty(templateV3.getAppVersionConfigs()) ? templateV3.getAppVersionConfigs() : appVersionConfigs;


            messageTemplateV3Dao.lambdaUpdate().eq(MessageTemplateV3::getId, templateV3.getId())
                    .set(!CollectionUtils.isEmpty(updateChannels), MessageTemplateV3::getChannels, updateChannels)
                    .set(StringUtils.hasText(updateCardStyleCode), MessageTemplateV3::getCardStyleCode, updateCardStyleCode)
                    .set(!CollectionUtils.isEmpty(updateCardExtFields), MessageTemplateV3::getCardExtFields, updateCardExtFields)
                    .set(!CollectionUtils.isEmpty(updateAppVersionConfigs), MessageTemplateV3::getAppVersionConfigs, updateAppVersionConfigs).update();
        }
    }

    private Supplier<List<MessageTemplateV3>> templateV3sCursor() {
        Ref<Long> maxId = Ref.create(0L);
        return () -> {
            List<MessageTemplateV3> accounts = messageTemplateV3Dao
                    .lambdaQuery()
                    .eq(MessageTemplateV3::getIsDelete, TableIsDeleteEnum.NORMAL.value)
                    .gt(MessageTemplateV3::getId, maxId.get())
                    .orderByAsc(MessageTemplateV3::getId)
                    .last("LIMIT 200")
                    .list();
            if (!accounts.isEmpty()) {
                maxId.set(accounts.get(accounts.size() - 1).getId());
                log.info("update cursor id to: {}", maxId.get());
            }
            return accounts;
        };
    }

    @Data
    public static class ParamParse {
        private List<String> codes;
    }
}
