/*
*  Copyright 2019-2020 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package me.zhengjie.modules.dm.printingApproval.service.impl;

import me.zhengjie.base.BaseResult;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.dm.activiti.event.ActivitiEvent;
import me.zhengjie.modules.dm.activiti.status.OperationStatus;
import me.zhengjie.modules.dm.printingApproval.domain.DmPrintingApproval;
import me.zhengjie.modules.dm.printingQueue.domain.DmPrintingQueue;
import me.zhengjie.modules.dm.printingQueue.service.DmPrintingQueueService;
import me.zhengjie.modules.dm.printingRequest.domain.DmPrintingRequest;
import me.zhengjie.modules.dm.user.domain.DmUser;
import me.zhengjie.modules.dm.user.service.mapstruct.DmUserMapper;
import me.zhengjie.modules.dm.user.util.DmUserUtils;
import me.zhengjie.modules.system.service.UserService;
import me.zhengjie.modules.system.service.dto.UserDto;
import me.zhengjie.utils.*;
import lombok.RequiredArgsConstructor;
import me.zhengjie.modules.dm.printingApproval.repository.DmPrintingApprovalRepository;
import me.zhengjie.modules.dm.printingApproval.service.DmPrintingApprovalService;
import me.zhengjie.modules.dm.printingApproval.service.dto.DmPrintingApprovalDto;
import me.zhengjie.modules.dm.printingApproval.service.dto.DmPrintingApprovalQueryCriteria;
import me.zhengjie.modules.dm.printingApproval.service.mapstruct.DmPrintingApprovalMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.io.IOException;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

/**
* @website https://el-admin.vip
* @description 服务实现
* @author xwx
* @date 2021-03-17
**/
@Service
@RequiredArgsConstructor
public class DmPrintingApprovalServiceImpl implements DmPrintingApprovalService {

    private final DmPrintingApprovalRepository dmPrintingApprovalRepository;
    private final DmPrintingApprovalMapper dmPrintingApprovalMapper;


    /** 用户信息 */
    @Autowired
    private UserService userService;
    @Autowired
    private final DmUserMapper dmUserMapper;

    /** 文印队列 */
    @Autowired
    private DmPrintingQueueService printingQueueService;

    @Resource
    private ApplicationContext applicationContext;

