package com.njcn.process.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.process.enums.ProcessResponseEnum;
import com.njcn.process.mapper.FlowFormAssMapper;
import com.njcn.process.mapper.FlowableAssMapper;
import com.njcn.process.mapper.RFlowProcessPOMapper;
import com.njcn.process.pojo.param.RFlowProcessParm;
import com.njcn.process.pojo.param.RFlowProcessQueryParm;
import com.njcn.process.pojo.po.FlowFormAss;
import com.njcn.process.pojo.po.FlowableAss;
import com.njcn.process.pojo.po.RFlowProcessPO;
import com.njcn.process.pojo.vo.applyform.RFlowProcessVO;
import com.njcn.process.pojo.vo.flowable.FlowTaskVo;
import com.njcn.process.service.RFlowProcessPOService;
import com.njcn.process.service.flowable.IFlowDefinitionService;
import com.njcn.process.service.flowable.IFlowInstanceService;
import com.njcn.process.service.flowable.IFlowTaskService;
import com.njcn.process.utils.FlowableUtils;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.user.api.DeptFeignClient;
import com.njcn.user.pojo.vo.PvTerminalTreeVO;
import com.njcn.web.utils.RequestUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.flowable.task.api.Task;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 
 * Description:
 * Date: 2024/4/15  16:24【需求编号】
 *
 * @author clam
 * @version V1.0.0
 */
@Service
@RequiredArgsConstructor
public class RFlowProcessPOServiceImpl extends ServiceImpl<RFlowProcessPOMapper, RFlowProcessPO> implements RFlowProcessPOService{

    private final FlowableAssMapper flowableAssMapper;

    private final FlowFormAssMapper flowFormAssMapper;

    private final DicDataFeignClient dicDataFeignClient;
    private final DeptFeignClient deptFeignClient;


    private final IFlowDefinitionService iFlowDefinitionService;

    private final IFlowInstanceService iFlowInstanceService;

