package com.jeelowcode.module.biz.service.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.jeelowcode.core.framework.service.IFrameSqlService;
import com.jeelowcode.framework.plus.SqlHelper;
import com.jeelowcode.framework.plus.build.buildmodel.wrapper.SqlInfoQueryWrapper;
import com.jeelowcode.framework.plus.core.toolkit.StringUtils;
import com.jeelowcode.framework.utils.tool.spring.SpringUtils;
import com.jeelowcode.module.biz.service.IRiskService;
import com.jeelowcode.service.bpm.config.framework.portal.core.PortalRequest;
import com.jeelowcode.service.bpm.config.framework.portal.core.dto.ReceiveRequestInfoDTO;
import com.jeelowcode.service.system.api.IApiAdminUserApi;
import com.jeelowcode.service.system.dto.AdminUserRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

import static com.jeelowcode.tool.framework.common.util.collection.CollectionUtils.getFirst;


/**
 * demo
 */
@Slf4j
@Service
public class RiskServiceImpl implements IRiskService {

    private static final String SPACE = " ";
    private static final String WORK_NODE_NAME = "整改风险隐患";
    private static final String WORK_FLOW_NAME = "风险隐患信息";
    // TODO 待办跳转链接,这个以后需要优化，通过配置去取这个链接，不能写死在这里
    private static final String RISK_PC_URL = "/fx/table/view/1963446160885366786";
    private static final String WORK_STATUS_TODO = "0";
    private static final String WORK_STATUS_DONE = "2";
    private static final String VIEW_TYPE_UNREAD = "0";
    private static final String VIEW_TYPE_READ = "1";

    @Resource
    private IFrameSqlService sqlService;

    @Resource
    private IApiAdminUserApi apiAdminUserApi;

    /**
     * 发生消息给整改人
     */
    @Override
    public void sendNotify2Corrective(Long id) {

        // 0.1.查找风险隐患数据，如果查不到任务可以结束了
        Map<String, Object> risk = this.getRiskById(id);
        if (MapUtil.isEmpty(risk)) return;

        // 0.2.从容器中获取 PortalRequest 对象，如果没有配置则放弃通知
        PortalRequest portalRequest = SpringUtils.getBean(PortalRequest.class);
        if (!Objects.requireNonNull(portalRequest).available()) return;

        // 1.构建请求参数,准备推送待办信息
        // 1.1.拼接标题
        String requestName = DateUtil.formatDate((Date) risk.getOrDefault("check_date", new Date())) + SPACE +
                risk.getOrDefault("parkname", "") + SPACE +
                risk.getOrDefault("check_area", "") + SPACE +
                risk.getOrDefault("check_content", "") + SPACE +
                risk.getOrDefault("check_problem", "") + SPACE +
                risk.getOrDefault("check_people", "");

        // 1.2.暂时先使用创建人当作发送人 TODO 需要升级存储检查人的username
        Long createUserId = Objects.isNull(risk.get("create_user")) ? null : (Long) risk.get("create_user");
        AdminUserRespDTO createUser = Optional.ofNullable(createUserId)
                .map(userId -> apiAdminUserApi.getUser(userId))
                .orElse(new AdminUserRespDTO());
        Date createDateTime = Objects.isNull(risk.get("create_time")) ? new Date() : (Date) risk.get("create_time");

        // 1.3.从风险隐患数据中获取整改确认人 TODO 需要升级存储整改确认人的username
        String corrective_confirm_people = Objects.isNull(risk.get("corrective_confirm_people")) ? null : (String) risk.get("corrective_confirm_people");
        List<AdminUserRespDTO> confirmUserList = Optional.ofNullable(corrective_confirm_people)
                .map(userName -> apiAdminUserApi.getUserListByNickname(userName))
                .orElse(Collections.emptyList());
        // 如果没有整改确认人则放弃通知
        if (confirmUserList.isEmpty()) return;
        String receiver = Optional.ofNullable(getFirst(confirmUserList))
                .map(AdminUserRespDTO::getUsername).orElse(null);
        if (StringUtils.isEmpty(receiver)) return;

        // 1.2.组织请求数据
        ReceiveRequestInfoDTO requestDTO = new ReceiveRequestInfoDTO()
                .setFlowId(Base64.encode(String.valueOf(id)))
                .setRequestName(requestName)
                .setWorkflowName(WORK_FLOW_NAME)
                .setNodeName(WORK_NODE_NAME)
                .setPcUrl(RISK_PC_URL)
                .setIsRemark(WORK_STATUS_TODO)
                .setViewType(VIEW_TYPE_UNREAD)
                .setCreator(createUser.getUsername())
                .setCreateDateTime(createDateTime)
                .setReceiver(receiver)
                .setReceiveDateTime(new Date())
                .setReceiveTs(String.valueOf(System.currentTimeMillis()));

        // 2.将请求包裹在try catch 中，避免异常导致上层调用方法事务回滚
        try {
            portalRequest.receiveRequestInfo(requestDTO);
        } catch (Exception e) {
            log.error("发送待办信息失败", e);
        }
    }

    /**
     * 发送消息给检查人
     */
    @Override
    public void sendNotify2Check(Long id) {
        // 空实现目前业务需求并不需要发送给检查人
    }

    @Override
    public Map<String, Object> getRiskById(long id) {
        SqlInfoQueryWrapper.Wrapper wrapper = SqlHelper.getQueryWrapper();
        wrapper.setTableName("lc_risk_hazard_manage");
        wrapper.setWhere(where -> {
            where.eq("id", id);
        });
        return sqlService.getDataOneByPlus(wrapper);
    }

}
