package com.ruoyi.system.service.md.impl;

import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;
import com.ruoyi.system.domain.md.NewmsgInbox;
import com.ruoyi.system.domain.md.NewmsgOutbox;
import com.ruoyi.system.domain.md.enums.BooleanType;
import com.ruoyi.system.domain.md.enums.OutboxState;
import com.ruoyi.system.domain.md.query.QueryPage;
import com.ruoyi.system.domain.md.request.NewMsgQuery;
import com.ruoyi.system.domain.md.request.NewMsgSendRequest;
import com.ruoyi.system.domain.md.request.NewMsgUser;
import com.ruoyi.system.service.md.NewMsgService;
import com.ruoyi.system.service.md.NewmsgInboxService;
import com.ruoyi.system.service.md.NewmsgOutboxService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author vidar
 * date 2024/6/6
 * description
 **/
@Service
public class NewMsgServiceImpl implements NewMsgService {
    @Resource
    private NewmsgOutboxService outboxService;
    @Resource
    private NewmsgInboxService inboxService;

    private final ExecutorService threadPools = new ThreadPoolExecutor(30, 1000, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(9999), new ThreadPoolExecutor.CallerRunsPolicy());

    @Override
    public String send(NewMsgSendRequest sendRequest) {
        Assert.notNull(sendRequest,"request 不能为空");
        Assert.notEmpty(sendRequest.getTo(),"to 不能为空");
        Assert.notNull(sendRequest.getSendData(),"sendData 不能为空");
        Assert.notNull(sendRequest.getSendData().getMsgtype(),"sendData.msgType 不能为空");
        Assert.isTrue(org.apache.commons.lang3.StringUtils.isNotBlank(sendRequest.getSendData().getTitle()),"sendData.title 不能为空");
        sendRequest.getSendData().addParam("recipientNum",sendRequest.getTo().size());
        //参数处理
        paramsConvert(sendRequest);
        //保存&更新发件为草稿
        String outboxId = outboxService.saveDraft(sendRequest.getSendData(), sendRequest.getFrom());
        sendRequest.getSendData().setOutboxid(outboxId);
        send(sendRequest, outboxId);
        outboxService.updateOutboxState(outboxId, OutboxState.send);
        return outboxId;
    }

    @Override
    public IPage<Map<String, Object>> queryUnion(NewMsgQuery query, QueryPage page) {
        return inboxService.queryUnion(query, page);
    }

    @Override
    public Map<String, Object> getInboxDetail4Map(String id) {
        NewmsgInbox res = inboxService.getInboxDetail(id);
        if (res == null) {
            return null;
        }
        try {
            return inboxService.inboxToMap(res);
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public boolean readInbox(String id) {
        NewMsgQuery query = new NewMsgQuery();
        query.setInboxid(id);
        return inboxService.readInbox(query);
    }

    @Override
    public boolean readInbox(Byte msgType, NewMsgQuery query) {
        query.setMsgtype(msgType);
        return inboxService.readInbox(query);
    }

    @Override
    public int countRead(Byte msgType, NewMsgQuery query, boolean userRead) {
        query.setMsgtype(msgType);
        query.setUserread(userRead ? BooleanType.yes.getCode() : BooleanType.no.getCode());
        return inboxService.count(query);
    }

    @Override
    public NewmsgOutbox getOutboxDetailNoBody(String outboxId) {
        return outboxService.getOutboxDetailNoBody(outboxId);
    }

    /**
     * 校验附件 纠正hasatt参数
     */
    private void paramsConvert(NewMsgSendRequest sendRequest) {
        String attfiles = sendRequest.getSendData().getParam("attfiles");
        String hasatt = "0";
        try {
            if (!StringUtils.isEmpty(attfiles)) {
                JSONArray array = JSONArray.parseArray(attfiles);
                if (!CollectionUtils.isEmpty(array)) {
                    hasatt = "1";
                }
            }
        } catch (Exception e) {
        }
        sendRequest.getSendData().addParam("hasatt", hasatt);

        //判断body是否为空
        String body = sendRequest.getSendData().getBody();
        sendRequest.getSendData().addParam("hasbody", StringUtils.isEmpty(body) ? "0" : "1");
    }

    /**
     * 发送消息 批量
     */
    private void send(NewMsgSendRequest sendRequest, String outboxId) {
        if (StringUtils.isEmpty(outboxId)) {
            return;
        }
        sendRequest.getSendData().addParam("recipient", ""); //内存占用过大
        sendRequest.getSendData().getExtMapJson();
        sendRequest.getSendData().getParamsJson();

        int batch_size = 500;

        List<List<NewMsgUser>> userBatch = Lists.partition(sendRequest.getTo(), batch_size);
        for (List<NewMsgUser> list : userBatch) {
            threadPools.submit(() -> {
                try {
                    inboxService.saveInBatch(sendRequest.getSendData(), sendRequest.getFrom(), list);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
    }
}
