package com.njcn.supervision.service.survey.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.enums.common.DealStateEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.device.pq.api.LineFeignClient;
import com.njcn.device.pq.pojo.dto.PollutionSubstationDTO;
import com.njcn.supervision.enums.FlowStatusEnum;
import com.njcn.supervision.enums.SupervisionKeyEnum;
import com.njcn.supervision.enums.SupervisionResponseEnum;
import com.njcn.supervision.mapper.survey.SurveyPlanMapper;
import com.njcn.supervision.pojo.param.survey.SurveyPlanParam;
import com.njcn.supervision.pojo.po.survey.SurveyPlan;
import com.njcn.supervision.pojo.po.survey.SurveyTest;
import com.njcn.supervision.pojo.vo.survey.SurveyPlanVO;
import com.njcn.supervision.pojo.vo.survey.SurveySubstation;
import com.njcn.supervision.service.survey.ISurveyPlanService;
import com.njcn.supervision.service.survey.ISurveyTestService;
import com.njcn.supervision.utils.InstanceUtil;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.system.pojo.po.DictData;
import com.njcn.user.api.DeptFeignClient;
import com.njcn.web.factory.PageFactory;
import com.njcn.web.utils.RequestUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * <p>
 * 普测计划流程表 服务实现类
 * </p>
 *
 * @author hongawen
 * @since 2024-05-30
 */
@Service
public class SurveyPlanServiceImpl extends ServiceImpl<SurveyPlanMapper, SurveyPlan> implements ISurveyPlanService {


    @Resource
    private BpmProcessFeignClient bpmProcessFeignClient;

    @Resource
    private DeptFeignClient deptFeignClient;

    @Resource
    private LineFeignClient lineFeignClient;

    @Resource
    private ISurveyTestService surveyTestService;

    @Resource
    private DicDataFeignClient dicDataFeignClient;