    private final IFlowTaskService iFlowTaskService;

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public Boolean add(RFlowProcessParm rFlowProcessParm) {

        RFlowProcessPO rFlowProcessPO = new RFlowProcessPO();
        BeanUtils.copyProperties(rFlowProcessParm,rFlowProcessPO);
        rFlowProcessPO.setProcessStatus(1);
        this.save(rFlowProcessPO);
        String businessId = rFlowProcessPO.getId();
        //生成新建工作流
        createflow(businessId, rFlowProcessParm.getApplyType(), rFlowProcessParm.getType());
        //生成提交审核工作流
//        if(Objects.equals(rFlowProcessParm.getOperate(),"2")){
//            createCheckflow(businessId);
//            //修改状态
//
//        }

        return true;
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public Boolean update(RFlowProcessParm.RFlowProcessUpdate rFlowProcessParm) {
        RFlowProcessPO byId = this.getById(rFlowProcessParm.getId());
        if(byId.getProcessStatus()==1||byId.getProcessStatus()==3){
            BeanUtils.copyProperties(rFlowProcessParm,byId);
            this.updateById(byId);

        }else {
            throw new BusinessException(ProcessResponseEnum.NO_UPDATE);

        }
        return null;
    }
    //审核
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public Boolean check(RFlowProcessParm.RFlowProcessCheck rFlowProcessCheck) {
        boolean result = true;
        UpdateWrapper<RFlowProcessPO> updateWrapper = new UpdateWrapper();
        updateWrapper.eq("id", rFlowProcessCheck.getId());
        updateWrapper.set("description", rFlowProcessCheck.getDescription());
        updateWrapper.set("check_status", rFlowProcessCheck.getCheckStatus());
        updateWrapper.set("process_status",rFlowProcessCheck.getCheckStatus()==1?3:4);
        result = this.update(updateWrapper);
        //流程审核
        FlowableAss flowableAss = flowableAssMapper.selectOne(new LambdaQueryWrapper<FlowableAss>().eq(FlowableAss::getThsIndex,rFlowProcessCheck.getId()));
        if(Objects.isNull(flowableAss)){
            throw new BusinessException("当前功能未绑定流程,请联系管理员处理");
        }
        FlowableUtils.dealAuditResult(flowableAss,rFlowProcessCheck.getCheckStatus()+"",iFlowTaskService,rFlowProcessCheck.getDescription());
        return result;
    }

    @Override
    public Boolean file(String id) {
        boolean result = true;
        UpdateWrapper<RFlowProcessPO> updateWrapper = new UpdateWrapper();
        updateWrapper.eq("id", id);
        updateWrapper.set("process_status",5);
        result = this.update(updateWrapper);
        //流程审核
        FlowableAss flowableAss = flowableAssMapper.selectOne(new LambdaQueryWrapper<FlowableAss>().eq(FlowableAss::getThsIndex,id));
        if(Objects.isNull(flowableAss)){
            throw new BusinessException("当前功能未绑定流程,请联系管理员处理");
        }
        Task task = iFlowTaskService.getTask(flowableAss.getExecIndex());
        FlowTaskVo flowTaskVo = new FlowTaskVo();
        flowTaskVo.setTaskId(task.getId());
        flowTaskVo.setComment(RequestUtil.getUserNickname() + "进行归档" );

        flowTaskVo.setInstanceId(flowableAss.getExecIndex());
        iFlowTaskService.complete(flowTaskVo);

        return result;
    }

    @Override
    public Page<RFlowProcessVO> getFlowProcess(RFlowProcessQueryParm rFlowProcessQueryParm) {
        Page<RFlowProcessVO> page = new Page<> (rFlowProcessQueryParm.getPageNum(), rFlowProcessQueryParm.getPageSize());
        IPage<RFlowProcessPO> tempPage = new Page<> (rFlowProcessQueryParm.getPageNum(), rFlowProcessQueryParm.getPageSize());

        String loginUsrId = RequestUtil.getUserIndex();
        //部门处理：根据部门code取名称
        List<PvTerminalTreeVO> dept = deptFeignClient.allDeptList().getData();
        Map<String, String> pvTerminalTreeVOMap = dept.stream().collect(Collectors.toMap(PvTerminalTreeVO::getId, PvTerminalTreeVO::getName));
        QueryWrapper<RFlowProcessPO> queryWrapper = new QueryWrapper<> ();
        /*type=1：新建页面：查看自己负责的计划；type=2：审核页面：审核者==当前用户；结果页面：查看自己负责的计划*/
        if (Objects.equals(rFlowProcessQueryParm.getPageType(),"1")   ) {
            queryWrapper.lambda().eq(RFlowProcessPO::getCreateBy, loginUsrId);
            queryWrapper.lambda().in(RFlowProcessPO::getProcessStatus, Stream.of(1,3,4,5).collect(Collectors.toList()));
        }
        if (Objects.equals(rFlowProcessQueryParm.getPageType(),"2")) {
            queryWrapper.lambda().eq(RFlowProcessPO::getChecker, loginUsrId);
            queryWrapper.lambda().in(RFlowProcessPO::getProcessStatus, Stream.of(2).collect(Collectors.toList()));
        }
        queryWrapper.lambda().eq(RFlowProcessPO::getApplyType,rFlowProcessQueryParm.getApplyType())
                .between(StringUtils.isNotBlank(rFlowProcessQueryParm.getStartTime()) &&
                StringUtils.isNotBlank(rFlowProcessQueryParm.getEndTime()) ,
                RFlowProcessPO::getCreateTime,rFlowProcessQueryParm.getStartTime()+" 00:00:00",rFlowProcessQueryParm.getEndTime()+" 23:59:59");

        IPage<RFlowProcessPO> rGeneralSurveyPlanDetailIPage = this.getBaseMapper().selectPage (tempPage, queryWrapper);
        List<RFlowProcessVO> collect = rGeneralSurveyPlanDetailIPage.getRecords().stream().map(temp->{
            RFlowProcessVO rFlowProcessVO = new RFlowProcessVO();
            BeanUtils.copyProperties(temp,rFlowProcessVO);

            Object bean = JSONUtil.toBean(temp.getApplicationFormText(), Object.class);
            rFlowProcessVO.setApplyForm(bean);
            rFlowProcessVO.setOrgName(pvTerminalTreeVOMap.get(temp.getOrgNo())); //单位名称
            return rFlowProcessVO;
        }).collect(Collectors.toList());
        page.setRecords(collect);
        page.setTotal(page.getTotal());
        return page;
    }

    //新建流程
    public Boolean createflow(String businessId ,Integer applyType,Integer type ) {
        String userId = RequestUtil.getUserIndex();


        //绑定工作流
        Map<String, Object> map = new HashMap<>();

        //开始流程
        FlowFormAss flowFormAss = flowFormAssMapper.selectOne(new LambdaQueryWrapper<FlowFormAss>().eq(FlowFormAss::getFormId, applyType));
        if (Objects.isNull(flowFormAss)) {
            throw new BusinessException("当前功能未绑定流程,请先绑定流程");
        }
        //如何applyType==3 电能质量管理下有3个子流程
        map.put("type",type);
        String processId = iFlowDefinitionService.startProcessInstanceById(flowFormAss.getDefinitionId(), businessId, applyType, map);
        Task task = iFlowTaskService.getTask(processId);
        FlowTaskVo flowTaskVo = new FlowTaskVo();
        flowTaskVo.setTaskId(task.getId());
        flowTaskVo.setInstanceId(processId);
        flowTaskVo.setComment(RequestUtil.getUserNickname() + "发起电能质量申请");
        flowTaskVo.setVariables(map);
        iFlowTaskService.complete(flowTaskVo);





        return true;
    }

    //提交审核工作流
    @Override
    public Boolean createCheckflow(String businessId ) {
        //流程审核
        FlowableAss flowableAss = flowableAssMapper.selectOne(new LambdaQueryWrapper<FlowableAss>().eq(FlowableAss::getThsIndex,businessId));
        if(Objects.isNull(flowableAss)){
            throw new BusinessException("当前功能未绑定流程,请联系管理员处理");
        }
        RFlowProcessPO byId = this.getById(businessId);
        Task taskNext = iFlowTaskService.getTask(flowableAss.getExecIndex());
        FlowTaskVo flowTaskVoNext = new FlowTaskVo();
        flowTaskVoNext.setTaskId(taskNext.getId());
        flowTaskVoNext.setAssignee(byId.getChecker());
        iFlowTaskService.toNextTaskUser(flowTaskVoNext);
        byId.setProcessStatus(2);
        this.updateById(byId);
        return true;
    }

}
