package com.cm.central.control.service.clientexception.impl;

import com.cm.central.control.config.properties.SocketServerProperties;
import com.cm.central.control.pojo.dtos.client.ClientDTO;
import com.cm.central.control.pojo.dtos.projectleader.ProjectLeaderDTO;
import com.cm.central.control.service.client.IClientService;
import com.cm.central.control.service.projectleader.IProjectLeaderService;
import com.cm.common.base.AbstractService;
import com.cm.common.exception.RemoveException;
import com.cm.common.exception.SaveException;
import com.cm.common.exception.SearchException;
import com.cm.common.exception.UpdateException;
import com.cm.common.exception.base.SystemException;
import com.cm.common.pojo.ListPage;
import com.cm.common.result.SuccessResult;
import com.cm.common.result.SuccessResultData;
import com.cm.common.result.SuccessResultList;
import com.cm.common.utils.HashMapUtil;
import com.cm.common.utils.UUIDUtil;
import com.cm.central.control.dao.clientexception.IClientExceptionDao;
import com.cm.central.control.pojo.dtos.clientexception.ClientExceptionDTO;
import com.cm.central.control.pojo.vos.clientexception.ClientExceptionVO;
import com.cm.central.control.service.clientexception.IClientExceptionService;
import com.cm.manager.sms.pojo.vos.email.EmailVO;
import com.cm.manager.sms.service.IEmailService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import net.sf.jsqlparser.util.deparser.UpdateDeParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.*;

/**
 * @ClassName: ClientExceptionServiceImpl
 * @Description: 客户端异常
 * @Author: WenG
 * @Date: 2020-07-30 19:13
 * @Version: 1.0
 **/
@Service
public class ClientExceptionServiceImpl extends AbstractService implements IClientExceptionService {

    @Autowired
    private IClientExceptionDao clientExceptionDao;
    @Autowired
    private IEmailService emailService;
    @Autowired
    private SocketServerProperties socketServerProperties;
    @Autowired
    private IProjectLeaderService projectLeaderService;
    @Autowired
    private IClientService clientService;

    @Override
    public String saveClientExceptionReturnId(ClientExceptionVO clientExceptionVO) throws Exception {
        String clientExceptionId = UUIDUtil.getUUID();
        Map<String, Object> params = HashMapUtil.beanToMap(clientExceptionVO);
        params.put("clientExceptionId", clientExceptionId);
        setSaveInfoByUserId(params, "1");
        clientExceptionDao.saveClientException(params);
        return clientExceptionId;
    }

    @Override
    public SuccessResult removeClientException(String ids) throws RemoveException {
        removeClientExceptionInfo(null, ids);
        return new SuccessResult();
    }

    @Override
    public SuccessResult removeClientExceptionByToken(String token, String ids) throws RemoveException {
        removeClientExceptionInfo(token, ids);
        return new SuccessResult();
    }

    /**
     * 删除客户端异常
     *
     * @param token
     * @param ids
     */
    private void removeClientExceptionInfo(String token, String ids) {
        Map<String, Object> params = getHashMap(3);
        params.put("clientExceptionIds", Arrays.asList(ids.split("_")));
        if (token != null) {
            setUpdateInfo(token, params);
        } else {
            setUpdateInfo(params);
        }
        clientExceptionDao.removeClientException(params);
    }

    @Override
    public void deleteClientException(String ids) throws RemoveException {
        Map<String, Object> params = getHashMap(3);
        params.put("clientExceptionIds", Arrays.asList(ids.split("_")));
        clientExceptionDao.deleteClientException(params);
    }

    @Override
    public SuccessResult updateClientException(String clientExceptionId, ClientExceptionVO clientExceptionVO) throws Exception {
        updateClientExceptionInfo(null, clientExceptionId, clientExceptionVO);
        return new SuccessResult();
    }

