package com.njcn.supervision.service.user.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.bpm.api.BpmProcessFeignClient;
import com.njcn.bpm.enums.BpmProcessInstanceStatusEnum;
import com.njcn.bpm.enums.BpmTaskStatusEnum;
import com.njcn.bpm.pojo.dto.BpmInstanceInfo;
import com.njcn.bpm.pojo.dto.BpmProcessInstanceCreateReqDTO;
import com.njcn.bpm.pojo.param.instance.BpmProcessInstanceCancelParam;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.supervision.enums.*;
import com.njcn.supervision.mapper.user.UserReportRenewalMapper;
import com.njcn.supervision.pojo.param.user.UserReportParam;
import com.njcn.supervision.pojo.po.user.*;
import com.njcn.supervision.service.user.*;
import com.njcn.supervision.utils.InstanceUtil;
import com.njcn.user.api.DeptFeignClient;
import com.njcn.user.api.UserFeignClient;
import com.njcn.user.pojo.vo.UserVO;
import com.njcn.web.utils.RequestUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户档案信息表	 服务实现类
 * </p>
 *
 * @author wr
 * @since 2024-06-26
 */
@Service
@RequiredArgsConstructor
public class UserReportRenewalServiceImpl extends ServiceImpl<UserReportRenewalMapper, UserReportRenewalPO> implements IUserReportRenewalService {

    private final UserReportPOServiceImpl userReportPOService;
    private final BpmProcessFeignClient bpmProcessFeignClient;
    private final UserFeignClient userFeignClient;
    private final DeptFeignClient deptFeignClient;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateProcessStatus(String businessId, Integer status) {
        UserReportRenewalPO userReportPO = this.getById(businessId);
        if (ObjUtil.isNotNull(userReportPO)) {
            if (Objects.equals(BpmTaskStatusEnum.APPROVE.getStatus(), status)) {
                UserReportParam userReportParam = new UserReportParam();
                userReportParam.setId(businessId);
                userReportPO.getUserReportMessageJson().setSaveOrCheckflag("0");
                BeanUtil.copyProperties(userReportPO.getUserReportMessageJson(), userReportParam);
                userReportPOService.addUserReport(userReportParam);
            }
            this.lambdaUpdate().set(UserReportRenewalPO::getStatus, status).eq(UserReportRenewalPO::getId, businessId).update();
        } else {
            throw new BusinessException(SupervisionResponseEnum.NO_USER_REPORT_UPDATE);
        }
    }

    @Override
    public BpmInstanceInfo getInstanceInfo(String businessId) {
        BpmInstanceInfo bpmInstanceInfo = new BpmInstanceInfo();
        UserReportRenewalPO userReportPO = this.getById(businessId);
        if(ObjectUtil.isNotNull(userReportPO)){
            bpmInstanceInfo.setHistoryInstanceId(userReportPO.getHistoryInstanceId());
            bpmInstanceInfo.setInstanceSign(userReportPO.getUserReportMessageJson().getProjectName()+"信息更新");
            return bpmInstanceInfo;
        }
        return null;
    }

