package com.boman.web.core.service.message;

import com.alibaba.fastjson.JSONObject;
import com.boman.domain.constant.FormDataConstant;
import com.boman.domain.dto.AjaxResult;
import com.boman.domain.dto.FormDataDto;
import com.boman.domain.dto.QueryBySqlDto;
import com.boman.domain.dto.UpdateDto;
import com.boman.web.core.domain.MessageDto;
import com.boman.web.core.mapper.MessageMapper;
import com.boman.web.core.service.TableServiceCmdService;
import com.boman.web.core.service.bomanMessageReceive.IBomanMessageReceiveService;
import com.boman.web.core.service.common.ICommonService;
import com.boman.web.core.utils.AuthUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

import java.util.ArrayList;
import java.util.List;

import static com.boman.common.core.utils.number.NumberUtils.eqZero;
import static com.boman.common.core.utils.obj.ObjectUtils.*;
import static com.boman.domain.constant.FormDataConstant.*;
/**
 * @author shiqian
 * @date 2021年07月08日 13:56
 **/
@Service
public class MessageServiceImpl implements MessageService {

    private static final String BOMAN_MESSAGE_PK = "id";
    private static final String BOMAN_MESSAGE = "boman_message";
    private static final String CREATE_TIME = "create_time";
    private static final String MESSAGE_SITUATION = "message_situation";
    /*** 已撤回 ***/
    private static final String WITHDRAW_CODE = "3";
    /*** 默认30分钟 ***/
    private static final int DEFAULT_TIME_OUT = 30;


    private static final Logger LOGGER = LoggerFactory.getLogger(MessageServiceImpl.class);

    @Resource
    private ICommonService commonService;
    @Resource
    private IBomanMessageReceiveService receiveService;
    @Resource
    private TableServiceCmdService cmdService;
    @Autowired
    private MessageMapper messageMapper;

    /**
     * 功能描述: 撤回
     *
     * @param id id
     * @return java.lang.String
     */
    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public boolean withdraw(Long id) {
        requireNonNull(id, "撤回时, 发文id为空");
        JSONObject message = commonService.getById(BOMAN_MESSAGE, id);
        requireNonNull(message, "当前发文不存在, id = " + id);
        long before = message.getTimestamp(CREATE_TIME).getTime();
        long current = System.currentTimeMillis();
        if ((current - before) / 1000 / 60 > DEFAULT_TIME_OUT) {
            LOGGER.error("超过30分钟以上的发文无法撤回, 操作人：{}", AuthUtils.getLoginUser().getUsername());
            throw new RuntimeException("超过30分钟以上的发文无法撤回");
        }

        // 修改主表
        UpdateDto dto = new UpdateDto();
        dto.setTableName(BOMAN_MESSAGE);
        JSONObject commitData = new JSONObject();
        commitData.put(MESSAGE_SITUATION, WITHDRAW_CODE);
        JSONObject condition = new JSONObject();
        condition.put(BOMAN_MESSAGE_PK, id);
        dto.setCommitData(commitData);
        dto.setCondition(condition);
        int update = commonService.update(dto);
        if (eqZero(update)) {
            return false;
        }

        // 修改子表
        int effective = receiveService.withdrawByMessageId(id);
        if (eqZero(effective)) {
            throw new RuntimeException("撤回收文失败");
        }

        return true;
    }

    /*
     * 功能描述: 超过30分钟true，否则false
     *
     * @param id id
     * @return boolean
     */
    @Override
    public boolean canDownload(Long id) {
        requireNonNull(id, "撤回时, 发文id为空");
        JSONObject message = commonService.getById(BOMAN_MESSAGE, id);
        requireNonNull(message, "当前发文不存在, id = " + id);
        long before = message.getTimestamp(CREATE_TIME).getTime();
        long current = System.currentTimeMillis();
        return ((current - before) / 1000 / 60) > DEFAULT_TIME_OUT;
    }

    /**
     * 功能描述: 未完成的发文，对应菜单（申请中）
     *
     * @param queryBySql queryBySql
     * @return List<JSONObject>
     */
    @Override
    public AjaxResult notFinishMessages(QueryBySqlDto queryBySql) {
        return cmdService.queryListByUnionTable(queryBySql);
    }

    @Override
    public AjaxResult toDoMessage(FormDataDto dto) {
        JSONObject rows = new JSONObject();
        int total = messageMapper.countByCondition(dto.getUsername());
        rows.put(FormDataConstant.PAGE_TOTAL, total);

        if (total <= 0) {
            rows.put(FormDataConstant.PAGE_ROWS, new ArrayList<>());
            return AjaxResult.success(rows);
        }
        if (total <= 0) {
            rows.put(FormDataConstant.PAGE_ROWS, new ArrayList<>());
            return AjaxResult.success(rows);
        }
        List<JSONObject> result = messageMapper.toDoMessage(dto.getUsername(), dto.getLimit(), dto.getOffset());
        rows.put(PAGE_ROWS, result);
        return AjaxResult.success(rows);
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public AjaxResult receiveMessage(MessageDto dto) {
        // 第一步修改收文时间和状态
        Integer updates = messageMapper.updateReceive(dto.getObjId(), dto.getReceiveTime());
        // 统计是否还有未读
        Integer unRead = messageMapper.countReceive(dto.getMessageId());
        LOGGER.info("已读人数还有{}人。", unRead);
        if(unRead == 0) {
            messageMapper.updateMessageSituationStatus(dto.getMessageId());
        }
        return AjaxResult.success(updates);
    }
}
