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 cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
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.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.FlowStatusEnum;
import com.njcn.supervision.enums.SupervisionKeyEnum;
import com.njcn.supervision.enums.SupervisionResponseEnum;
import com.njcn.supervision.enums.SupervisionUserStatusEnum;
import com.njcn.supervision.mapper.device.SupervisionTempLineDebugPOMapper;
import com.njcn.supervision.mapper.device.SupervisionTempLineReportMapper;
import com.njcn.supervision.pojo.param.device.SupervisionTempLineReportParam;
import com.njcn.supervision.pojo.po.device.SupervisionTempLineDebugPO;
import com.njcn.supervision.pojo.po.device.SupervisionTempLineReport;
import com.njcn.supervision.pojo.vo.device.SupervisionTempLineReportVO;
import com.njcn.supervision.service.device.SupervisionTempLineReportService;
import com.njcn.supervision.service.user.UserReportPOService;
import com.njcn.supervision.utils.InstanceUtil;
import com.njcn.system.api.DictTreeFeignClient;
import com.njcn.user.api.DeptFeignClient;
import com.njcn.user.api.UserFeignClient;
import com.njcn.user.pojo.vo.UserVO;
import com.njcn.web.factory.PageFactory;
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;


/**
 * Description:
 * Date: 2024/5/11  14:07【需求编号】
 *
 * @author clam
 * @version V1.0.0
 */
@Service
@RequiredArgsConstructor
public class SupervisionTempLineReportServiceImpl extends ServiceImpl<SupervisionTempLineReportMapper, SupervisionTempLineReport> implements SupervisionTempLineReportService {


    private final BpmProcessFeignClient bpmProcessFeignClient;
    private final DeptFeignClient deptFeignClient;
    private final UserFeignClient userFeignClient;
    private final DictTreeFeignClient dictTreeFeignClient;
    private final UserReportPOService userReportPOService;
    private final SupervisionTempLineDebugPOMapper supervisionTempLineDebugPOMapper;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addTempLineReport(SupervisionTempLineReportParam supervisionTempLineReportParam) {
        SupervisionTempLineReport supervisionTempLineReport = new SupervisionTempLineReport();
        BeanUtils.copyProperties(supervisionTempLineReportParam, supervisionTempLineReport);
        if (Objects.equals(supervisionTempLineReportParam.getSaveOrCheckflag(), "2")) {
            checkLineId(supervisionTempLineReportParam, !StringUtils.isEmpty(supervisionTempLineReportParam.getId()));
        }
        //设置状态
        if (Objects.equals(supervisionTempLineReportParam.getSaveOrCheckflag(), "1")) {
            supervisionTempLineReport.setStatus(BpmTaskStatusEnum.WAIT.getStatus());

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

        }


        supervisionTempLineReport.setState(DataStateEnum.ENABLE.getCode());

        this.saveOrUpdate(supervisionTempLineReport);
        String id = supervisionTempLineReport.getId();
        supervisionTempLineReport = this.baseMapper.selectById(id);

        if (Objects.equals(supervisionTempLineReportParam.getSaveOrCheckflag(), "2")) {
            // 发起 BPM 流程
            Map<String, Object> processInstanceVariables = new HashMap<>(16);
            BpmProcessInstanceCreateReqDTO bpmProcessInstanceCreateReqDTO = new BpmProcessInstanceCreateReqDTO();
            bpmProcessInstanceCreateReqDTO.setProcessDefinitionKey(SupervisionKeyEnum.LINE_INFO_ADD.getKey());
            bpmProcessInstanceCreateReqDTO.setBusinessKey(id);
            bpmProcessInstanceCreateReqDTO.setStartUserSelectAssignees(supervisionTempLineReportParam.getStartUserSelectAssignees());
            bpmProcessInstanceCreateReqDTO.setVariables(processInstanceVariables);
            String processInstanceId = bpmProcessFeignClient.createProcessInstance(supervisionTempLineReport.getCreateBy(), bpmProcessInstanceCreateReqDTO).getData();
            // 将工作流的编号，更新到流程单中
            supervisionTempLineReport.setProcessInstanceId(processInstanceId);
            this.baseMapper.updateById(supervisionTempLineReport);
        }
        return id;
    }

