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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.StrPool;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
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.BpmResponseEnum;
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.device.pq.api.LineFeignClient;
import com.njcn.device.pq.enums.RunFlagEnum;
import com.njcn.device.pq.pojo.param.DataParam;
import com.njcn.device.pq.pojo.po.line.LineInfoVO;
import com.njcn.device.pq.pojo.vo.DeviceVO;
import com.njcn.device.pq.pojo.vo.LineDetailVO;
import com.njcn.supervision.enums.SupervisionKeyEnum;
import com.njcn.supervision.enums.SupervisionResponseEnum;
import com.njcn.supervision.enums.SupervisionUserStatusEnum;
import com.njcn.supervision.mapper.device.QuitRunningDeviceMapper;
import com.njcn.supervision.pojo.param.device.QuitRunningDeviceParam;
import com.njcn.supervision.pojo.po.device.QuitRunningDevice;
import com.njcn.supervision.pojo.vo.device.QuitRunningDeviceVO;
import com.njcn.supervision.service.device.IQuitRunningDeviceService;
import com.njcn.supervision.service.user.UserReportPOService;
import com.njcn.supervision.utils.InstanceUtil;
import com.njcn.user.api.UserFeignClient;
import com.njcn.web.factory.PageFactory;
import com.njcn.web.utils.RequestUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author hongawen
 * @since 2024-05-13
 */
@Service
@RequiredArgsConstructor
public class QuitRunningDeviceServiceImpl extends ServiceImpl<QuitRunningDeviceMapper, QuitRunningDevice> implements IQuitRunningDeviceService {


    private final BpmProcessFeignClient bpmProcessFeignClient;

    private final LineFeignClient lineFeignClient;

    private final UserFeignClient userFeignClient;

