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

import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject;
import me.zhengjie.domain.Log;
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.printingApproval.service.DmPrintingApprovalService;
import me.zhengjie.modules.dm.printingQueue.domain.DmPrintingQueue;
import me.zhengjie.modules.dm.printingQueue.repository.DmPrintingQueueRepository;
import me.zhengjie.modules.dm.printingQueue.service.DmPrintingQueueService;
import me.zhengjie.modules.dm.printingRequest.domain.DmPrintingRequest;
import me.zhengjie.modules.dm.printingRequest.service.dto.FindDmPrintingRequestParam;
import me.zhengjie.modules.dm.user.domain.DmUser;
import me.zhengjie.modules.dm.user.service.dto.DmUserDto;
import me.zhengjie.modules.dm.user.service.mapstruct.DmUserMapper;
import me.zhengjie.modules.dm.user.util.DmUserUtils;
import me.zhengjie.modules.system.domain.User;
import me.zhengjie.modules.system.repository.UserRepository;
import me.zhengjie.modules.system.service.UserService;
import me.zhengjie.modules.system.service.dto.UserDto;
import me.zhengjie.repository.LogRepository;
import me.zhengjie.service.LocalStorageService;
import me.zhengjie.utils.*;
import lombok.RequiredArgsConstructor;
import me.zhengjie.modules.dm.printingRequest.repository.DmPrintingRequestRepository;
import me.zhengjie.modules.dm.printingRequest.service.DmPrintingRequestService;
import me.zhengjie.modules.dm.printingRequest.service.dto.DmPrintingRequestDto;
import me.zhengjie.modules.dm.printingRequest.service.dto.DmPrintingRequestQueryCriteria;
import me.zhengjie.modules.dm.printingRequest.service.mapstruct.DmPrintingRequestMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.math.BigInteger;
import java.sql.Timestamp;
import java.util.*;
import java.io.IOException;
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.servlet.http.HttpServletResponse;

/**
* @website https://el-admin.vip
* @description 服务实现
* @author xwx
* @date 2021-03-15
**/
@Service
@RequiredArgsConstructor
public class DmPrintingRequestServiceImpl implements DmPrintingRequestService {
    @Value("${generateProc}")
    private String url;
    @Value("${messageUrl}")
    private String messageurl;
    @Value("${headerKey}")
    private String header_key;
    @Value("${key}")
    private String key;
    private final DmPrintingRequestRepository dmPrintingRequestRepository;
    private final DmPrintingRequestMapper dmPrintingRequestMapper;
    /** 打印审批信息 */
    private final DmPrintingApprovalService dmPrintingApprovalService;
    //文件信息
    private final LocalStorageService localStorageService;
    /** 用户信息 */
    private final UserService userService;
    private final DmUserMapper dmUserMapper;
    private final UserRepository userRepository;
    private final LogRepository logRepository;
    /** 文印队列 */
    private final DmPrintingQueueService printingQueueService;
    private final DmPrintingQueueRepository dmPrintingQueueRepository;

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

