package jnpf.attendance.event;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jnpf.attendance.service.AttendanceDailyRuleService;
import jnpf.attendance.service.AttendanceGroupService;
import jnpf.attendance.service.AttendanceUserService;
import jnpf.constants.MessageTopicConstants;
import jnpf.database.util.TenantDataSourceUtil;
import jnpf.entity.AttendanceGroup;
import jnpf.entity.AttendanceGroupUser;
import jnpf.model.attendance.vo.SecondmentDateVo;
import jnpf.model.personnels.dto.secondment.msg.SecondmentMsgUserInfo;
import jnpf.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 借调撤销消息
 */
@Component
@RocketMQMessageListener(
        topic = MessageTopicConstants.SECONDMENT_WITHDRAWAL_OUTPUT,
        consumerGroup = MessageTopicConstants.SECONDMENT_WITHDRAWAL_GROUP,
        replyTimeout = 600000,
        nameServer = "${spring.cloud.stream.rocketmq.binder.name-server}"
)
@Slf4j
public class SecondmentWithdrawalConsumerMQListener implements RocketMQListener<String> {
    @Resource
    private AttendanceDailyRuleService attendanceDailyRuleService;
    @Autowired
    private AttendanceUserService attendanceUserService;
    @Autowired
    private AttendanceGroupService attendanceGroupService;

    @Override
    public void onMessage(String message) {
        if (StringUtil.isEmpty(message)) {
            return;
        }
        log.error("接受借调撤回信息{}", message);
        try {
            SecondmentMsgUserInfo messageList = JSONUtil.toBean(message, SecondmentMsgUserInfo.class);
            if (Objects.isNull(messageList)) {
                return;
            }
            TenantDataSourceUtil.switchTenant(messageList.getTenantId());
            //存在排班的借调撤回不执行
            Assert.isFalse(attendanceDailyRuleService.hasRuleByUserIdAndTime(messageList.getUserId(), messageList.getSecondmentStartTime(), messageList.getSecondmentEndTime()), "存在排班的借调撤回不执行");
            List<AttendanceGroup> byOrgId = attendanceGroupService.getByOrgIds(List.of(messageList.getOriginalOrganizationId(), messageList.getSecondedOrganizationId()));
            Map<String, String> group2orgMap = byOrgId.stream().collect(Collectors.toMap(AttendanceGroup::getId, AttendanceGroup::getOrgId));
            List<AttendanceGroupUser> userList = attendanceUserService.list(new LambdaQueryWrapper<AttendanceGroupUser>()
                    .in(AttendanceGroupUser::getGroupId, byOrgId.stream().map(AttendanceGroup::getId).collect(Collectors.toList()))
                    .eq(AttendanceGroupUser::getUserId, messageList.getUserId())
            );
            //删除借调组数据
            for (AttendanceGroupUser next : userList) {
                String orgId = group2orgMap.get(next.getGroupId());
                List<SecondmentDateVo> list = StringUtil.isEmpty(next.getTimeJson()) ? Lists.newArrayList() : JSONUtil.toList(next.getTimeJson(), SecondmentDateVo.class);
                if (list.stream().noneMatch(item -> item.getStartTime().compareTo(messageList.getSecondmentStartTime()) == 0)) {
                    continue;
                }
                //如果是借调组或者被借调组，则根据借调时间范围找到timeJSON中指定时段并清除
                list.removeIf(item -> item.getStartTime().compareTo(messageList.getSecondmentStartTime()) == 0);
                if (CollUtil.isNotEmpty(list) || Objects.equals(next.getType(),1)) {
                    next.setTimeJson(JSONUtil.toJsonStr(list));
                    attendanceUserService.updateById(next);
                    continue;
                }
                //当借调组的timeJson为空时，则删除该用户信息
                if (StringUtil.equals(orgId, messageList.getSecondedOrganizationId())) {
                    attendanceUserService.removeById(next);
                }
            }
        } catch (Exception e) {
            log.error("消息解析异常: message={}", message, e);
        }

    }

}