    @Override
    public String updateLineReport(SupervisionTempLineReportParam.SupervisionTempLineReportUpdate supervisionTempLineReportParam) {
        if (Objects.equals(supervisionTempLineReportParam.getSaveOrCheckflag(), "2")) {
            checkLineId(supervisionTempLineReportParam, !StringUtils.isEmpty(supervisionTempLineReportParam.getId()));
        }
        SupervisionTempLineReport supervisionTempLineReport = this.baseMapper.selectById(supervisionTempLineReportParam.getId());
        //判断是否有权限操作
        InstanceUtil.judgeUserPower(RequestUtil.getUserIndex(), supervisionTempLineReport.getCreateBy());
        supervisionTempLineReportParam.setProcessInstanceId(supervisionTempLineReport.getProcessInstanceId());
        supervisionTempLineReportParam.setHistoryInstanceId(supervisionTempLineReport.getHistoryInstanceId());
        BeanUtils.copyProperties(supervisionTempLineReportParam, supervisionTempLineReport);
        supervisionTempLineReport.setStatus(BpmTaskStatusEnum.RUNNING.getStatus());
        supervisionTempLineReport.setState(DataStateEnum.ENABLE.getCode());
        //处理历史流程id列表
        String historyInstanceIds = InstanceUtil.dealHistoryId(supervisionTempLineReport.getProcessInstanceId(), supervisionTempLineReport.getHistoryInstanceId());
        // 发起 BPM 流程
        Map<String, Object> processInstanceVariables = new HashMap<>(16);
        BpmProcessInstanceCreateReqDTO bpmProcessInstanceCreateReqDTO = new BpmProcessInstanceCreateReqDTO();
        bpmProcessInstanceCreateReqDTO.setProcessDefinitionKey(SupervisionKeyEnum.LINE_INFO_ADD.getKey());
        bpmProcessInstanceCreateReqDTO.setBusinessKey(supervisionTempLineReport.getId());
        bpmProcessInstanceCreateReqDTO.setStartUserSelectAssignees(supervisionTempLineReportParam.getStartUserSelectAssignees());
        bpmProcessInstanceCreateReqDTO.setVariables(processInstanceVariables);
        String processInstanceId = bpmProcessFeignClient.createProcessInstance(supervisionTempLineReport.getCreateBy(), bpmProcessInstanceCreateReqDTO).getData();
        // 将工作流的编号，更新到流程单中
        supervisionTempLineReport.setProcessInstanceId(processInstanceId);
        //保存历史流程id列表
        supervisionTempLineReport.setHistoryInstanceId(historyInstanceIds);
        this.baseMapper.updateById(supervisionTempLineReport);
        return supervisionTempLineReport.getId();
    }