    @Override
    public List<DmPrintingRequestDto> queryAll(DmPrintingRequestQueryCriteria criteria){
        return dmPrintingRequestMapper.toDto(dmPrintingRequestRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    public DmPrintingRequestDto findById(Long id) {
        DmPrintingRequest dmPrintingRequest = dmPrintingRequestRepository.findById(id).orElseGet(DmPrintingRequest::new);
        ValidationUtil.isNull(dmPrintingRequest.getId(),"DmPrintingRequest","id",id);
        return dmPrintingRequestMapper.toDto(dmPrintingRequest);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DmPrintingRequestDto create(DmPrintingRequest resources) throws IOException {
        Snowflake snowflake = IdUtil.createSnowflake(1, 1);
        UserDto userDto= userService.findById(SecurityUtils.getCurrentUserId());

        String taskId = String.valueOf(snowflake.nextId());
        resources.setId(Long.valueOf(taskId));
        //resources.setTaskCode(getCode());
        resources.setRequestUser(dmUserMapper.toEntity(userDto.getDmUser()));//当前用户
        resources.setTaskId(taskId);
        resources.setTaskCode(taskId);

        DmPrintingRequestDto dmPrintingRequestDto = null;
        Timestamp timestamp=new Timestamp(System.currentTimeMillis());

        if("1".equals(resources.getDevice().getIsCommonPrinter())){     //1：公共打印机
            resources.setStatus("01");
            resources.setIsHasApproval(false);
            dmPrintingRequestDto = dmPrintingRequestMapper.toDto(dmPrintingRequestRepository.save(resources));
            //推送打印
            DmPrintingQueue printingQueue = new DmPrintingQueue();
            printingQueue.setPrintingRequest(resources);//.getId()
            printingQueue.setStatus("00");
            printingQueue.setStartTime(timestamp);
            printingQueueService.create(printingQueue);
        }else if ("0".equals(resources.getDevice().getIsCommonPrinter())){ //0：不是公共打印机
            resources.setStatus("00");
            resources.setIsHasApproval(true);
//            String url = "http://10.19.0.234:30170/api-third-party/busi/comm/collaboration/process/generateProc";
//            String taskId = UUID.randomUUID().toString();
            String generateProcData = "";
            try {
                JSONObject generateProcJson = new JSONObject();
                JSONObject formData = new JSONObject();
                formData.put("taskId",taskId);
                formData.put("taskName",resources.getTaskName());
                formData.put("page",resources.getFilePageNum());
                formData.put("number",resources.getFileRepeatNum());
                formData.put("printerNumber",resources.getDevice().getCode());
                formData.put("printerName",resources.getDevice().getName());
                formData.put("type","2");
                formData.put("taskType","2");
                generateProcJson.put("formData",formData);
                User user = userRepository.getUserByDmUserId(resources.getRequestUser().getId());
                JSONObject caihRuRequestInfo = new JSONObject();
                caihRuRequestInfo.put("compId", user.getUserRootGroupId());
                caihRuRequestInfo.put("compName", user.getUserRootGroupName());
                caihRuRequestInfo.put("orgId", user.getDept().getId());
                caihRuRequestInfo.put("orgName", user.getDept().getName());
                caihRuRequestInfo.put("userId",user.getId());
                caihRuRequestInfo.put("userName",user.getNickName());
                caihRuRequestInfo.put("mobile",user.getPhone());
                generateProcJson.put("caihRuRequestInfo",caihRuRequestInfo);
                generateProcJson.put("procDefKey","CUST_e8d0cec5-2042-4730-a9ae-81bf4c2dd3e6");//CUST_56bc329d-776c-4c48-96a5-99a853c861ea
                generateProcJson.put("procName","办公-文印申请");
                generateProcJson.put("tarTaskDefKey", "taskDefinitionKey2");
                generateProcJson.put("tenantId","caih");
                generateProcData = HttpRequest.get(url).body(generateProcJson.toJSONString()).execute().body();
                JSONObject generateProcDataJson = JSONObject.parseObject(generateProcData);
                System.out.println("generateProcDataJson:"+generateProcDataJson);
                String code = generateProcDataJson.getString("code");
                if(!StringUtils.equals(code,"0000")){
                    throw new BadRequestException("发起审批失败");
                }
            }catch (Exception ex){
                ex.printStackTrace();
                Log log = new Log();
                log.setDescription(ex.toString());
                log.setLogType("ERROR");
                log.setMethod(url);
                log.setParams(generateProcData);
                log.setUsername("东信ERP审核问题");
                logRepository.save(log);
            }
            dmPrintingRequestDto = dmPrintingRequestMapper.toDto(dmPrintingRequestRepository.save(resources));
        }

        //触发审批流程
//        ActivitiEvent event = new ActivitiEvent(this,resources,OperationStatus.PRINTING_SUBMIT);
//        applicationContext.publishEvent(event);
        return dmPrintingRequestDto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(DmPrintingRequest resources,String ... statusList) {
        DmPrintingRequest dmPrintingRequest = dmPrintingRequestRepository.findById(resources.getId()).orElseGet(DmPrintingRequest::new);
        ValidationUtil.isNull( dmPrintingRequest.getId(),"DmPrintingRequest","id",resources.getId());
        dmPrintingRequest.copy(resources);
//        Boolean isAPProvalUpdate = false;
//        String status = statusList!=null && statusList.length>0 ?statusList[0]:dmPrintingRequest.getStatus();
//        if("02".equals(status)){
//                isAPProvalUpdate = true;
//        }
        dmPrintingRequestRepository.save(dmPrintingRequest);
        //reset(dmPrintingRequest.getId());

        //触发审批流程
//        if(isAPProvalUpdate){
//            ActivitiEvent event = new ActivitiEvent(this,resources,OperationStatus.PRINTING_SUBMIT_APPROVAL_USER);
//            applicationContext.publishEvent(event);
//        }

    }

    /**
     * TODO 添加审批人
     * @param resources /
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addApprovalUser(DmPrintingRequest resources) {
        DmPrintingRequest dmPrintingRequest = dmPrintingRequestRepository.findById(resources.getId()).orElseGet(DmPrintingRequest::new);
        ValidationUtil.isNull( dmPrintingRequest.getId(),"DmPrintingRequest","id",resources.getId());
        dmPrintingRequest.setIsHasApproval(true);
        List<DmUser> appUsers = resources.getApprovalUserList();

        if(appUsers !=null && appUsers.size()>0){
            //修改当前申请人的所有审批信息为旧审批信息
//            dmPrintingApprovalService.changeOld(dmPrintingRequest.getId());
            for(DmUser dmUser : appUsers){
                DmPrintingApproval approval = new DmPrintingApproval();
                approval.setPrintingRequest(resources);
                approval.setApprovalUser(dmUser);
                approval.setApprovalStatus("00");
                approval.setIsNew(true);
                dmPrintingApprovalService.create(approval);
                //选择审核人时，给申请填写审核人，而不是审核页面返回
                dmPrintingRequest.setApprovalUser(dmUser);
            }
        }
        dmPrintingRequestRepository.save(dmPrintingRequest);

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

    /**
     * TODO 撤回
     * @param resources /
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void recallApprovalUser(DmPrintingRequest resources) {
        DmPrintingRequest dmPrintingRequest = dmPrintingRequestRepository.findById(resources.getId()).orElseGet(DmPrintingRequest::new);
        ValidationUtil.isNull( dmPrintingRequest.getId(),"DmPrintingRequest","id",resources.getId());
        dmPrintingRequest.setIsHasApproval(false);
        dmPrintingRequest.setApprovalUser(null);//审核人置空
        dmPrintingApprovalService.deleteByRequestId(resources.getId());

        dmPrintingRequestRepository.save(dmPrintingRequest);
        //触发审批流程
//        ActivitiEvent event = new ActivitiEvent(this,dmPrintingRequest,OperationStatus.PRINTING_SUBMIT);
//        applicationContext.publishEvent(event);
    }

    public void message(DmPrintingRequestDto dmPrintingRequest,String taskId,String sendContent){
//        String url = "https://smartpark.caih.com/zkxt/api/thirdparty/v1/message/sendChatMessage";
        String res = "";
        try {
            Map<String,Object> token = SecurityUtils.getToken(key);
            UserDto user = userService.findById(dmPrintingRequest.getRequestUser().getId());
            JSONObject query = new JSONObject();
            query.put("systemName","文印系统");
            query.put("sendId","dm_printing_request|task_id|"+taskId);
            query.put("sendUserId",dmPrintingRequest.getRequestUser().getId());
            JSONObject sendContentJSON = new JSONObject();
            sendContentJSON.put("text",sendContent);
            query.put("sendContent",sendContentJSON);
            query.put("usernames",user.getUsername());
            JSONObject param = new JSONObject();
            param.put("nonce",token.get("nonce"));
            param.put("timestamp",token.get("timestamp"));
            param.put("query",query);
            res = HttpRequest.get(messageurl).header(header_key, token.get("token").toString()).body(param.toJSONString()).execute().body();
            JSONObject jsonObject = JSONObject.parseObject(res);
            System.out.println("jsonObject"+jsonObject);
        }catch (Exception ex){
            ex.printStackTrace();
            Log log = new Log();
            log.setDescription(ex.toString());
            log.setLogType("ERROR");
            log.setMethod(url);
            log.setParams(res);
            log.setUsername("东信ERP消息通知问题");
            logRepository.save(log);
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String,Object> deleteAll(Long[] ids) {
        Long[] fileId = new Long[1];
        Map<String,Object> map= new HashMap<>();
        List name=dmPrintingQueueRepository.selectPrintingQueueName(ids);
        for (Long id : ids) {
            Integer count = dmPrintingQueueRepository.selecIsNotPrintingQueue(id);
            if(count<=0){
                DmPrintingRequest dmPrintingRequest = dmPrintingRequestRepository.findById(id).orElseGet(DmPrintingRequest::new);
                //删除上传文件
                fileId[0] = dmPrintingRequest.getFile().getId();
                localStorageService.deleteAll(fileId);
                dmPrintingRequestRepository.deleteById(id);
                //删除审批信息
                dmPrintingApprovalService.deleteByRequestId(id);
//                if(dmPrintingRequest.getId() !=null){
//                    //触发中止流程
//                    ActivitiEvent event = new ActivitiEvent(this,dmPrintingRequest,OperationStatus.PRINTING_PUZ_INST);
//                    applicationContext.publishEvent(event);
//                }
            }else {
                map.put("lose",name+"已进入文印队列,不能删除");
                map.put("type", "request");
            }
        }
        return map;
    }

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

    @Override
    public void updatePringTask(DmPrintingRequest resources) {
         dmPrintingRequestRepository.updatePringTask(resources);
    }

    @Override
    public void download(List<DmPrintingRequestDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (DmPrintingRequestDto dmPrintingRequest : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            String status = dmPrintingRequest.getStatus();
            //01已通过、00未审核、02已驳回
            if (status.equals("00")){
                status="未审核";
            }else if (status.equals("01")){
                status="已通过";
            }else if (status.equals("02")){
                status="已驳回";
            }
            map.put("任务编号", dmPrintingRequest.getTaskCode());
            map.put("任务名称", dmPrintingRequest.getTaskName());
            map.put("文档总页数", dmPrintingRequest.getFilePageNum());
            map.put("文档份数", dmPrintingRequest.getFileRepeatNum());
            map.put("打印机编号", dmPrintingRequest.getDevice().getCode());
            if (dmPrintingRequest.getApprovalUser()!=null&&dmPrintingRequest.getApprovalUser().getName()!=null){
                map.put("审批人", dmPrintingRequest.getApprovalUser().getName());
            }else {
                map.put("审批人", "");
            }
            if (dmPrintingRequest.getRequestUser()!=null&&dmPrintingRequest.getRequestUser().getName()!=null){
                map.put("发起人", dmPrintingRequest.getRequestUser().getName());
            }else {
                map.put("发起人", "");
            }
            map.put("创建者", dmPrintingRequest.getCreateBy());
            map.put("更新者", dmPrintingRequest.getUpdatedBy());
            map.put("创建日期", dmPrintingRequest.getCreateTime());
            map.put("更新时间", dmPrintingRequest.getUpdateTime());
            map.put("目前状态", status);//
            map.put("备注", dmPrintingRequest.getRemark());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public DmPrintingRequestDto findInfo(Long id){
        DmPrintingRequestDto dto = this.findById(id);
        return dto;
    };

    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;
    }

    public DmPrintingRequest toEntity(DmPrintingRequestDto dto) {
        if (dto == null) {
            return null;
        } else {
            DmPrintingRequest dmPrintingRequest = new DmPrintingRequest();
            dmPrintingRequest.setCreateBy(dto.getCreateBy());
            dmPrintingRequest.setUpdatedBy(dto.getUpdatedBy());
            dmPrintingRequest.setCreateTime(dto.getCreateTime());
            dmPrintingRequest.setUpdateTime(dto.getUpdateTime());
            dmPrintingRequest.setId(dto.getId());
            dmPrintingRequest.setTaskCode(dto.getTaskCode());
            dmPrintingRequest.setTaskName(dto.getTaskName());
            dmPrintingRequest.setFilePageNum(dto.getFilePageNum());
            dmPrintingRequest.setFileRepeatNum(dto.getFileRepeatNum());
            dmPrintingRequest.setStatus(dto.getStatus());
            dmPrintingRequest.setRemark(dto.getRemark());
            dmPrintingRequest.setTaskId(dto.getTaskId());
            dmPrintingRequest.setProcInstId(dto.getProcInstId());
            return dmPrintingRequest;
        }
    }

    @Override
    public Page<Map<String, Object>> findByRequestUser(String status, String printingRequest, String requestUser, Pageable pageable) {
        return dmPrintingRequestRepository.findByRequestUser(status, printingRequest, requestUser, pageable);
    }

    @PersistenceContext
    private EntityManager em;

    @Override
    public Map<String, Object> findMyWy(FindDmPrintingRequestParam findDmPrintingRequestParam, Pageable pageable) {
        Integer offset = (int)pageable.getOffset();
        Integer pageSize = pageable.getPageSize();
        //sql参数
        Map<String,Object> queryParams = new HashMap<>();
        //拼接sql
        StringBuffer querySql = new StringBuffer();//查询sql
        querySql.append(
                "select pr.id,pr.task_name as taskName,pr.file_page_num as filePageNum,pr.file_repeat_num as fileRepeatNum,d.`name` as deviceName,u.`name` as userName,pr.`status`,pr.approval_remark as approvalRemark,pr.remark,ls.real_name as realName "
        );
        String columns = "id,taskName,filePageNum,fileRepeatNum,deviceName,userName,status,approvalRemark,remark,realName";

        StringBuffer countSql = new StringBuffer();//计数sql
        countSql.append("select count(*) ");


        StringBuffer baseSql = new StringBuffer();//共同的sql
        baseSql.append(
                " from dm_printing_request as pr left join dm_device as d on pr.printer_code = d.id left join dm_user as u on pr.request_user = u.id left join tool_local_storage as ls on pr.fileid = ls.storage_id ");
        baseSql.append(" where pr.request_user = :requestUser");
        queryParams.put("requestUser",findDmPrintingRequestParam.getRequestUser());

        if(StringUtils.isNotBlank(findDmPrintingRequestParam.getFileName())){
            String blurry = "%"+findDmPrintingRequestParam.getFileName()+"%";
            baseSql.append(" and ls.real_name LIKE :blurry ");
            queryParams.put("blurry",blurry);
        }

        if(StringUtils.isNotBlank(findDmPrintingRequestParam.getStatus())){
            baseSql.append(" and pr.`status`= :status ");
            queryParams.put("status",findDmPrintingRequestParam.getStatus());
        }

        //排序
        baseSql.append(" order by pr.create_time desc ");

        querySql.append(baseSql);
        countSql.append(baseSql);
        Query query = em.createNativeQuery(querySql.toString());
        Query countQuery = em.createNativeQuery(countSql.toString());

        for (Map.Entry<String,Object> entry : queryParams.entrySet()) {
            query.setParameter(entry.getKey(),entry.getValue());
            countQuery.setParameter(entry.getKey(),entry.getValue());
        }
        BigInteger total = (BigInteger) countQuery.getSingleResult();
        //设置分页
        if(offset != null && pageSize != null){
            query.setFirstResult(offset);
            query.setMaxResults(pageSize);
        }
        List<Object[]> list = query.getResultList();
        List<Map<String,String>> result = DmUserUtils.queryResultToMap(list,columns);

        Map<String,Object> map = new HashMap<>();
        map.put("total",total);
        map.put("list",result);
        return map;
    }

    @Override
    public Long findRequestCount() {
        return dmPrintingRequestRepository.findRequestCount();
    }

    @Override
    public List<Map<String,Object>> findRequestInfo() {
        return dmPrintingRequestRepository.findRequestInfo();
    }

    public void reset (Long id){
        //修改审批状态为待审批
        dmPrintingApprovalService.reset(id);
        //修改文印申请为待审批状态
        dmPrintingRequestRepository.reset(id);
    }

    @Override
    public List<Map<String,Object>> requestListByDeviceId(Long deviceId){
        return dmPrintingRequestRepository.requestListByDeviceId(deviceId);
    }
}
