package com.cm.websocket.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cm.common.base.AbstractService;
import com.cm.common.exception.SaveException;
import com.cm.common.plugin.interfaces.IUserImBaseService;
import com.cm.common.plugin.pojo.bos.user.UserDepartmentResourceBO;
import com.cm.common.result.SuccessResult;
import com.cm.websocket.WebSocket;
import com.cm.websocket.enums.AppSocketTypeEnum;
import com.cm.websocket.exception.AppSessionException;
import com.cm.websocket.exception.SessionException;
import com.cm.websocket.manager.AppSocketSessionManager;
import com.cm.websocket.pojo.AppSocketMessage;
import com.cm.websocket.pojo.AppSocketSession;
import com.cm.websocket.pojo.pos.NoticePO;
import com.cm.websocket.pojo.vos.message.NoticeVO;
import com.cm.websocket.service.IMessageService;
import com.cm.websocket.service.INoticeService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.websocket.Session;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * When you feel like quitting. Think about why you started
 * 当你想要放弃的时候，想想当初你为何开始
 *
 * @ClassName: MessageServiceImpl
 * @Description: 消息
 * @Author: wanggeng
 * @Date: 2021/1/14 3:28 下午
 * @Version: 1.0
 */
@Service
public class MessageServiceImpl extends AbstractService implements IMessageService {

