/*
*  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.information.service.impl;

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.information.domain.DmInformation;
import me.zhengjie.modules.dm.informationApproval.domain.DmInformationApproval;
import me.zhengjie.modules.dm.informationApproval.service.DmInformationApprovalService;
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.information.repository.DmInformationRepository;
import me.zhengjie.modules.dm.information.service.DmInformationService;
import me.zhengjie.modules.dm.information.service.dto.DmInformationDto;
import me.zhengjie.modules.dm.information.service.dto.DmInformationQueryCriteria;
import me.zhengjie.modules.dm.information.service.mapstruct.DmInformationMapper;
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.awt.*;
import java.sql.Timestamp;
import java.util.*;
import java.io.IOException;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

/**
* @website https://el-admin.vip
* @description 服务实现
* @author xwx
* @date 2021-04-22
**/
@Service
@RequiredArgsConstructor
public class DmInformationServiceImpl implements DmInformationService {

    private final DmInformationRepository dmInformationRepository;
    private final DmInformationMapper dmInformationMapper;
    @Autowired
    private DmInformationApprovalService approvalService;
    @Resource
    private ApplicationContext applicationContext;

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

    @Override
    public Map<String,Object> queryAll(DmInformationQueryCriteria criteria, Pageable pageable){
        Page<DmInformation> page = dmInformationRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(dmInformationMapper::toDto));
    }

    @Override
    public List<DmInformationDto> queryAll(DmInformationQueryCriteria criteria){
        return dmInformationMapper.toDto(dmInformationRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    public DmInformationDto findById(Long id) {
        DmInformation dmInformation = dmInformationRepository.findById(id).orElseGet(DmInformation::new);
        ValidationUtil.isNull(dmInformation.getId(),"DmInformation","id",id);
        return dmInformationMapper.toDto(dmInformation);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DmInformationDto create(DmInformation resources) {
        Snowflake snowflake = IdUtil.createSnowflake(1, 1);
        resources.setId(snowflake.nextId());
        resources.setRequestUser(dmUserMapper.toEntity(DmUserUtils.getCurrDmUser()));
        resources.setStatus("00");
        resources.setIsHasApproval(false);
        DmInformationDto dto = dmInformationMapper.toDto(dmInformationRepository.save(resources));
        dto.setRequestUser(DmUserUtils.getCurrDmUser());
        ActivitiEvent event = new ActivitiEvent(this,resources,OperationStatus.SUBMIT);
        applicationContext.publishEvent(event);
        return dto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(DmInformation resources,String ... statusList) {
        DmInformation dmInformation = dmInformationRepository.findById(resources.getId()).orElseGet(DmInformation::new);
        ValidationUtil.isNull( dmInformation.getId(),"DmInformation","id",resources.getId());
        dmInformation.copy(resources);
         String status = statusList.length>0?statusList[0]:dmInformation.getStatus();
         //判断是否驳回后修改
         Boolean isApprovalUpdate = "02".equals(status);
        //触发审批流程
        if(isApprovalUpdate){
            //初始化所有信息
            reset(dmInformation.getId());
            ActivitiEvent event = new ActivitiEvent(this,resources,OperationStatus.SUBMIT_APPROVAL_USER);
            applicationContext.publishEvent(event);
        }
        if("02".equals(status) || "03".equals(status)){
            dmInformation.setStatus("00");//将状态改为待审批
            dmInformationRepository.save(dmInformation);
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addApprovalUser(DmInformation resources){
        DmInformation dmInformation = dmInformationRepository.findById(resources.getId()).orElseGet(DmInformation::new);
        ValidationUtil.isNull( dmInformation.getId(),"DmInformation","id",resources.getId());

        dmInformation.setIsHasApproval(true);
        List<DmUser> appUsers = resources.getApprovalUserList();

        if(appUsers !=null && appUsers.size()>0){
            for(DmUser dmUser : appUsers){
                DmInformationApproval approval = new DmInformationApproval();
                approval.setInformation(resources);
                approval.setApprovalUser(dmUser);
                approval.setStatus("00");
                approval.setIsNew(true);
                approvalService.create(approval);
            }
        }
        dmInformationRepository.save(dmInformation);

        //触发审批流程
        ActivitiEvent event = new ActivitiEvent(this,dmInformation,OperationStatus.SUBMIT_APPROVAL_USER);
        applicationContext.publishEvent(event);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approval(DmInformation resources) {
        DmInformation information = dmInformationRepository.findById(resources.getId()).orElseGet(DmInformation::new);
        ValidationUtil.isNull( information.getId(),"DmInformation","id",resources.getId());
        information.copy(resources);

        //判断用户是否具备审批权限
        //1、判断是否具有审批用户
        UserDto user= userService.findById(SecurityUtils.getCurrentUserId());
        Boolean isApproval =true;
        List<DmInformationApproval> approvalList = approvalService.findInfoByReqAndUser(information.getId(),user.getDmUser().getId()+"");
        DmInformationApproval approval = approvalList==null || approvalList.size()<=0 || approvalList.get(0).getId() == null?null:approvalList.get(0);
        isApproval=!(approval==null);
        if(!isApproval){
            throw new BadRequestException("无审批权限");
        }
        String status = information.getStatus();
        if(!"01".equals(status) && !"02".equals(status)){
            throw new BadRequestException("审批状态错误");
        }

        DmInformation information1 = approval.getInformation();
        System.out.println("information1.getStatus() ==> "+information1.getStatus());
        if(information1 == null || information1.getId() == null ||  !"00".equals(approval.getStatus())){
            throw new BadRequestException("当前状态不可审批");
        }
        DmUser dmUser = dmUserMapper.toEntity(user.getDmUser());
        String inistatus = approval.getStatus();

        //修改信息
        information.setApprovalUser(dmUser);
        information.setApprovalTime(new Timestamp(System.currentTimeMillis()));
        this.update(information,inistatus);
        //保存审批信息
        approval.setApprovalUser(dmUser);
        approval.setStatus(information.getStatus());
        approval.setApprovalRemark(information.getApprovalRemark());
        approvalService.update(approval);

        //触发审批流程
        information.setTaskId(approval.getTaskId());
        ActivitiEvent event = new ActivitiEvent(this,information,OperationStatus.APPROVE);
        applicationContext.publishEvent(event);
    }


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

    @Override
    public void download(List<DmInformationDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (DmInformationDto dmInformation : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("发布内容(需发布的信息内容)", dmInformation.getContent());
            map.put("(00-待审核  01-审批通过(已发布） 02-审核未通过)", dmInformation.getStatus());
            map.put("审批人", dmInformation.getApprovalUser());
            map.put("任务ID act_ru_task", dmInformation.getTaskId());
            map.put("任务实例id act_ru_execution", dmInformation.getProcInstId());
            map.put("发起人", dmInformation.getRequestUser());
            map.put("创建者", dmInformation.getCreateBy());
            map.put("更新者", dmInformation.getUpdateBy());
            map.put("创建日期", dmInformation.getCreateTime());
            map.put("更新时间", dmInformation.getUpdateTime());
            map.put("发布时间", dmInformation.getReleaseTime());
            map.put("审批时间", dmInformation.getApprovalTime());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public void ch(Long id){
        DmInformation information = dmInformationRepository.findById(id).orElseGet(DmInformation::new);
        ValidationUtil.isNull( information.getId(),"DmInformation","id",id);
        if("00".equals(information.getStatus())){
            information.setStatus("03");
            this.update(information,"00");
        }else {
            throw new BadRequestException("当前状态不可撤回");
        }
    }

    @Override
    public Map<String, Object> findAllDSP(Pageable pageable) {
        Page<DmInformation> page = dmInformationRepository.findAllDSP(DmUserUtils.getCurrDmUser().getId()+"",pageable);
        return PageUtil.toPage(page.map(dmInformationMapper::toDto));
    }

    @Override
    public DmInformation toEntity(DmInformationDto dto) {
        if ( dto == null ) {
            return null;
        }

        DmInformation dmInformation = new DmInformation();

        dmInformation.setCreateBy( dto.getCreateBy() );
        dmInformation.setCreateTime( dto.getCreateTime() );
        dmInformation.setUpdateTime( dto.getUpdateTime() );
        dmInformation.setId( dto.getId() );
        dmInformation.setContent( dto.getContent() );
        dmInformation.setStatus( dto.getStatus() );
        dmInformation.setTaskId( dto.getTaskId() );
        dmInformation.setProcInstId( dto.getProcInstId() );
        dmInformation.setReleaseTime( dto.getReleaseTime() );
        dmInformation.setApprovalTime( dto.getApprovalTime() );

        return dmInformation;
    }

    @Override
    public void updateTask(DmInformation resources) {
        dmInformationRepository.updateTask(resources);
    }


    public void reset (Long id){
        //修改审批状态为待审批
        approvalService.reset(id);
        //修改申请为待审批状态
        dmInformationRepository.reset(id);
    }
}