package com.zcloud.fire.check.facade;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.cola.dto.MultiResponse;
import com.alibaba.cola.dto.SingleResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jjb.saas.message.client.message.facede.MessageFacade;
import com.jjb.saas.message.client.message.request.MessageSendCmd;
import com.jjb.saas.message.client.message.request.MessageTargetCmd;
import com.zcloud.fire.check.domain.config.MessageConfig;
import com.zcloud.fire.check.persistence.dataobject.FireCheckListDO;
import com.zcloud.fire.check.persistence.dataobject.FireCheckListUserDO;
import com.zcloud.fire.check.persistence.dataobject.UserDO;
import com.zcloud.fire.check.persistence.mapper.FireCheckListMapper;
import com.zcloud.fire.check.persistence.mapper.FireCheckListUserMapper;
import com.zcloud.fire.check.persistence.repository.UserRepository;
import com.zcloud.gbscommon.utils.UuidUtil;
import com.zcloud.gbscommon.zloudfirecheck.facade.ZcloudFireCheckFacade;
import com.zcloud.gbscommon.zloudfirecheck.request.FireCheckQry;
import com.zcloud.gbscommon.zloudfirecheck.response.FireCheckListByUserCO;
import com.zcloud.gbscommon.zloudfirecheck.response.FireCheckWorkChangeCmd;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.transaction.annotation.Transactional;

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

@DubboService
@AllArgsConstructor
@Slf4j
public class ZcloudFireCheckFacadeImpl implements ZcloudFireCheckFacade {
    @Resource
    private final FireCheckListMapper fireCheckListMapper;
    @Resource
    private final FireCheckListUserMapper fireCheckListUserMapper;
    @Resource
    private final UserRepository userRepository;
    @DubboReference
    private MessageFacade messageFacade;
    @Resource
    private final MessageConfig messageConfig;