    @Override
    public Page<SurveyPlanVO> surveyPlanPage(SurveyPlanParam.SurveyPlanQueryParam surveyPlanQueryParam) {
        QueryWrapper<SurveyPlanVO> surveyPlanVOQueryWrapper = new QueryWrapper<>();
        if (Objects.nonNull(surveyPlanQueryParam)) {
            //添加上时间范围
            if (Objects.nonNull(surveyPlanQueryParam.getSearchBeginTime()) && Objects.nonNull(surveyPlanQueryParam.getSearchEndTime())) {
                surveyPlanVOQueryWrapper.and(x -> x.between("supervision_survey_plan.plan_start_time",
                        DateUtil.beginOfDay(DateUtil.parse(surveyPlanQueryParam.getSearchBeginTime())),
                        DateUtil.endOfDay(DateUtil.parse(surveyPlanQueryParam.getSearchEndTime()))).or().isNull("supervision_survey_plan.plan_start_time"));
            }
            //根据工程名称模糊搜索
            if (StrUtil.isNotBlank(surveyPlanQueryParam.getSearchValue())) {
                surveyPlanVOQueryWrapper.like("supervision_survey_plan.plan_name", surveyPlanQueryParam.getSearchValue());
            }
            //筛选普测负责单位
            if (StrUtil.isNotBlank(surveyPlanQueryParam.getDeptIndex())) {
                List<String> deptIds = deptFeignClient.getDepSonIdtByDeptId(surveyPlanQueryParam.getDeptIndex()).getData();
                surveyPlanVOQueryWrapper.in("supervision_survey_plan.dept_id", deptIds);
            }
            surveyPlanVOQueryWrapper
                    .and(CollUtil.isNotEmpty(InstanceUtil.filterTaskStatus()), w -> w.in("supervision_survey_plan.status", InstanceUtil.filterTaskStatus())
                            .or()
                            .eq("supervision_survey_plan.create_by", RequestUtil.getUserIndex())
                    );
            if (Objects.nonNull(surveyPlanQueryParam.getStatus())) {
                surveyPlanVOQueryWrapper.in("supervision_survey_plan.status", surveyPlanQueryParam.getStatus());
            }
            surveyPlanVOQueryWrapper.eq(StringUtils.isNotBlank(surveyPlanQueryParam.getSupvType()), "supervision_survey_plan.supv_type", surveyPlanQueryParam.getSupvType());
        }
        surveyPlanVOQueryWrapper.eq("supervision_survey_plan.state", DataStateEnum.ENABLE.getCode())
                .orderByDesc("supervision_survey_plan.Update_Time");
        Page<SurveyPlanVO> surveyPlanVOPage = this.baseMapper.surveyPlanPage(new Page<>(PageFactory.getPageNum(surveyPlanQueryParam), PageFactory.getPageSize(surveyPlanQueryParam)), surveyPlanVOQueryWrapper);
        List<SurveyPlanVO> records = surveyPlanVOPage.getRecords();
        if (CollectionUtil.isNotEmpty(records)) {
            for (SurveyPlanVO record : records) {
                //回显部门名称
                record.setDeptName(deptFeignClient.getDeptById(record.getDeptId()).getData().getName());
                //回显变电站名称
                if (record.getCustomSubstationFlag() == 0) {
                    //关联台账内的变电站名称
                    String subName = "";

                    String substation = record.getSubstation();
                    //保存草稿时未选择电站判断

                    if (StringUtils.isNotEmpty(substation)) {
                        String[] subIds = substation.split(StrPool.COMMA);

                        for (String subId : subIds) {
                            String name = lineFeignClient.getSubstationInfo(subId).getData().getName();
                            subName = subName.concat(StrPool.COMMA).concat(name);
                        }
                        subName = subName.substring(1);
                    }

                    record.setSubstation(subName);
                } else {
                    record.setSubstationName(record.getSubstation());
                }
            }
        }
        return surveyPlanVOPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addSurveyPlan(SurveyPlanParam surveyPlanParam) {
        //排除重复计划的策略暂时未知，待后期有人提出了，再去做，todo...
        SurveyPlan surveyPlan = new SurveyPlan();
        BeanUtils.copyProperties(surveyPlanParam, surveyPlan);
        //设置状态
        if (Objects.equals(surveyPlanParam.getSaveOrCheckflag(), "1")) {
            surveyPlan.setStatus(BpmTaskStatusEnum.WAIT.getStatus());

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

        }
        surveyPlan.setState(DataStateEnum.ENABLE.getCode());
        this.saveOrUpdate(surveyPlan);
        surveyPlan = this.baseMapper.selectById(surveyPlan.getId());

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

        return surveyPlan.getId();
    }

    @Override
    public String updateSurveyPlan(SurveyPlanParam.SurveyPlanUpdateParam surveyPlanUpdateParam) {
        SurveyPlan surveyPlan = this.baseMapper.selectById(surveyPlanUpdateParam.getId());
        //判断是否有权限操作
        InstanceUtil.judgeUserPower(RequestUtil.getUserIndex(), surveyPlan.getCreateBy());
        surveyPlanUpdateParam.setStatus(surveyPlan.getStatus());
        surveyPlanUpdateParam.setProcessInstanceId(surveyPlan.getProcessInstanceId());
        surveyPlanUpdateParam.setHistoryInstanceId(surveyPlan.getHistoryInstanceId());
        BeanUtils.copyProperties(surveyPlanUpdateParam, surveyPlan);
        surveyPlan.setState(DataStateEnum.ENABLE.getCode());
        surveyPlan.setStatus(BpmTaskStatusEnum.RUNNING.getStatus());
        //处理历史流程id列表
        String historyInstanceIds = InstanceUtil.dealHistoryId(surveyPlan.getProcessInstanceId(), surveyPlan.getHistoryInstanceId());
        // 发起 BPM 流程
        Map<String, Object> processInstanceVariables = new HashMap<>(16);
        BpmProcessInstanceCreateReqDTO bpmProcessInstanceCreateReqDTO = new BpmProcessInstanceCreateReqDTO();
        bpmProcessInstanceCreateReqDTO.setProcessDefinitionKey(SupervisionKeyEnum.SURVEY_PLAN.getKey());
        bpmProcessInstanceCreateReqDTO.setBusinessKey(surveyPlan.getId());
        bpmProcessInstanceCreateReqDTO.setStartUserSelectAssignees(new HashMap<>(16));
        bpmProcessInstanceCreateReqDTO.setVariables(processInstanceVariables);
        String processInstanceId = bpmProcessFeignClient.createProcessInstance(surveyPlan.getCreateBy(), bpmProcessInstanceCreateReqDTO).getData();
        // 将工作流的编号，更新到流程单中
        surveyPlan.setProcessInstanceId(processInstanceId);
        //保存历史流程id列表
        surveyPlan.setHistoryInstanceId(historyInstanceIds);
        this.baseMapper.updateById(surveyPlan);
        return surveyPlan.getId();
    }

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

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateProcessStatus(String businessKey, Integer status) {
        SurveyPlan surveyPlan = this.baseMapper.selectById(businessKey);
        surveyPlan.setStatus(status);
        this.updateById(surveyPlan);
        if (Objects.equals(status, FlowStatusEnum.APPROVE.getCode())) {
            //计划审核成功后，需要将计划拆成一个个待测试的
            if (surveyPlan.getCustomSubstationFlag() == 0) {
                String substation = surveyPlan.getSubstation();
                //保存草稿时未选择电站判断
                if (StringUtils.isNotEmpty(substation)) {
                    String[] subIds = substation.split(StrPool.COMMA);
                    for (String subId : subIds) {
                        SurveyTest surveyTest = new SurveyTest();
                        surveyTest.setPlanId(surveyPlan.getId());
                        surveyTest.setDeptId(surveyPlan.getDeptId());
                        surveyTest.setInitiateWarningFlag(0);
                        surveyTest.setSubstation(subId);
                        surveyTest.setCustomSubstationFlag(0);
                        surveyTest.setDealState(DealStateEnum.UNSOLVED.getCode());
                        surveyTest.setCreateBy("");
                        surveyTest.setStatus(FlowStatusEnum.NEW.getCode());
                        surveyTestService.save(surveyTest);
                    }
                }
            } else {
                SurveyTest surveyTest = new SurveyTest();
                surveyTest.setPlanId(surveyPlan.getId());
                surveyTest.setDeptId(surveyPlan.getDeptId());
                surveyTest.setSubstation(surveyPlan.getSubstation());
                surveyTest.setInitiateWarningFlag(0);
                surveyTest.setCustomSubstationFlag(1);
                surveyTest.setDealState(DealStateEnum.UNSOLVED.getCode());
                surveyTest.setStatus(FlowStatusEnum.NEW.getCode());
                surveyTest.setCreateBy("");
                surveyTestService.save(surveyTest);
            }
        }
    }

    @Override
    public BpmInstanceInfo getInstanceInfo(String businessId) {
        BpmInstanceInfo bpmInstanceInfo = new BpmInstanceInfo();
        SurveyPlanVO surveyPlanVO = this.getVOById(businessId);
        if (Objects.isNull(surveyPlanVO)) {
            return null;
        }
        bpmInstanceInfo.setHistoryInstanceId(surveyPlanVO.getHistoryInstanceId());
        DictData data = dicDataFeignClient.getDicDataById(surveyPlanVO.getSupvType()).getData();
        String name = "未知监督类型";
        if (Objects.nonNull(data)) {
            name = data.getName();
        }
        String sign = name.concat("->")
                .concat(surveyPlanVO.getSupvObjectName());
        bpmInstanceInfo.setInstanceSign(sign);
        return bpmInstanceInfo;
    }

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

    @Override
    public SurveyPlanVO getVOById(String id) {
        SurveyPlan surveyPlan = this.baseMapper.selectById(id);
        if (Objects.isNull(surveyPlan)) {
            throw new BusinessException(SupervisionResponseEnum.DATA_NOT_EXISTS);
        }
        SurveyPlanVO surveyPlanVO = new SurveyPlanVO();
        BeanUtils.copyProperties(surveyPlan, surveyPlanVO);
        surveyPlanVO.setDeptName(deptFeignClient.getDeptById(surveyPlanVO.getDeptId()).getData().getName());
        List<SurveySubstation> surveySubstationList = new ArrayList<>();
        if (surveyPlanVO.getCustomSubstationFlag() == 0) {
            //系统内变电站信息
            String substation = surveyPlanVO.getSubstation();
            //保存草稿时未选择电站判断
            if (StringUtils.isNotEmpty(substation)) {
                String[] subIds = substation.split(StrPool.COMMA);
                for (String subId : subIds) {
                    PollutionSubstationDTO data = lineFeignClient.getSubstationInfo(subId).getData();
                    if (ObjectUtil.isNotNull(data)) {
                        SurveySubstation surveySubstation = new SurveySubstation();
                        surveySubstation.setDataSource(0);
                        surveySubstation.setSubstationName(data.getName());
                        surveySubstation.setVoltageLevel(data.getVoltageLevel());
                        surveySubstationList.add(surveySubstation);
                    }
                }
            }
        } else {
            SurveySubstation surveySubstation = new SurveySubstation();
            surveySubstation.setDataSource(1);
            surveySubstation.setSubstationName(surveyPlanVO.getSubstation());
            surveySubstation.setVoltageLevel(StrPool.SLASH);
            surveySubstationList.add(surveySubstation);
        }
        surveyPlanVO.setSurveySubstationList(surveySubstationList);
        return surveyPlanVO;
    }

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