    @Override
    public SuccessResult updateClientExceptionByToken(String token, String clientExceptionId, ClientExceptionVO clientExceptionVO) throws Exception {
        updateClientExceptionInfo(token, clientExceptionId, clientExceptionVO);
        return new SuccessResult();
    }

    /**
     * 修改客户端异常
     *
     * @param token
     * @param clientExceptionId
     * @param clientExceptionVO
     */
    private void updateClientExceptionInfo(String token, String clientExceptionId, ClientExceptionVO clientExceptionVO) throws Exception {
        Map<String, Object> params = HashMapUtil.beanToMap(clientExceptionVO);
        params.put("clientExceptionId", clientExceptionId);
        if (token != null) {
            setUpdateInfo(token, params);
        } else {
            setUpdateInfo(params);
        }
        clientExceptionDao.updateClientException(params);
    }

    @Override
    public ClientExceptionDTO getClientExceptionById(String clientExceptionId) throws SearchException {
        Map<String, Object> params = super.getHashMap(1);
        params.put("clientExceptionId", clientExceptionId);
        return clientExceptionDao.getClientException(params);
    }

    @Override
    public List<ClientExceptionDTO> listClientException(Map<String, Object> params) throws SearchException {
        return clientExceptionDao.listClientException(params);
    }

    @Override
    public SuccessResultList<List<ClientExceptionDTO>> listPageClientException(ListPage page) throws SearchException {
        PageHelper.startPage(page.getPage(), page.getRows());
        List<ClientExceptionDTO> clientExceptionDTOs = clientExceptionDao.listClientException(page.getParams());
        PageInfo<ClientExceptionDTO> pageInfo = new PageInfo<>(clientExceptionDTOs);
        return new SuccessResultList<>(clientExceptionDTOs, pageInfo.getPageNum(), pageInfo.getTotal());
    }

    @Override
    public Integer countNumberClientException(Map<String, Object> params) throws SearchException {
        Integer count = clientExceptionDao.countClientException(params);
        return count == null ? 0 : count;
    }

    @Override
    public SuccessResultData<Integer> countClientException(Map<String, Object> params) throws SearchException {
        return new SuccessResultData<>(countNumberClientException(params));
    }

    @Override
    public SuccessResult updateIsHandlerByClientExceptionId(String clientExceptionId) throws UpdateException {
        Map<String, Object> params = getHashMap(2);
        params.put("clientExceptionId", clientExceptionId);
        params.put("isHandle", 1);
        params.put("isNoticeProjectLeader", 1);
        setUpdateInfo(params);
        clientExceptionDao.updateClientException(params);
        return new SuccessResult();
    }

    @Override
    public void updateClientExceptionAndNoticeProjectLeader() {
        Map<String, Object> params = getHashMap(10);
        List<ProjectLeaderDTO> projectLeaderDTOs = projectLeaderService.listProjectLeader(params);
        if (projectLeaderDTOs.isEmpty()) {
            return;
        }
        for (ProjectLeaderDTO projectLeaderDTO : projectLeaderDTOs) {
            params.clear();
            params.put("projectLeaderId", projectLeaderDTO.getProjectLeaderId());
            List<ClientDTO> clientDTOs = clientService.listClient(params);
            if (clientDTOs.isEmpty()) {
                continue;
            }
            List<String> clientIds = new ArrayList<>();
            for (ClientDTO clientDTO : clientDTOs) {
                clientIds.add(clientDTO.getClientId());
            }
            params.clear();
            params.put("clientIds", clientIds);
            params.put("isNoticeProjectLeader", 0);
            List<ClientExceptionDTO> clientExceptionDTOs = listClientException(params);
            if (clientExceptionDTOs.isEmpty()) {
                continue;
            }
            noticeProjectLeader(projectLeaderDTO, clientExceptionDTOs);
        }
    }

