
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 cn.hutool.json.JSONUtil;
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.IExamPlanService;
import com.jeelowcode.module.biz.service.ITodoRequestService;
import com.jeelowcode.module.biz.service.IWorkItemService;
import com.jeelowcode.service.bpm.config.framework.portal.core.PortalRequest;
import com.jeelowcode.service.bpm.config.framework.portal.core.dto.DeleteRequestInfoDTO;
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 com.jeelowcode.tool.framework.common.util.object.BeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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


/**
 * demo
 */
@Slf4j
@Service
public class WorkItemServiceImpl implements IWorkItemService {


    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 = "/gzxt/table/view/1983351353033953281";
    private static final String WORK_STATUS_TODO = "0";
    private static final String WORK_STATUS_DONE = "2";
    private static final String WORK_STATUS_COMPLETE = "4";
    private static final String VIEW_TYPE_UNREAD = "0";
    private static final String VIEW_TYPE_READ = "1";
    private static final String Bill_Table_Name = "lc_item_result";

    @Autowired
    private IFrameSqlService sqlService;

    @Resource
    private IApiAdminUserApi apiAdminUserApi;

    @Resource
    private ITodoRequestService todoRequestService;

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

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

    @Override
    public List<Map<String, Object>> getItemResultByItemId(Long workItemId) {
        SqlInfoQueryWrapper.Wrapper wrapper = SqlHelper.getQueryWrapper();
        wrapper.setTableName("lc_item_result");
        wrapper.setWhere(where->{
            where.eq("workItemId",workItemId);
            where.eq("is_deleted",0);
        });
        List<Map<String, Object>> dataMapList = sqlService.getDataListByPlus(wrapper);
        return dataMapList;
    }

    @Override
    public boolean pushTodoWorkItemWorkflow(Long workItemId,Long itemResultId, String todoType) {
        // 0.1.查找工作事项数据，如果查不到则放弃推送
        Map<String, Object> workItem = getWorkItemById(workItemId);
        if (MapUtil.isEmpty(workItem)) return false;
        Map<String, Object> itemResult = getItemResultById(itemResultId);
        if (MapUtil.isEmpty(itemResult)) return false;
        // 0.2.从容器中获取 PortalRequest 对象，如果没有配置则放弃通知
        PortalRequest portalRequest = SpringUtils.getBean(PortalRequest.class);
        if (ObjectUtil.isNull(portalRequest)) return false;

        // 0.3.判断是否存在 场景下发送的消息，已经发送过消息的不重复发送
        boolean isExist = todoRequestService.isExistTodoRequest(itemResultId, todoType);
        if(isExist)
        {
            return true;
        }

        // 1.构建请求参数,准备推送待办信息
        String creator="";
        String receiver="";
        String isRemark="";
        String viewType="";

        // 1.1.拼接标题
        String requestName = DateUtil.formatDate((Date) workItem.getOrDefault("initiatingdate", new Date())) + SPACE +
                workItem.getOrDefault("initiatingdeptname", "") + SPACE +
                "发起工作事项："+
                workItem.getOrDefault("itemcontext", "");

        // 1.2.根据代办类型取消息发送者 TODO 需要升级存储检查人的username
        if(todoType.equals("WORK_ITEM_TODO"))
        {
            isRemark=WORK_STATUS_TODO;
            viewType=VIEW_TYPE_UNREAD;
        }else
        {
            isRemark=WORK_STATUS_DONE;
            viewType=VIEW_TYPE_READ;
        }

        // 消息发送者为 工作事项 发起人
        Long createUserId = Objects.isNull(workItem.get("initiatorid")) ? null : Long.valueOf(workItem.get("initiatorid").toString());
        AdminUserRespDTO createUser = Optional.ofNullable(createUserId)
                .map(userId -> apiAdminUserApi.getUser(userId))
                .orElse(new AdminUserRespDTO());
        if(StringUtils.isEmpty(createUser.getUsername()))
        {
            return false;
        }else
        {
            creator=createUser.getUsername();
        }

        // 消息接受者为 事项结果 责任人
        Long receiveId = Objects.isNull(itemResult.get("chargeid")) ? null : Long.valueOf( itemResult.get("chargeid").toString());
        AdminUserRespDTO receiveUser = Optional.ofNullable(receiveId)
                .map(userId -> apiAdminUserApi.getUser(userId))
                .orElse(new AdminUserRespDTO());
        if(StringUtils.isEmpty(receiveUser.getUsername()))
        {
            return false;
        }else
        {
            receiver=receiveUser.getUsername();
        }
        // 1.2.组织请求数据
        ReceiveRequestInfoDTO todoRequestDTO = new ReceiveRequestInfoDTO()
                .setFlowId(Base64.encode(String.valueOf(itemResultId)))
                .setRequestName(requestName)
                .setWorkflowName(WORK_FLOW_NAME)
                .setNodeName(WORK_NODE_NAME)
                .setPcUrl(RISK_PC_URL)
                .setIsRemark(isRemark)
                .setViewType(viewType)
                .setCreator(creator)
                .setCreateDateTime(new Date())
                .setReceiver(receiver)
                .setReceiveDateTime(new Date())
                .setReceiveTs(String.valueOf(System.currentTimeMillis()));
        ReceiveRequestInfoDTO completeRequestDTO = BeanUtils.toBean(todoRequestDTO, ReceiveRequestInfoDTO.class);
        completeRequestDTO.setIsRemark(WORK_STATUS_COMPLETE);

        // 1.3.构建发送消息详情
        HashMap<String, Object> newRecord = new HashMap<>();
        newRecord.put("bill_id", itemResultId);
        newRecord.put("bill_table_name", Bill_Table_Name);
        newRecord.put("bill_action", todoType);
        newRecord.put("todo_request", JSONUtil.toJsonStr(todoRequestDTO));

        // 2.推送待办信息，使用try-catch避免影响上层调用方法的事务回滚
        try {
            portalRequest.receiveRequestInfo(todoRequestDTO);
            newRecord.put("is_success", 1);
            todoRequestService.addTodoRequest(newRecord);
            if(todoType.equals("WORK_ITEM_DONE"))
            {
                portalRequest.receiveRequestInfo(completeRequestDTO);
            }
        } catch (Exception e) {
            log.error("推送待办信息失败", e);
            newRecord.put("is_success", 0);
            todoRequestService.addTodoRequest(newRecord);
            return false;
        }
        return true;
    }

    @Override
    public boolean pushCancelWorkItemWorkflow(Long id) {
        // 0.1.查找风险隐患数据，如果查不到则放弃推送
        Map<String, Object> itemResult = getItemResultById(id);
        if (MapUtil.isEmpty(itemResult)) return false;
        // 0.2.从容器中获取 PortalRequest 对象，如果没有配置则放弃通知
        PortalRequest portalRequest = SpringUtils.getBean(PortalRequest.class);
        if (ObjectUtil.isNull(portalRequest)) return false;

        // 1.构建请求参数,准备推送待办信息
        DeleteRequestInfoDTO deleteRequestInfoDTO = new DeleteRequestInfoDTO()
                .setFlowId(Base64.encode(String.valueOf(id)));
        // 2.推送待办信息，使用try-catch避免影响上层调用方法的事务回滚
        try {
            portalRequest.deleteRequestInfo(deleteRequestInfoDTO);
        } catch (Exception e) {
            log.error("删除待办信息失败", e);
            return false;
        }
        return true;
    }
}