    @Override
    public Map<String,Object> queryAll(DmPrintingApprovalQueryCriteria criteria, Pageable pageable){
        //只查询自己能审批的信息
        criteria.setApprovalUserCode(DmUserUtils.getCurrDmUser().getId());
        criteria.setRequestStatus("00");
        Page<DmPrintingApproval> page = dmPrintingApprovalRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(dmPrintingApprovalMapper::toDto));
    }

    @Override
    public List<DmPrintingApprovalDto> queryAll(DmPrintingApprovalQueryCriteria criteria){
        //只查询自己能审批的信息
        criteria.setApprovalUserCode(DmUserUtils.getCurrDmUser().getId());
        criteria.setRequestStatus("00");
        return dmPrintingApprovalMapper.toDto(dmPrintingApprovalRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    public DmPrintingApprovalDto findById(Long id) {
        DmPrintingApproval dmPrintingApproval = dmPrintingApprovalRepository.findById(id).orElseGet(DmPrintingApproval::new);
        ValidationUtil.isNull(dmPrintingApproval.getId(),"DmPrintingApproval","id",id);
        return dmPrintingApprovalMapper.toDto(dmPrintingApproval);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DmPrintingApprovalDto create(DmPrintingApproval resources) {
        Snowflake snowflake = IdUtil.createSnowflake(1, 1);
        resources.setId(snowflake.nextId());
        resources.setTaskCode(getCode());
        return dmPrintingApprovalMapper.toDto(dmPrintingApprovalRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(DmPrintingApproval resources) {
        DmPrintingApproval dmPrintingApproval = dmPrintingApprovalRepository.findById(resources.getId()).orElseGet(DmPrintingApproval::new);
        ValidationUtil.isNull( dmPrintingApproval.getId(),"DmPrintingApproval","id",resources.getId());
        dmPrintingApproval.copy(resources);
        dmPrintingApprovalRepository.save(dmPrintingApproval);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult approval(DmPrintingApproval resources) {
        BaseResult result = new BaseResult();
        DmPrintingApproval dmPrintingApproval = dmPrintingApprovalRepository.findById(resources.getId()).orElseGet(DmPrintingApproval::new);
        ValidationUtil.isNull( dmPrintingApproval.getId(),"DmPrintingApproval","id",resources.getId());
        dmPrintingApproval.copy(resources);

        //判断用户是否具备审批权限
        //1、判断是否具有审批用户
        UserDto user= userService.findById(SecurityUtils.getCurrentUserId());
        Boolean isApproval =true;
        isApproval = user.getDmUser()==null||dmPrintingApproval.getApprovalUser() == null ? false:user.getDmUser().getId().equals(dmPrintingApproval.getApprovalUser().getId())?true:false;
        if(!isApproval){
            throw new BadRequestException("无审批权限");
        }
        String status = dmPrintingApproval.getApprovalStatus();
        if(!"01".equals(status) && !"02".equals(status)){
            throw new BadRequestException("当前状态不可审批");
        }

        DmPrintingRequest request = dmPrintingApproval.getPrintingRequest();
        if(request == null || request.getId() == null ||  !"00".equals(request.getStatus())){
            throw new BadRequestException("当前状态不可审批");
        }
        DmUser dmUser = dmUserMapper.toEntity(user.getDmUser());

        String inistatus = request.getStatus();
        //修改文印申请信息
        request.setStatus(status);
        request.setApprovalUser(dmUser);
        //printingRequestService.update(request,inistatus);
        //保存审批信息
        dmPrintingApproval.setApprovalUser(dmUser);
        dmPrintingApprovalRepository.save(dmPrintingApproval);
        Timestamp timestamp=new Timestamp(System.currentTimeMillis());
        //审批通过
        if("01".equals(dmPrintingApproval.getApprovalStatus())){
            //推送打印
            DmPrintingQueue printingQueue = new DmPrintingQueue();
            printingQueue.setPrintingRequest(dmPrintingApproval.getPrintingRequest());
            printingQueue.setStatus("00");
            printingQueue.setStartTime(timestamp);
            printingQueueService.create(printingQueue);
        }
        //触发审批流程
        request.setTaskId(dmPrintingApproval.getTaskId());
        ActivitiEvent event = new ActivitiEvent(this,request,OperationStatus.PRINTING_APPROVE);
        applicationContext.publishEvent(event);
        return result;
    }


    @Override
    public void deleteAll(Long[] ids) {
        for (Long id : ids) {
            dmPrintingApprovalRepository.deleteById(id);
        }
    }

    @Override
    public  void  deleteByRequestId(Long requestId){
        dmPrintingApprovalRepository.deleteByRequestId(requestId);
    }

    @Override
    public void download(List<DmPrintingApprovalDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (DmPrintingApprovalDto dmPrintingApproval : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("文印申请主键", dmPrintingApproval.getPrintingRequest().getId());
            map.put("任务编号", dmPrintingApproval.getTaskCode());
            map.put("审批意见", dmPrintingApproval.getApprovalRemark());
            map.put("审批状态", dmPrintingApproval.getApprovalStatus());
            map.put("审批节点", dmPrintingApproval.getApprovalLeave());
            map.put("是否为叶子节点", dmPrintingApproval.getLastLeave());
            map.put("是否为最新审批", dmPrintingApproval.getIsNew());
            map.put("创建者", dmPrintingApproval.getCreateBy());
            map.put("更新者", dmPrintingApproval.getUpdatedBy());
            map.put("创建日期", dmPrintingApproval.getCreateTime());
            map.put("更新时间", dmPrintingApproval.getUpdateTime());
            map.put("审批人", dmPrintingApproval.getApprovalUser());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public void editApprovalUser(String approvalUser, Long requestId) {
        dmPrintingApprovalRepository.editApprovalUser(approvalUser,requestId);
    }

    @Override
    public void changeOld(Long requestId) {
        dmPrintingApprovalRepository.changeOld(requestId);
    }

    /** todo 重置审批信息
     * */
    @Override
    public void reset(Long requestId){ dmPrintingApprovalRepository.reset(requestId);}

    @Override
    public void resetTask(Long requestId, String approvalUser, String taskId, String procInstId) {
        dmPrintingApprovalRepository.resetTask(requestId,approvalUser,taskId,procInstId);
    };

    @Override
    public String getMaxCode() {
        return dmPrintingApprovalRepository.getMaxCode();
    }

    public String getCode(){
        String code = "";
        String maxCode = getMaxCode();
        if(maxCode == null || maxCode.isEmpty()){
            code="001";
        }else {
            int codeMax = Integer.parseInt(maxCode) +1;
            switch ((codeMax+"").length()){
                case 1:code = "00"+codeMax; break;
                case 2:code = "0"+codeMax; break;
                default:code = codeMax +"";
            }
        }
        return code;
    }
}