    @Override
    public Set<String> getAllRejectInstanceIds() {
        Set<String> rejectInstanceIds = new HashSet<>();
        // 查询所有走了流程，但是流程状态为不通过的流程实例id
        LambdaQueryWrapper<UserReportRenewalPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserReportRenewalPO::getCreateBy, RequestUtil.getUserIndex())
                .eq(UserReportRenewalPO::getStatus, BpmProcessInstanceStatusEnum.REJECT.getStatus())
                .eq(UserReportRenewalPO::getState, DataStateEnum.ENABLE.getCode())
                .select(UserReportRenewalPO::getProcessInstanceId);
        List<UserReportRenewalPO> userReportRenewalPOList = this.baseMapper.selectList(lambdaQueryWrapper);
        List<String> result = userReportRenewalPOList.stream().map(UserReportRenewalPO::getProcessInstanceId).collect(Collectors.toList());
        if(CollectionUtil.isNotEmpty(result)){
            rejectInstanceIds.addAll(result);
        }
        return rejectInstanceIds;
    }


    @Override
    public UserReportRenewalPO getUserReportUpdateById(String id) {
        UserReportRenewalPO byId = this.getById(id);
        UserVO userVO = userFeignClient.getUserById(byId.getUserReportMessageJson().getReporter()).getData();
        byId.getUserReportMessageJson().setReporter(userVO.getName());
        byId.getUserReportMessageJson().setOrgName(deptFeignClient.getDeptById(byId.getUserReportMessageJson().getOrgId()).getData().getName());
        return byId;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addEditor(UserReportParam userReportParam) {
        UserReportRenewalPO po = new UserReportRenewalPO();
        UserReportPO userReportPO = new UserReportPO();
        BeanUtils.copyProperties(userReportParam, userReportPO);
        userReportPO.setState(DataStateEnum.ENABLE.getCode());
        if (Objects.equals(userReportParam.getSaveOrCheckflag(), "2")) {
            po.setStatus(BpmTaskStatusEnum.RUNNING.getStatus());
            userReportPOService.checkProjectName(userReportParam, !StringUtils.isEmpty(userReportParam.getId()));
        }else {
            po.setStatus(BpmTaskStatusEnum.WAIT.getStatus());
        }
        if (ObjectUtil.isNotNull(userReportParam.getDataType())) {
            userReportPO.setDataType(userReportParam.getDataType());
            if (userReportParam.getDataType() == 1) {
                userReportPO.setStatus(FlowStatusEnum.APPROVE.getCode());
            }
        } else {
            userReportPO.setDataType(0);
        }
        addition(userReportParam, userReportPO.getUserType());
        // 如何未提交审则不需要发起 BPM 流程
        if (Objects.equals(userReportParam.getSaveOrCheckflag(), "2")) {
            UserReportRenewalPO byId = this.getById(userReportParam.getId());
            if(ObjectUtil.isNotNull(byId)){
                if(Objects.equals(FlowStatusEnum.APPROVE.getCode(), byId.getStatus())) {
                    //处理历史流程id列表
                    String historyInstanceIds = InstanceUtil.dealHistoryId(byId.getProcessInstanceId(), byId.getHistoryInstanceId());
                    //保存历史流程id列表
                    po.setHistoryInstanceId(historyInstanceIds);
                }
            }
            Map<String, Object> processInstanceVariables = new HashMap<>(16);
            BpmProcessInstanceCreateReqDTO bpmProcessInstanceCreateReqDTO = new BpmProcessInstanceCreateReqDTO();
            bpmProcessInstanceCreateReqDTO.setProcessDefinitionKey(SupervisionKeyEnum.USER_REPORT_RENEWAL.getKey());
            bpmProcessInstanceCreateReqDTO.setBusinessKey(userReportPO.getId());
            bpmProcessInstanceCreateReqDTO.setStartUserSelectAssignees(userReportParam.getStartUserSelectAssignees());
            bpmProcessInstanceCreateReqDTO.setVariables(processInstanceVariables);
            String processInstanceId = bpmProcessFeignClient.createProcessInstance(RequestUtil.getUserIndex(), bpmProcessInstanceCreateReqDTO).getData();
            // 将工作流的编号，更新到流程单中
            po.setProcessInstanceId(processInstanceId);
        }
        String userReport = JSONObject.toJSONStringWithDateFormat(userReportParam, JSON.DEFFAULT_DATE_FORMAT);
        po.setId(userReportParam.getId());
        po.setUserReportMessage(userReport);
        po.setState(DataStateEnum.ENABLE.getCode());
        userReportPO.setCreateBy(RequestUtil.getUserIndex());
        if (this.saveOrUpdate(po)) {
            return userReportParam.getId();
        }
        return "失败";
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String resend(UserReportParam userReportParam) {
        UserReportRenewalPO po = this.getById(userReportParam.getId());
        //判断是否有权限操作
        InstanceUtil.judgeUserPower(RequestUtil.getUserIndex(), po.getCreateBy());
        if (Objects.equals(po.getStatus(), BpmTaskStatusEnum.APPROVE.getStatus())) {
            throw new BusinessException("当前流程以完成审批,无法重新发起");
        }
        //处理历史流程id列表
        String historyInstanceIds = InstanceUtil.dealHistoryId(po.getProcessInstanceId(), po.getHistoryInstanceId());
        addition(userReportParam, userReportParam.getUserType());

        // 发起 BPM 流程
        Map<String, Object> processInstanceVariables = new HashMap<>(16);
        BpmProcessInstanceCreateReqDTO bpmProcessInstanceCreateReqDTO = new BpmProcessInstanceCreateReqDTO();
        bpmProcessInstanceCreateReqDTO.setProcessDefinitionKey(SupervisionKeyEnum.USER_REPORT_RENEWAL.getKey());
        bpmProcessInstanceCreateReqDTO.setBusinessKey(userReportParam.getId());
        bpmProcessInstanceCreateReqDTO.setStartUserSelectAssignees(userReportParam.getStartUserSelectAssignees());
        bpmProcessInstanceCreateReqDTO.setVariables(processInstanceVariables);
        String processInstanceId = bpmProcessFeignClient.createProcessInstance(po.getCreateBy(), bpmProcessInstanceCreateReqDTO).getData();
        // 将工作流的编号，更新到流程单中
        po.setProcessInstanceId(processInstanceId);
        po.setStatus(BpmTaskStatusEnum.RUNNING.getStatus());
        po.setState(DataStateEnum.ENABLE.getCode());
        //保存历史流程id列表
        po.setHistoryInstanceId(historyInstanceIds);
        String userReport = JSONObject.toJSONStringWithDateFormat(userReportParam, JSON.DEFFAULT_DATE_FORMAT);
        po.setUserReportMessage(userReport);
        if (this.updateById(po)) {
            return userReportParam.getId();
        }
        return "失败";
    }

    @Override
    public String cancelUserReportRenewal(BpmProcessInstanceCancelParam cancelReqVO) {
        //准备取消该流程，需要远程调用接口
        UserReportRenewalPO userReportRenewalPO = this.baseMapper.selectById(cancelReqVO.getId());
        //取消流程
        bpmProcessFeignClient.cancelProcessInstanceByStartUser(cancelReqVO);
        //更新状态
        userReportRenewalPO.setStatus(BpmProcessInstanceStatusEnum.CANCEL.getStatus());
        this.updateById(userReportRenewalPO);
        return userReportRenewalPO.getId();
    }

    private void addition(UserReportParam userReportParam, Integer userType) {
        if (
                CollectionUtil.newArrayList(
                        UserNatureEnum.BUILD_POWER_GRID.getCode(),
                        UserNatureEnum.EXTEND_POWER_GRID.getCode()
                ).contains(userType)) {
            //电网工程类用户额外数据
            UserReportProjectPO userReportProjectPO = userReportParam.getUserReportProjectPO();
            userReportProjectPO.setId(userReportParam.getId());
            userReportProjectPO.setState(DataStateEnum.ENABLE.getCode());
        } else if (
                CollectionUtil.newArrayList(
                        UserNatureEnum.BUILD_NON_LINEAR_LOAD.getCode(),
                        UserNatureEnum.EXTEND_NON_LINEAR_LOAD.getCode(),
                        UserNatureEnum.BUILD_NEW_ENERGY_POWER_STATION.getCode(),
                        UserNatureEnum.EXTEND_NEW_ENERGY_POWER_STATION.getCode()
                ).contains(userType)) {
            //非线性负荷用户 & 新能源发电站用户
            UserReportSubstationPO userReportSubstationPO = userReportParam.getUserReportSubstationPO();
            userReportSubstationPO.setId(userReportParam.getId());
            userReportSubstationPO.setState(DataStateEnum.ENABLE.getCode());
        } else if (UserNatureEnum.SENSITIVE_USER.getCode().equals(userType)) {
            // 敏感及重要用户
            UserReportSensitivePO userReportSensitivePO = userReportParam.getUserReportSensitivePO();
            userReportSensitivePO.setId(userReportParam.getId());
            userReportSensitivePO.setState(DataStateEnum.ENABLE.getCode());
        }
    }
}
