package com.docus.server.archivefile.service.impl;

import com.docus.core.util.DateUtil;
import com.docus.core.util.Func;
import com.docus.core.util.ListUtils;
import com.docus.core.util.property.Setters;
import com.docus.infrastructure.redis.service.IdService;
import com.docus.infrastructure.web.request.SearchRequest;
import com.docus.infrastructure.web.response.PageResult;
import com.docus.server.archivefile.convert.TaskMessageConvert;
import com.docus.server.archivefile.infrastructure.dao.ITaskMessageDao;
import com.docus.server.archivefile.infrastructure.dao.ITaskMessageRetryLogDao;
import com.docus.server.archivefile.service.ITaskMessageService;
import com.docus.server.entity.TaskMessage;
import com.docus.server.entity.TaskMessageRetryLog;
import com.docus.server.enums.CollectTypeEnum;
import com.docus.server.enums.StateEnum;
import com.docus.server.vo.archivefile.TaskMessageVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class TaskMessageServiceImpl implements ITaskMessageService {
    @Resource
    private ITaskMessageRetryLogDao taskMessageRetryLogDao;
    @Resource
    private TrackRetryService trackRetryService;
    @Resource
    private ITaskMessageDao taskMessageDao;
    @Resource
    private IdService idService;

    /**
     * 新增 ws xml 原始报文
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long insertTaskMessage(String json, String xml, CollectTypeEnum collectType, String retryKey) {
        TaskMessage taskOriginalMessage = TaskMessageConvert.INSTANCE.convert(json, xml, collectType, retryKey, idService.getDateSeq());
        taskMessageDao.save(taskOriginalMessage);
        return taskOriginalMessage.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateTaskMessage(Long id, String json, String exMessageResult, StateEnum stateEnum) {
        if (null == id) {
            return;
        }
        TaskMessage taskOriginalMessage = taskMessageDao.findById(id);
        if (Func.isNotEmpty(taskOriginalMessage)) {
            taskOriginalMessage.setJsonStr(json);
            taskOriginalMessage.setUpdateTime(DateUtil.now());
            taskOriginalMessage.setState(stateEnum);
            taskOriginalMessage.setErrorMsg(exMessageResult);
            taskMessageDao.updateById(taskOriginalMessage);
        }
    }

    @Override
    public List<TaskMessage> findByState(StateEnum stateEnum) {
        return taskMessageDao.findBy("state", stateEnum);
    }

    @Override
    public TaskMessageVO findById(String id) {
        TaskMessage taskMessage = taskMessageDao.findById(id);
        TaskMessageVO taskMessageVO = TaskMessageConvert.INSTANCE.convert(taskMessage);
        List<TaskMessageRetryLog> retryLogs = taskMessageRetryLogDao.findBy("messageId", id);
        if (!CollectionUtils.isEmpty(retryLogs)) {
            taskMessageVO.setHaveRetryLog(true);
        }
        return taskMessageVO;
    }

    @Override
    public PageResult<TaskMessageVO> search(SearchRequest request) {
        PageResult<TaskMessageVO> result = TaskMessageConvert.INSTANCE.convert(searchTaskMessage(request));

        if (CollectionUtils.isEmpty(result.getList())) {
            return new PageResult<>();
        }

        List<TaskMessageRetryLog> retryLogs = taskMessageRetryLogDao.findBy("messageId", ListUtils.distinctSelect(result.getList(), TaskMessageVO::getId));
        Map<Long, TaskMessageRetryLog> longTaskMessageRetryLogMap = ListUtils.toMap(retryLogs, TaskMessageRetryLog::getMessageId);

        Setters.<TaskMessageVO>instance().list(result.getList()).cycleSetProperties(taskMessage -> {
            if (longTaskMessageRetryLogMap.containsKey(taskMessage.getId())) {
                taskMessage.setHaveRetryLog(true);
            }
        });

        return result;
    }

    public PageResult<TaskMessage> searchTaskMessage(SearchRequest request) {
        return taskMessageDao.searchTaskMessage(request);
    }


    @Override
    public void searchRetry(SearchRequest searchRequest) throws Exception {
        PageResult<TaskMessage> result = searchTaskMessage(searchRequest);
        actionRetry(result.getList());
    }


    @Override
    public void findRetry(List<Long> ids) throws Exception {
        List<TaskMessage> taskMessages = taskMessageDao.findByIds(ids);
        actionRetry(taskMessages);
    }

    private void actionRetry(List<TaskMessage> taskMessages) throws Exception {
        if (CollectionUtils.isEmpty(taskMessages)) {
            return;
        }

        for (TaskMessage message : taskMessages) {
            trackRetryService.doRetryTaskMessage(message);
        }

    }

}