    @Override
    public MultiResponse<FireCheckListByUserCO> listManagerByUserId(FireCheckQry fireCheckQry) {
        if (fireCheckQry == null || fireCheckQry.getUserId() == null || fireCheckQry.getCorpinfoId() == null) {
            return MultiResponse.of(Collections.emptyList());
        }
        QueryWrapper<FireCheckListUserDO> listUserQueryWrapper = new QueryWrapper<>();
        listUserQueryWrapper.eq("user_id", fireCheckQry.getUserId());
        listUserQueryWrapper.eq("corpinfo_id", fireCheckQry.getCorpinfoId());
        List<FireCheckListUserDO> fireCheckListUserList = fireCheckListUserMapper.selectList(listUserQueryWrapper);
        if (CollUtil.isEmpty(fireCheckListUserList)) {
            return MultiResponse.of(Collections.emptyList());
        }
        Set<String> fireCheckIdSet = fireCheckListUserList.stream()
                .map(FireCheckListUserDO::getFireCheckId)
                .filter(StringUtils::isNotEmpty)
                .collect(Collectors.toSet());
        if (CollUtil.isEmpty(fireCheckIdSet)) {
            return MultiResponse.of(Collections.emptyList());
        }
        QueryWrapper<FireCheckListDO> listQueryWrapper = new QueryWrapper<>();
        listQueryWrapper.in("fire_check_id", fireCheckIdSet);
        listQueryWrapper.eq("corpinfo_id", fireCheckQry.getCorpinfoId());
        List<FireCheckListDO> fireCheckListList = fireCheckListMapper.selectList(listQueryWrapper);
        if (CollUtil.isEmpty(fireCheckListList)) {
            return MultiResponse.of(Collections.emptyList());
        }
        List<FireCheckListByUserCO> result = fireCheckListList.stream()
                .map(this::buildFireCheckListByUserCO)
                .collect(Collectors.toList());
        return MultiResponse.of(result);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SingleResponse updateRiskWorkChange(FireCheckWorkChangeCmd fireCheckWorkChangeCmd) {
        if (fireCheckWorkChangeCmd == null
                || StringUtils.isEmpty(fireCheckWorkChangeCmd.getFireCheckId())
                || fireCheckWorkChangeCmd.getOldUserId() == null
                || fireCheckWorkChangeCmd.getUserId() == null) {
            return SingleResponse.buildFailure("PARAM_ERROR", "交接参数不完整");
        }
        QueryWrapper<FireCheckListUserDO> listUserQueryWrapper = new QueryWrapper<>();
        listUserQueryWrapper.eq("fire_check_id", fireCheckWorkChangeCmd.getFireCheckId());
        listUserQueryWrapper.eq("user_id", fireCheckWorkChangeCmd.getOldUserId());
        List<FireCheckListUserDO> fireCheckListUserList = fireCheckListUserMapper.selectList(listUserQueryWrapper);
        if (CollUtil.isEmpty(fireCheckListUserList)) {
            return SingleResponse.buildFailure("DATA_NOT_FOUND", "未查询到待交接的消防检查工作");
        }
        QueryWrapper<FireCheckListUserDO> existsQueryWrapper = new QueryWrapper<>();
        existsQueryWrapper.eq("fire_check_id", fireCheckWorkChangeCmd.getFireCheckId());
        existsQueryWrapper.eq("user_id", fireCheckWorkChangeCmd.getUserId());
        Long existsCount = fireCheckListUserMapper.selectCount(existsQueryWrapper);
        if (existsCount != null && existsCount > 0) {
            return SingleResponse.buildFailure("DATA_EXISTS", "新责任人已存在于该消防检查工作中");
        }

        UserDO newUser = getNewUser(fireCheckWorkChangeCmd.getUserId());
        for (FireCheckListUserDO fireCheckListUserDO : fireCheckListUserList) {
            fireCheckListUserDO.setUserId(fireCheckWorkChangeCmd.getUserId());
            fireCheckListUserDO.setDepartmentId(resolveDepartmentId(fireCheckWorkChangeCmd, newUser));
            fireCheckListUserDO.setCorpinfoId(resolveCorpinfoId(fireCheckWorkChangeCmd, newUser));
            fireCheckListUserMapper.updateById(fireCheckListUserDO);
        }

        FireCheckListDO fireCheckListDO = getFireCheckList(fireCheckWorkChangeCmd.getFireCheckId());
        sendWorkChangeMessage(fireCheckWorkChangeCmd, fireCheckListDO);
        return SingleResponse.buildSuccess();
    }

    private FireCheckListByUserCO buildFireCheckListByUserCO(FireCheckListDO fireCheckListDO) {
        FireCheckListByUserCO result = new FireCheckListByUserCO();
        result.setFireCheckId(fireCheckListDO.getFireCheckId());
        result.setWorkProject("消防检查");
        result.setWorkContent(buildWorkContent(fireCheckListDO));
        return result;
    }

    private String buildWorkContent(FireCheckListDO fireCheckListDO) {
        if (fireCheckListDO == null) {
            return "";
        }
        if (StringUtils.isNotEmpty(fireCheckListDO.getFireCheckName())
                && StringUtils.isNotEmpty(fireCheckListDO.getFireCheckTypeName())) {
            return fireCheckListDO.getFireCheckName() + "（" + fireCheckListDO.getFireCheckTypeName() + "）";
        }
        if (StringUtils.isNotEmpty(fireCheckListDO.getFireCheckName())) {
            return fireCheckListDO.getFireCheckName();
        }
        return StringUtils.defaultString(fireCheckListDO.getFireCheckTypeName());
    }

    private UserDO getNewUser(Long userId) {
        List<UserDO> userList = userRepository.getListById(Collections.singletonList(userId));
        if (CollUtil.isEmpty(userList)) {
            return null;
        }
        return userList.get(0);
    }

    private Long resolveDepartmentId(FireCheckWorkChangeCmd fireCheckWorkChangeCmd, UserDO newUser) {
        if (fireCheckWorkChangeCmd.getDeptId() != null) {
            return fireCheckWorkChangeCmd.getDeptId();
        }
        if (newUser != null) {
            return newUser.getDepartmentId();
        }
        return null;
    }

    private Long resolveCorpinfoId(FireCheckWorkChangeCmd fireCheckWorkChangeCmd, UserDO newUser) {
        if (fireCheckWorkChangeCmd.getCorpId() != null) {
            return fireCheckWorkChangeCmd.getCorpId();
        }
        if (newUser != null) {
            return newUser.getCorpinfoId();
        }
        return null;
    }

    private FireCheckListDO getFireCheckList(String fireCheckId) {
        QueryWrapper<FireCheckListDO> listQueryWrapper = new QueryWrapper<>();
        listQueryWrapper.eq("fire_check_id", fireCheckId);
        return fireCheckListMapper.selectOne(listQueryWrapper);
    }

    private void sendWorkChangeMessage(FireCheckWorkChangeCmd fireCheckWorkChangeCmd, FireCheckListDO fireCheckListDO) {
        try {
            MessageSendCmd messageSendCmd = new MessageSendCmd();
            messageSendCmd.setBusinessId(UuidUtil.get32UUID());
            MessageTargetCmd messageTargetCmd = new MessageTargetCmd();
            messageTargetCmd.setUserId(fireCheckWorkChangeCmd.getUserId());
            messageSendCmd.setTargetCmd(messageTargetCmd);
            messageSendCmd.setSourceCode(messageConfig.getFireCheckPending());
            messageSendCmd.setNeedTokenEnum(false);
            messageSendCmd.setParams(buildSendParams(fireCheckWorkChangeCmd, fireCheckListDO));
            log.info("消防检查工作交接发送消息参数:{}", JSONUtil.toJsonStr(messageSendCmd));
            SingleResponse<Boolean> response = messageFacade.send(messageSendCmd);
            log.info("消防检查工作交接发送消息结果:{}", JSONUtil.toJsonStr(response));
            if (response == null || !response.isSuccess() || !Boolean.TRUE.equals(response.getData())) {
                log.warn("消防检查工作交接消息发送未成功, fireCheckId:{}, userId:{}", fireCheckWorkChangeCmd.getFireCheckId(), fireCheckWorkChangeCmd.getUserId());
            }
        } catch (Exception e) {
            log.error("消防检查工作交接发送消息失败", e);
        }
    }

    private Map<String, Object> buildSendParams(FireCheckWorkChangeCmd fireCheckWorkChangeCmd, FireCheckListDO fireCheckListDO) {
        String fireCheckName = fireCheckListDO == null ? "" : StringUtils.defaultString(fireCheckListDO.getFireCheckName());
        String fireCheckTypeName = fireCheckListDO == null ? "" : StringUtils.defaultString(fireCheckListDO.getFireCheckTypeName());
        return Stream.of(
                        new Object[]{"FirefightinglistName", fireCheckName},
                        new Object[]{"checkPeriod", fireCheckTypeName},
                        new Object[]{"oldUserId", fireCheckWorkChangeCmd.getOldUserId()},
                        new Object[]{"newUserId", fireCheckWorkChangeCmd.getUserId()},
                        new Object[]{"newUserName", StringUtils.defaultString(fireCheckWorkChangeCmd.getUserName())},
                        new Object[]{"workProject", "消防检查"},
                        new Object[]{"workContent", buildWorkContent(fireCheckListDO)}
                )
                .filter(item -> Objects.nonNull(item[1]))
                .collect(Collectors.toMap(item -> String.valueOf(item[0]), item -> item[1], (left, right) -> right));
    }
}