    @Override
    public Page<SupervisionTempLineReportVO> getTempLineReport(SupervisionTempLineReportParam.SupervisionTempLineReportQuery supervisionTempLineReportQuery) {
        QueryWrapper<SupervisionTempLineReport> queryWrapper = new QueryWrapper<>();
        //获取当前用户部门所有同事的id，查看该部门下所有的数据
        List<String> colleaguesIds = userFeignClient.getColleaguesIdByUserId(RequestUtil.getUserIndex()).getData();
        queryWrapper.in("supervision_temp_line_report.create_by", colleaguesIds)
                .eq("supervision_temp_line_report.state", DataStateEnum.ENABLE.getCode())
                .in(CollectionUtil.isNotEmpty(supervisionTempLineReportQuery.getStatueList()), "supervision_temp_line_report.status", supervisionTempLineReportQuery.getStatueList());
        if (StrUtil.isNotBlank(supervisionTempLineReportQuery.getOrgNo())) {
            /*获取直接下属子单位*/
            List<String> data = deptFeignClient.getDepSonIdtByDeptId(supervisionTempLineReportQuery.getOrgNo()).getData();
            queryWrapper.in("supervision_temp_line_report.org_id", data);
        }
        queryWrapper
                .and(CollUtil.isNotEmpty(InstanceUtil.filterTaskStatus()), w -> w.in("supervision_temp_line_report.status", InstanceUtil.filterTaskStatus())
                        .or()
                        .eq("supervision_temp_line_report.create_by", RequestUtil.getUserIndex())
                );

        if (Objects.nonNull(supervisionTempLineReportQuery.getStatus())) {
            queryWrapper.eq("supervision_temp_line_report.status", supervisionTempLineReportQuery.getStatus());
        }
        if (StrUtil.isNotBlank(supervisionTempLineReportQuery.getSearchValue())) {
            queryWrapper.and(x -> x
                    .like("supervision_temp_line_report.Power_Substation_Name", supervisionTempLineReportQuery.getSearchValue())
                    .or()
                    .like("supervision_temp_line_report.connected_bus", supervisionTempLineReportQuery.getSearchValue())
                    .or()
                    .like("supervision_temp_line_report.monitoring_terminal_name", supervisionTempLineReportQuery.getSearchValue())
                    .or()
                    .like("supervision_temp_line_report.line_name", supervisionTempLineReportQuery.getSearchValue())
            );
        }
        //添加上时间范围
        if (Objects.nonNull(supervisionTempLineReportQuery.getSearchBeginTime()) && Objects.nonNull(supervisionTempLineReportQuery.getSearchEndTime())) {
            queryWrapper.between("supervision_temp_line_report.Create_Time",
                    DateUtil.beginOfDay(DateUtil.parse(supervisionTempLineReportQuery.getSearchBeginTime())),
                    DateUtil.endOfDay(DateUtil.parse(supervisionTempLineReportQuery.getSearchEndTime())));
        }
        queryWrapper.orderByDesc("supervision_temp_line_report.Update_Time");
        return this.baseMapper.page(new Page<>(PageFactory.getPageNum(supervisionTempLineReportQuery), PageFactory.getPageSize(supervisionTempLineReportQuery)), queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateProcessStatus(String businessKey, Integer status) {
        this.lambdaUpdate().set(SupervisionTempLineReport::getStatus, status).eq(SupervisionTempLineReport::getId, businessKey).update();
        if (status.equals(BpmProcessInstanceStatusEnum.APPROVE.getStatus())) {
            SupervisionTempLineReport byId = this.getById(businessKey);

            userReportPOService.updateUserStatus(businessKey, SupervisionUserStatusEnum.BUILD.getCode());
            //新增监测点联调
            SupervisionTempLineDebugPO supervisionTempLineDebugPO = new SupervisionTempLineDebugPO();
            supervisionTempLineDebugPO.setId(businessKey);

            supervisionTempLineDebugPO.setState(DataStateEnum.ENABLE.getCode());
            supervisionTempLineDebugPO.setStatus(BpmTaskStatusEnum.WAIT.getStatus());
            supervisionTempLineDebugPO.setCreateBy(byId.getCreateBy());
            supervisionTempLineDebugPOMapper.insert(supervisionTempLineDebugPO);
        }
    }

    @Override
    public BpmInstanceInfo getInstanceInfo(String businessId) {
        BpmInstanceInfo bpmInstanceInfo = new BpmInstanceInfo();
        SupervisionTempLineReportVO supervisionTempLineReportVO = this.getDetailTempLine(businessId);
        if (ObjectUtil.isNotNull(supervisionTempLineReportVO)) {
            bpmInstanceInfo.setHistoryInstanceId(supervisionTempLineReportVO.getHistoryInstanceId());
            String powerSubstationName = supervisionTempLineReportVO.getPowerSubstationName();
            if (StrUtil.isNotBlank(powerSubstationName)) {
                powerSubstationName = powerSubstationName.concat(StrPool.SLASH);
            } else {
                powerSubstationName = "";
            }
            String sign = powerSubstationName
                    .concat(supervisionTempLineReportVO.getMonitoringTerminalName())
                    .concat(StrPool.SLASH)
                    .concat(supervisionTempLineReportVO.getConnectedBus())
                    .concat(StrPool.SLASH)
                    .concat(supervisionTempLineReportVO.getLineName());
            bpmInstanceInfo.setInstanceSign(sign);
        }
        return null;
    }

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

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

    @Override
    public SupervisionTempLineReportVO getDetailTempLine(String id) {
        SupervisionTempLineReportVO vo = null;
        SupervisionTempLineReport byId = this.getById(id);
        if (ObjectUtil.isNotNull(byId)) {
            vo = new SupervisionTempLineReportVO();
            BeanUtils.copyProperties(byId, vo);
            //处理特殊字段，用户名、部门名
            UserVO userVO = userFeignClient.getUserById(vo.getCreateBy()).getData();
            vo.setReporter(userVO.getName());
            if (StringUtils.isNotEmpty(vo.getOrgId())) {
                vo.setOrgName(deptFeignClient.getDeptById(vo.getOrgId()).getData().getName());
            }
            if (StringUtils.isNotEmpty(vo.getLoadType())) {
                vo.setLoadType(dictTreeFeignClient.queryById(vo.getLoadType()).getData().getName());
            }
            if (StringUtils.isNotEmpty(vo.getBusinessType())) {
                vo.setBusinessType(dictTreeFeignClient.queryById(vo.getBusinessType()).getData().getName());
            }
        }
        return vo;
    }

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

    private void checkLineId(SupervisionTempLineReportParam supervisionTempLineReportParam, boolean isExcludeSelf) {
        //保存时不为空则不校验
        if (Objects.nonNull(supervisionTempLineReportParam.getNum()) || Objects.nonNull(supervisionTempLineReportParam.getLineName())) {
            LambdaQueryWrapper<SupervisionTempLineReport> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper
                    .eq(SupervisionTempLineReport::getMonitoringTerminalCode, supervisionTempLineReportParam.getMonitoringTerminalCode())
                    .and(wrapper -> wrapper.eq(SupervisionTempLineReport::getNum, supervisionTempLineReportParam.getNum())
                            .or()
                            .eq(SupervisionTempLineReport::getLineName, supervisionTempLineReportParam.getLineName())
                    )
                    .eq(SupervisionTempLineReport::getState, DataStateEnum.ENABLE.getCode());
            //更新的时候，需排除当前记录
            if (isExcludeSelf) {
                if (supervisionTempLineReportParam instanceof SupervisionTempLineReportParam.SupervisionTempLineReportUpdate) {
                    lambdaQueryWrapper.ne(SupervisionTempLineReport::getId, ((SupervisionTempLineReportParam.SupervisionTempLineReportUpdate) supervisionTempLineReportParam).getId());
                } else {
                    lambdaQueryWrapper.ne(SupervisionTempLineReport::getId, (supervisionTempLineReportParam).getId());

                }


            }
            List<SupervisionTempLineReport> list = this.baseMapper.selectList(lambdaQueryWrapper);
            if (CollectionUtil.isNotEmpty(list)) {
                //过滤已取消的申请
                list = list.stream()
                        .filter(temp -> !temp.getStatus().equals(FlowStatusEnum.CANCEL.getCode()))
                        .collect(Collectors.toList());
                //如果还存在，则说明有人申请过了
                if (CollectionUtil.isNotEmpty(list)) {
                    throw new BusinessException(supervisionTempLineReportParam.getLineName().concat(",监测点线路号或监测点名称").concat("以使用"));
                }
            }
        }
    }
}