    @Override
    public void updateClientExceptionAndNoticeProjectLeaderByProjectLeaderId(String projectLeaderId) {
        ProjectLeaderDTO projectLeaderDTO = projectLeaderService.getProjectLeaderById(projectLeaderId);
        if (projectLeaderDTO == null) {
            LOG.error("项目经理不存在：{}", projectLeaderId);
            return;
        }
        Map<String, Object> params = getHashMap(10);
        params.put("projectLeaderId", projectLeaderId);
        List<ClientDTO> clientDTOs = clientService.listClient(params);
        if (clientDTOs.isEmpty()) {
            return;
        }
        List<String> clientIds = new ArrayList<>();
        for (ClientDTO clientDTO : clientDTOs) {
            clientIds.add(clientDTO.getClientId());
        }
        params.clear();
        params.put("clientIds", clientIds);
        params.put("isNoticeProjectLeader", 0);
        List<ClientExceptionDTO> clientExceptionDTOs = listClientException(params);
        if (clientExceptionDTOs.isEmpty()) {
            return;
        }
        if (clientExceptionDTOs.size() < socketServerProperties.getExceptionNoticeCount()) {
            return;
        }
        noticeProjectLeader(projectLeaderDTO, clientExceptionDTOs);
    }

    @Transactional(rollbackFor = {Exception.class})
    public void noticeProjectLeader(ProjectLeaderDTO projectLeaderDTO, List<ClientExceptionDTO> clientExceptionDTOs) {
        try {
            List<String> clientExceptionIds = new ArrayList<>();
            StringBuilder noticeContent = new StringBuilder();
            for (ClientExceptionDTO clientExceptionDTO : clientExceptionDTOs) {
                clientExceptionIds.add(clientExceptionDTO.getClientExceptionId());
                noticeContent.append("<tr>");
                noticeContent.append("<td>").append(clientExceptionDTO.getClientClientName()).append("</td>");
                noticeContent.append("<td>").append(clientExceptionDTO.getExceptionType()).append("</td>");
                noticeContent.append("<td>").append(clientExceptionDTO.getExceptionName()).append("</td>");
                noticeContent.append("<td>").append(clientExceptionDTO.getGmtCreate()).append("</td>");
                noticeContent.append("</tr>");
            }
            EmailVO emailVO = new EmailVO();
            emailVO.setEmailReceiver(projectLeaderDTO.getLeaderEmail());
            emailVO.setEmailSubject("项目异常通知");
            emailVO.setEmailContent(getExceptionEmailContent(projectLeaderDTO.getLeaderName(), noticeContent.toString()));
            emailVO.setEmailType("2");
            emailService.saveAndSendSystemEmail(emailVO);
            // 更新状态
            Map<String, Object> params = getHashMap(4);
            params.put("isNoticeProjectLeader", 1);
            params.put("clientExceptionIds", clientExceptionIds);
            setUpdateInfoByUserId(params, "1");
            clientExceptionDao.updateNoticeStatusByClientExceptionIds(params);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    /**
     * 获得异常有邮件内容
     *
     * @param leaderName
     * @param noticeContent
     * @return
     */
    private String getExceptionEmailContent(String leaderName, String noticeContent) {
        StringBuilder noticeContentTable = new StringBuilder();
        noticeContentTable.append("<div>").append(leaderName).append("，您好：</div>");
        noticeContentTable.append("<div>您所负责的项目有异常发生，请及时处理并更新</div><br/>");
        noticeContentTable.append("<div>异常情况见下表，详细内容请登录管理系统查看：</div><br/>");
        noticeContentTable.append("<table border=\"1\" cellspacing=\"0\">");
        noticeContentTable.append("<thead><tr><th>系统</th><th>异常类型</th><th>异常名称</th><th>异常时间</th></thread>");
        noticeContentTable.append("<tbody>");
        noticeContentTable.append(noticeContent);
        noticeContentTable.append("</tbody>");
        noticeContentTable.append("</table>");
        return noticeContentTable.toString();
    }

}