    private final UserReportPOService userReportPOService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addRunningDevice(QuitRunningDeviceParam quitRunningDeviceParam) {
        //判断该设备是否已经有在申请的
//        checkQuitRunningDevice(quitRunningDeviceParam, false);
        QuitRunningDevice quitRunningDevice = new QuitRunningDevice();
        BeanUtils.copyProperties(quitRunningDeviceParam, quitRunningDevice);

        quitRunningDevice.setDevStatus(quitRunningDeviceParam.getDevStatus());

        quitRunningDevice.setState(DataStateEnum.ENABLE.getCode());
        //设置状态
        if (Objects.equals(quitRunningDeviceParam.getSaveOrCheckflag(), "1")) {
            quitRunningDevice.setStatus(BpmTaskStatusEnum.WAIT.getStatus());

        } else {
            quitRunningDevice.setStatus(BpmTaskStatusEnum.RUNNING.getStatus());

        }

        this.saveOrUpdate(quitRunningDevice);
        quitRunningDevice = this.baseMapper.selectById(quitRunningDevice.getId());

        // 发起 BPM 流程
        if (Objects.equals(quitRunningDeviceParam.getSaveOrCheckflag(), "2")) {

            Map<String, Object> processInstanceVariables = new HashMap<>();
            BpmProcessInstanceCreateReqDTO bpmProcessInstanceCreateReqDTO = new BpmProcessInstanceCreateReqDTO();
            bpmProcessInstanceCreateReqDTO.setProcessDefinitionKey(SupervisionKeyEnum.QUIT_RUNNING_DEVICE.getKey());
            bpmProcessInstanceCreateReqDTO.setBusinessKey(quitRunningDevice.getId());
            bpmProcessInstanceCreateReqDTO.setStartUserSelectAssignees(quitRunningDeviceParam.getStartUserSelectAssignees());
            bpmProcessInstanceCreateReqDTO.setVariables(processInstanceVariables);
            String processInstanceId = bpmProcessFeignClient.createProcessInstance(quitRunningDevice.getCreateBy(), bpmProcessInstanceCreateReqDTO).getData();
            // 将工作流的编号，更新到流程单中
            quitRunningDevice.setProcessInstanceId(processInstanceId);
            this.baseMapper.updateById(quitRunningDevice);
        }
        return quitRunningDevice.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String updateQuitRunningDevice(QuitRunningDeviceParam.QuitRunningDeviceUpdateParam quitRunningDeviceUpdateParam) {
        QuitRunningDevice quitRunningDevice = this.baseMapper.selectById(quitRunningDeviceUpdateParam.getId());
        //判断是否有权限操作
        InstanceUtil.judgeUserPower(RequestUtil.getUserIndex(), quitRunningDevice.getCreateBy());
        //监测点只有退运，终端由前端选择了指定状态
        if (quitRunningDevice.getDeviceType() == 2) {
            quitRunningDevice.setDevStatus(4);
        }
        quitRunningDeviceUpdateParam.setProcessInstanceId(quitRunningDevice.getProcessInstanceId());
        quitRunningDeviceUpdateParam.setHistoryInstanceId(quitRunningDevice.getHistoryInstanceId());
        BeanUtils.copyProperties(quitRunningDeviceUpdateParam, quitRunningDevice);
        quitRunningDevice.setState(DataStateEnum.ENABLE.getCode());
        quitRunningDevice.setStatus(BpmTaskStatusEnum.RUNNING.getStatus());
        //处理历史流程id列表
        String historyInstanceIds = InstanceUtil.dealHistoryId(quitRunningDevice.getProcessInstanceId(), quitRunningDevice.getHistoryInstanceId());
        // 发起 BPM 流程
        Map<String, Object> processInstanceVariables = new HashMap<>();
        BpmProcessInstanceCreateReqDTO bpmProcessInstanceCreateReqDTO = new BpmProcessInstanceCreateReqDTO();
        bpmProcessInstanceCreateReqDTO.setProcessDefinitionKey(SupervisionKeyEnum.QUIT_RUNNING_DEVICE.getKey());
        bpmProcessInstanceCreateReqDTO.setBusinessKey(quitRunningDevice.getId());
        bpmProcessInstanceCreateReqDTO.setStartUserSelectAssignees(quitRunningDeviceUpdateParam.getStartUserSelectAssignees());
        bpmProcessInstanceCreateReqDTO.setVariables(processInstanceVariables);
        String processInstanceId = bpmProcessFeignClient.createProcessInstance(quitRunningDevice.getCreateBy(), bpmProcessInstanceCreateReqDTO).getData();
        // 将工作流的编号，更新到流程单中
        quitRunningDevice.setProcessInstanceId(processInstanceId);
        //保存历史流程id列表
        quitRunningDevice.setHistoryInstanceId(historyInstanceIds);
        this.baseMapper.updateById(quitRunningDevice);
        return quitRunningDevice.getId();
    }

    @Override
    public Page<QuitRunningDeviceVO> getQuitRunningDevice(QuitRunningDeviceParam.QuitRunningDeviceQueryParam quitRunningDeviceQueryParam) {
        DataParam param = new DataParam();
        param.setOrgId(RequestUtil.getDeptIndex());
        param.setType(quitRunningDeviceQueryParam.getDeviceType());
        param.setSearchValue(quitRunningDeviceQueryParam.getSearchValue());
        List<LineDetailVO.Detail> lineDetail = lineFeignClient.getDeptDeviceDetailData(param).getData();
        if (CollUtil.isEmpty(lineDetail)) {
            return new Page<>();
        }
        Map<String, LineDetailVO.Detail> mapDetail = new HashMap<>();
        QueryWrapper<QuitRunningDeviceVO> quitRunningDeviceVOQueryWrapper = new QueryWrapper<>();
        quitRunningDeviceVOQueryWrapper.eq("supervision_quit_running_device.state", DataStateEnum.ENABLE.getCode());
        if (Objects.nonNull(quitRunningDeviceQueryParam)) {
            //判断监测点/设备的选择
//            if (Objects.nonNull(quitRunningDeviceQueryParam.getDeviceType()) && Objects.nonNull(quitRunningDeviceQueryParam.getDeviceId())) {
//                quitRunningDeviceVOQueryWrapper.eq("supervision_quit_running_device.device_type", quitRunningDeviceQueryParam.getDeviceType());
//                quitRunningDeviceVOQueryWrapper.eq("supervision_quit_running_device.device_id", quitRunningDeviceQueryParam.getDeviceId());
//            }
            if (Objects.nonNull(quitRunningDeviceQueryParam.getSearchBeginTime()) && Objects.nonNull(quitRunningDeviceQueryParam.getSearchEndTime())) {
                quitRunningDeviceVOQueryWrapper.between("supervision_quit_running_device.Create_Time",
                        DateUtil.beginOfDay(DateUtil.parse(quitRunningDeviceQueryParam.getSearchBeginTime())),
                        DateUtil.endOfDay(DateUtil.parse(quitRunningDeviceQueryParam.getSearchEndTime())));
            }
            //判断监测点/设备的选择
            quitRunningDeviceVOQueryWrapper.eq("supervision_quit_running_device.device_type", quitRunningDeviceQueryParam.getDeviceType());
            if (2 == quitRunningDeviceQueryParam.getDeviceType()) {
                mapDetail.putAll(lineDetail.stream().collect(Collectors.toMap(LineDetailVO.Detail::getLineId, Function.identity())));
            } else {
                mapDetail.putAll(lineDetail.stream().collect(Collectors.toMap(LineDetailVO.Detail::getDevId, Function.identity(), (key1, key2) -> key1)));
            }
            quitRunningDeviceVOQueryWrapper
                    .and(CollUtil.isNotEmpty(InstanceUtil.filterTaskStatus()),w -> w.in("supervision_quit_running_device.status", InstanceUtil.filterTaskStatus())
                            .or()
                            .eq("supervision_quit_running_device.create_by", RequestUtil.getUserIndex())
                    );

            if (Objects.nonNull(quitRunningDeviceQueryParam.getStatus())) {
                quitRunningDeviceVOQueryWrapper.eq("supervision_quit_running_device.status", quitRunningDeviceQueryParam.getStatus());
            }
            quitRunningDeviceVOQueryWrapper.and(x -> x
                    .in(CollUtil.isNotEmpty(mapDetail.keySet()), "supervision_quit_running_device.device_id", mapDetail.keySet())
                    .or()
                    .isNull("supervision_quit_running_device.device_id")
                    .or().eq("supervision_quit_running_device.device_id", "")
            );
        }

        //获取当前用户部门所有同事的id，查看该部门下所有的数据
        List<String> colleaguesIds = userFeignClient.getColleaguesIdByUserId(RequestUtil.getUserIndex()).getData();
        quitRunningDeviceVOQueryWrapper.in("supervision_quit_running_device.Create_By", colleaguesIds)
                .orderByDesc("supervision_quit_running_device.Update_Time");
        Page<QuitRunningDeviceVO> page = this.baseMapper.page(new Page<>(PageFactory.getPageNum(quitRunningDeviceQueryParam), PageFactory.getPageSize(quitRunningDeviceQueryParam)), quitRunningDeviceVOQueryWrapper);
        List<QuitRunningDeviceVO> records = page.getRecords();
        if (CollectionUtil.isNotEmpty(records)) {
            for (QuitRunningDeviceVO record : records) {
                if (record.getDeviceType() == 1) {
                    //获取装置详细信息
                    if (mapDetail.containsKey(record.getDeviceId())) {
                        LineDetailVO.Detail detail = mapDetail.get(record.getDeviceId());
                        record.setDeviceName(detail.getDevName());
                        record.setDeviceStatus(detail.getRunFlag());
                        record.setGdName(detail.getGdName());
                        record.setSubName(detail.getSubName());
                    }
                } else if (record.getDeviceType() == 2) {
                    //获取监测点详细信息
                    if (mapDetail.containsKey(record.getDeviceId())) {
                        LineDetailVO.Detail detail = mapDetail.get(record.getDeviceId());
                        record.setDeviceName(detail.getVolName().concat("_").concat(detail.getLineName()));
                        record.setDeviceStatus(detail.getRunFlag());
                        record.setGdName(detail.getGdName());
                        record.setSubName(detail.getSubName());
                    }
                }
            }
        }
        page.setRecords(records);
        return page;

    }

    /**
     * 监听该流程的状态
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateProcessStatus(String businessKey, Integer status) {
        QuitRunningDevice quitRunningDevice = this.baseMapper.selectById(businessKey);
        //如果状态为审批通过
        if (status.equals(BpmProcessInstanceStatusEnum.APPROVE.getStatus())) {
            //通过，则需要远程将该装置调整为退运
            if (quitRunningDevice.getDeviceType() == 1) {
                //修改装置
                lineFeignClient.updateDeviceRunFlag(quitRunningDevice.getDeviceId(), quitRunningDevice.getDevStatus());
            } else if (quitRunningDevice.getDeviceType() == 2) {
                //修改监测点
                lineFeignClient.updateLineRunFlag(quitRunningDevice.getDeviceId(), quitRunningDevice.getDevStatus());
                userReportPOService.updateUserStatus(businessKey, SupervisionUserStatusEnum.QUIT.getCode());
            }
        }
        quitRunningDevice.setStatus(status);
        this.updateById(quitRunningDevice);
    }

    @Override
    public BpmInstanceInfo getInstanceInfo(String businessId) {
        BpmInstanceInfo bpmInstanceInfo = new BpmInstanceInfo();
        QuitRunningDeviceVO quitRunningDeviceVO = this.getVOById(businessId);
        if(Objects.isNull(quitRunningDeviceVO)){
            return null;
        }
        bpmInstanceInfo.setHistoryInstanceId(quitRunningDeviceVO.getHistoryInstanceId());
        String sign = quitRunningDeviceVO.getGdName()
                .concat(StrPool.SLASH)
                .concat(quitRunningDeviceVO.getSubName())
                .concat(StrPool.SLASH)
                .concat(quitRunningDeviceVO.getDeviceName())
                .concat("运行状态由")
                .concat(RunFlagEnum.getRunFlagRemarkByStatus(quitRunningDeviceVO.getDevOriginalStatus()))
                .concat("变更为")
                .concat(RunFlagEnum.getRunFlagRemarkByStatus(quitRunningDeviceVO.getDevStatus()));
        bpmInstanceInfo.setInstanceSign(sign);
        return bpmInstanceInfo;
    }

    @Override
    public Set<String> getAllRejectInstanceIds() {
        Set<String> rejectInstanceIds = new HashSet<>();
        //查询当前用户创建的createBy的流程审核不通过的
        LambdaQueryWrapper<QuitRunningDevice> deviceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        deviceLambdaQueryWrapper.eq(QuitRunningDevice::getCreateBy, RequestUtil.getUserIndex())
                .eq(QuitRunningDevice::getStatus, BpmProcessInstanceStatusEnum.REJECT.getStatus())
                .eq(QuitRunningDevice::getState, DataStateEnum.ENABLE.getCode())
                .select(QuitRunningDevice::getProcessInstanceId);
        List<QuitRunningDevice> quitRunningDevices = this.baseMapper.selectList(deviceLambdaQueryWrapper);
        if (CollectionUtil.isNotEmpty(quitRunningDevices)) {
            List<String> result = quitRunningDevices.stream().map(QuitRunningDevice::getProcessInstanceId).collect(Collectors.toList());
            rejectInstanceIds.addAll(result);
        }
        return rejectInstanceIds;
    }

    @Override
    public QuitRunningDeviceVO getVOById(String id) {
        QuitRunningDevice quitRunningDevice = this.baseMapper.selectById(id);
        QuitRunningDeviceVO quitRunningDeviceVO = new QuitRunningDeviceVO();
        BeanUtils.copyProperties(quitRunningDevice, quitRunningDeviceVO);
        if (StringUtils.isNotEmpty(quitRunningDeviceVO.getDeviceId())) {
            if (quitRunningDeviceVO.getDeviceType() == 1) {

                DeviceVO deviceVO = lineFeignClient.getDeviceDetailData(quitRunningDeviceVO.getDeviceId()).getData();
                quitRunningDeviceVO.setDeviceName(deviceVO.getName());
                quitRunningDeviceVO.setDeviceStatus(deviceVO.getRunFlag());
                quitRunningDeviceVO.setGdName(deviceVO.getGdName());
                quitRunningDeviceVO.setSubName(deviceVO.getSubName());
                //获取装置详细信息
            } else if (quitRunningDeviceVO.getDeviceType() == 2) {
                //获取监测点详细信息
                LineInfoVO lineInfoVO = lineFeignClient.getLineInfoVO(quitRunningDeviceVO.getDeviceId()).getData();
                quitRunningDeviceVO.setDeviceStatus(lineInfoVO.getRunFlag());
                quitRunningDeviceVO.setDeviceName(lineInfoVO.getVolName().concat("_").concat(lineInfoVO.getLineName()));
                quitRunningDeviceVO.setGdName(lineInfoVO.getGdName());
                quitRunningDeviceVO.setSubName(lineInfoVO.getSubName());
                quitRunningDeviceVO.setVolName(lineInfoVO.getVolName());
            }
        }

        return quitRunningDeviceVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String cancelQuitRunningDevice(BpmProcessInstanceCancelParam cancelReqVO) {
        //准备取消该流程，需要远程调用接口
        QuitRunningDevice quitRunningDevice = this.baseMapper.selectById(cancelReqVO.getId());
        //判断是否有权限操作
        InstanceUtil.judgeUserPower(RequestUtil.getUserIndex(), quitRunningDevice.getCreateBy());
        //取消流程
        bpmProcessFeignClient.cancelProcessInstanceByStartUser(cancelReqVO);
        //更新状态
        quitRunningDevice.setStatus(BpmProcessInstanceStatusEnum.CANCEL.getStatus());
        this.updateById(quitRunningDevice);
        return quitRunningDevice.getId();
    }

    @Override
    public Boolean deleteQuitRunningDevice(List<String> supervisionId) {
        List<QuitRunningDevice> quitRunningDevices = this.listByIds(supervisionId);
        if (CollUtil.isEmpty(quitRunningDevices)) {
            throw new BusinessException(SupervisionResponseEnum.EXISTENCE_OR_NOT);
        }
        List<String> collect = quitRunningDevices.stream().map(QuitRunningDevice::getCreateBy).distinct().collect(Collectors.toList());
        long count = quitRunningDevices.stream().filter(x -> !BpmTaskStatusEnum.WAIT.getStatus().equals(x.getStatus())).count();
        //判断是否有权限操作
        InstanceUtil.deleteRole(RequestUtil.getUserIndex(), collect, count);
        return this.update(new LambdaUpdateWrapper<QuitRunningDevice>().set(QuitRunningDevice::getState, DataStateEnum.DELETED.getCode())
                .in(QuitRunningDevice::getId, supervisionId));
    }

    /**
     * 校验是否已经有在审批的当前设备
     */
    private void checkQuitRunningDevice(QuitRunningDeviceParam quitRunningDeviceParam, boolean isExcludeSelf) {
        LambdaQueryWrapper<QuitRunningDevice> quitRunningDeviceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //判断流程表单的名称
        quitRunningDeviceLambdaQueryWrapper
                .eq(QuitRunningDevice::getDeviceId, quitRunningDeviceParam.getDeviceId())
                //审批中、审批通过
                .in(QuitRunningDevice::getStatus, CollectionUtil.newArrayList(BpmProcessInstanceStatusEnum.RUNNING.getStatus(), BpmProcessInstanceStatusEnum.APPROVE.getStatus()))
                .eq(QuitRunningDevice::getState, DataStateEnum.ENABLE.getCode());
        //更新的时候，需排除当前记录
        if (isExcludeSelf) {
            if (quitRunningDeviceParam instanceof QuitRunningDeviceParam.QuitRunningDeviceUpdateParam) {
                quitRunningDeviceLambdaQueryWrapper.ne(QuitRunningDevice::getId, ((QuitRunningDeviceParam.QuitRunningDeviceUpdateParam) quitRunningDeviceParam).getId());
            }
        }
        int deviceCountByAccount = this.count(quitRunningDeviceLambdaQueryWrapper);
        //大于等于1个则表示重复
        if (deviceCountByAccount >= 1) {
            throw new BusinessException(BpmResponseEnum.QUIT_RUNNING_REPEAT);
        }
    }

}