    @Autowired
    private IUserImBaseService userImBaseService;
    @Autowired
    private INoticeService noticeService;
    private ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1);

    @Override
    public SuccessResult sendByAppId(String appId) {
        try {
            AppSocketSession appSocketSession = AppSocketSessionManager.getInstance().getSessionByAppId(appId);
            Session session = appSocketSession.getSession();
            AppSocketMessage.NoticeBody noticeBody = new AppSocketMessage.NoticeBody("这是标题1", "目标页面测试1");
            AppSocketMessage appSocketMessage = new AppSocketMessage(AppSocketTypeEnum.NOTICE.getValue(),
                    true,
                    AppSocketSessionManager.FORM_SYSTEM,
                    appSocketSession.getAppId(),
                    JSONObject.toJSONString(noticeBody));
            WebSocket.send(session, appSocketMessage);
        } catch (AppSessionException e) {
            LOG.error(e.getMessage(), e);
            throw new SaveException(e.getMessage());
        }
        return new SuccessResult();
    }

    @Override
    public SuccessResult sendByAppIdTarget(String appId, String target) {
        try {
            AppSocketSession appSocketSession = AppSocketSessionManager.getInstance().getSessionByAppId(appId);
            Session session = appSocketSession.getSession();
            AppSocketMessage.NoticeBody noticeBody = new AppSocketMessage.NoticeBody("这是标题", "目标页面测试", target);
            AppSocketMessage appSocketMessage = new AppSocketMessage(AppSocketTypeEnum.NOTICE_TARGET_MESSAGE.getValue(),
                    true,
                    AppSocketSessionManager.FORM_SYSTEM,
                    appSocketSession.getAppId(),
                    JSONObject.toJSONString(noticeBody));
            WebSocket.send(session, appSocketMessage);
        } catch (AppSessionException e) {
            LOG.error(e.getMessage(), e);
            throw new SaveException(e.getMessage());
        }
        return new SuccessResult();
    }

    @Override
    public SuccessResult saveNoticeWithTarget(NoticeVO noticeVO, boolean save) throws Exception {
        for (NoticeVO.Notice notice : noticeVO.getNoticies()) {
            if (notice.getUserIds() == null || notice.getUserIds().isEmpty()) {
                continue;
            }
            if (StringUtils.isBlank(notice.getTitle())) {
                notice.setTitle("系统消息");
            }
            if (StringUtils.isBlank(notice.getMsg())) {
                notice.setMsg("您有一条系统消息");
            }
            List<AppSocketSession> appSocketSessions = AppSocketSessionManager.getInstance().listSessionByUserIds(notice.getUserIds());
            // 推送3s后通知
            scheduledExecutorService.schedule(() -> {
                for (AppSocketSession appSocketSession : appSocketSessions) {
                    Session session = appSocketSession.getSession();
                    AppSocketMessage.NoticeBody noticeBody = new AppSocketMessage.NoticeBody(notice.getTitle(), notice.getMsg(), notice.getTarget(), notice.getServiceId());
                    AppSocketMessage appSocketMessage = new AppSocketMessage(AppSocketTypeEnum.NOTICE_TARGET_MESSAGE.getValue(),
                            true,
                            AppSocketSessionManager.FORM_SYSTEM,
                            appSocketSession.getUserId(),
                            JSONObject.toJSONString(noticeBody));
                    WebSocket.send(session, appSocketMessage);
                }
            }, 3, TimeUnit.SECONDS);
            if (save) {
                // 保存通知记录
                List<String> userIds = notice.getUserIds();
                for (String userId : userIds) {
                    noticeService.save(userId, notice);
                }
                // 3s后通知，保证事务提交
                scheduledExecutorService.schedule(() -> {
                    // 更新状态待办
                    for (AppSocketSession appSocketSession : appSocketSessions) {
                        Session session = appSocketSession.getSession();
                        AppSocketMessage.CountNeedToDealWithBody countNeedToDealWithBody = new AppSocketMessage.CountNeedToDealWithBody();
                        countNeedToDealWithBody.setSystem(notice.getSystem());
                        // 查询待办状态
                        List<AppSocketMessage.CountNeedToDealWithBody> counts = noticeService.listNoticeCount(appSocketSession.getUserId(), countNeedToDealWithBody);
                        AppSocketMessage appSocketMessage = new AppSocketMessage(AppSocketTypeEnum.SEARCH_COUNT_NEED_TO_DEALT_WITH.getValue(),
                                true,
                                AppSocketSessionManager.FORM_SYSTEM,
                                appSocketSession.getUserId(),
                                JSONArray.toJSONString(counts));
                        WebSocket.send(session, appSocketMessage);
                    }
                }, 3, TimeUnit.SECONDS);
            }
        }
        return new SuccessResult();
    }

    @Override
    public void sendGroupTextMessage(Session fromSession, AppSocketMessage appSocketMessage) throws SessionException {
        AppSocketSession appSocketSession = AppSocketSessionManager.getInstance().getSessionById(fromSession.getId());
        List<String> departmentIds = new ArrayList<>();
        departmentIds.add(appSocketMessage.getTo());
        List<UserDepartmentResourceBO> userDepartmentResourceBOs = userImBaseService.listUserDepartmentResource(departmentIds);
        if (userDepartmentResourceBOs.isEmpty()) {
            WebSocket.sendTextFailed(fromSession, appSocketMessage, "组内无任何用户");
            return;
        }
        List<String> userIds = new ArrayList<>();
        for (UserDepartmentResourceBO userDepartmentResourceBO : userDepartmentResourceBOs) {
            // 排除自己
            if (StringUtils.equals(appSocketSession.getUserId(), userDepartmentResourceBO.getUserId())) {
                continue;
            }
            userIds.add(userDepartmentResourceBO.getUserId());
        }
        List<AppSocketSession> appSocketSessions = AppSocketSessionManager.getInstance().listSessionByUserIds(userIds);
        if (appSocketSessions.isEmpty()) {
            WebSocket.sendTextFailed(fromSession, appSocketMessage, "组内无用户在线");
            return;
        }
        for (AppSocketSession socketSession : appSocketSessions) {
            WebSocket.send(socketSession.getSession(), appSocketMessage);
        }
    }

    @Override
    public void delete(List<String> serviceIds) {
        List<NoticePO> noticePOs = noticeService.listPO(serviceIds);
        Set<String> noticeUserIdSet = new HashSet<>();
        noticePOs.forEach(noticePO -> {
            noticeUserIdSet.add(noticePO.getUserId());
        });
        // 删除通知
        noticeService.deleteByServiceIds(serviceIds);
        // 重新推送数量
        List<AppSocketSession> appSocketSessions = AppSocketSessionManager.getInstance().listSessionByUserIds(new ArrayList<>(noticeUserIdSet));
        // 3s后通知，保证事务提交
        scheduledExecutorService.schedule(() -> {
            // 更新状态待办
            for (AppSocketSession appSocketSession : appSocketSessions) {
                for (NoticePO noticePO : noticePOs) {
                    if (StringUtils.equals(appSocketSession.getUserId(), noticePO.getUserId())) {
                        Session session = appSocketSession.getSession();
                        AppSocketMessage.CountNeedToDealWithBody countNeedToDealWithBody = new AppSocketMessage.CountNeedToDealWithBody();
                        countNeedToDealWithBody.setSystem(noticePO.getNoticeSystem());
                        // 查询待办状态
                        List<AppSocketMessage.CountNeedToDealWithBody> counts = noticeService.listNoticeCount(appSocketSession.getUserId(), countNeedToDealWithBody);
                        AppSocketMessage appSocketMessage = new AppSocketMessage(AppSocketTypeEnum.SEARCH_COUNT_NEED_TO_DEALT_WITH.getValue(),
                                true,
                                AppSocketSessionManager.FORM_SYSTEM,
                                appSocketSession.getUserId(),
                                JSONArray.toJSONString(counts));
                        WebSocket.send(session, appSocketMessage);
                        break;
                    }
                }

            }
        }, 3, TimeUnit.SECONDS);
    }
}
