package com.huigou.topsun.sap.permit.application.impl;

import cn.hutool.core.bean.BeanUtil;

import com.huigou.cache.DictUtil;
import com.huigou.context.Operator;
import com.huigou.context.OrgUnit;
import com.huigou.context.ThreadLocalUtil;
import com.huigou.data.query.model.QueryDescriptor;
import com.huigou.data.query.model.QueryModel;
import com.huigou.topsun.common.CommonUtils;
import com.huigou.topsun.sap.permit.application.SapPermitApplication;
import com.huigou.topsun.sap.permit.application.SapPermitItemApplication;
import com.huigou.topsun.sap.permit.domain.SapPermit;
import com.huigou.topsun.sap.permit.domain.SapPermitItem;
import com.huigou.topsun.sap.permit.domain.query.SapPermitQueryRequest;
import com.huigou.topsun.sap.permit.repository.SapPermitItemRepository;
import com.huigou.topsun.sap.permit.repository.SapPermitRepository;
import com.huigou.topsun.sap.permit.vo.SapPermitItemVo;
import com.huigou.topsun.sap.permit.vo.SapPermitVo;
import com.huigou.uasp.bmp.common.BizBillStatus;
import com.huigou.uasp.bmp.operator.OperatorApplication;
import com.huigou.uasp.bpm.FlowBroker;
import com.huigou.uasp.bpm.ProcessAction;
import com.huigou.uasp.bpm.ProcessStartModel;
import com.huigou.uasp.bpm.engine.application.WorkflowApplication;
import com.huigou.util.*;


import freemarker.template.Template;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.runtime.ProcessInstance;

import org.krysalis.barcode4j.HumanReadablePlacement;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import javax.servlet.http.HttpServletResponse;

import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Auther: Lxh
 * @Date: 2024/03/26/11:35
 * @Description:
 */
@Service("sapPermitApplication")
public class SapPermitApplicationImpl extends FlowBroker implements SapPermitApplication {
    @Autowired
    private SapPermitRepository sapPermitRepository;
    @Autowired
    private SapPermitItemRepository sapPermitItemRepository;
    @Autowired
    private SapPermitItemApplication sapPermitItemApplication;
    @Autowired
    private WorkflowApplication workflowApplication;
    @Autowired
    private OperatorApplication operatorApplication;
    @Autowired
    private  FreeMarkerConfigurer freemarkerConfigurer;

    @Override
    public Map<String, Object> getPermitList(SapPermitQueryRequest queryRequest) {
        QueryDescriptor queryDescriptor = this.sqlExecutorDao.getQuery(QUERY_XML_FILE_PATH, "sapPermit");
        QueryModel queryModel = this.sqlExecutorDao.getQueryModel(queryDescriptor, queryRequest);
        if (queryRequest.getStatus() != null) {
            queryModel.addCriteria(" and t.status =:status");
            queryModel.putParam("status", queryRequest.getStatus());
        }
        if (queryRequest.getBillCode() != null) {
            queryModel.addCriteria(" and t.bill_code =:billCode");
            queryModel.putParam("billCode", queryRequest.getBillCode());
        }
        if (queryRequest.getBelongPerson() != null) {
            queryModel.addCriteria(" and t.belong_person like:person");
            queryModel.putLikeParam("person", queryRequest.getBelongPerson());
        }
        if (queryRequest.getDutyDepartName() != null) {
            queryModel.addCriteria(" and t.duty_depart_name like:deptName");
            queryModel.putLikeParam("deptName", queryRequest.getDutyDepartName());
        }
        if (queryRequest.getApplyPersonName() != null) {
            queryModel.addCriteria(" and t.apply_person_name like:personName");
            queryModel.putLikeParam("personName", queryRequest.getApplyPersonName());
        }
        if (queryRequest.getStartDate() != null&&!"".equals(queryRequest.getStartDate())) {
            queryModel.addCriteria(" and t.permit_date >=:startDate");
            queryModel.putParam("startDate", queryRequest.getStartDate());
        }
        if (queryRequest.getEndDate() != null&&!"".equals(queryRequest.getEndDate())) {
            queryModel.addCriteria(" and t.permit_date <=:endDate");
            queryModel.putParam("endDate", queryRequest.getEndDate());

        }

        queryModel.putDictionary("status", DictUtil.getDictionary("bizBillStatus"));
        queryModel.addCriteria(" order by bill_code desc ");
        Map<String, Object> map = this.sqlExecutorDao.executeSlicedQuery(queryModel);
        return map;
    }

    @Override
    public SapPermit getPermitById(String id) {
        return sapPermitRepository.findOne(id);
    }

    @Override
    public void deleteByIds(List<String> ids) {
        ids.forEach(id->{
             sapPermitRepository.delete(id);
            List<SapPermitItem> list=sapPermitItemRepository.findBySapPermitId(id);
            for (SapPermitItem sapPermitItem:list){
                sapPermitItemRepository.delete(sapPermitItem);
            }
        });
    }

    @Override
    protected void onBeforeComplete(DelegateTask delegateTask) {
        super.onBeforeComplete(delegateTask);
        String bizId = delegateTask.getExecution().getProcessBusinessKey();
        if (this.isApplyProcUnit(delegateTask) && this.getApprovalParameter().isAdvanceProcessAction()) {
            SapPermit sapPermit = sapPermitRepository.findOne(bizId);
            sapPermit.setStatusId(BizBillStatus.APPROVING.getId());
            sapPermitRepository.save(sapPermit);
        }
    }

    @Override
    protected void onEnd(DelegateExecution delegateExecution) {
        super.onEnd(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        BizBillStatus status = approvePassed() ? BizBillStatus.COMPLETED : BizBillStatus.ABORTED;
        SapPermit Permit = sapPermitRepository.findOne(bizId);
        Permit.setStatusId(status.getId());
        sapPermitRepository.save(Permit);
    }

    @Override
    protected void onAbortProcessInstance(DelegateExecution delegateExecution) {
        super.onAbortProcessInstance(delegateExecution);
        String bizId = delegateExecution.getProcessBusinessKey();
        SapPermit Permit = sapPermitRepository.findOne(bizId);
        Permit.setStatusId(BizBillStatus.ABORTED.getId());
        sapPermitRepository.save(Permit);
    }

    @Override
    protected void onBack(DelegateTask delegateTask, String destActivityId) {
        super.onBack(delegateTask, destActivityId);
        if ("Apply".equalsIgnoreCase(destActivityId)) {
            String bizId = delegateTask.getExecution().getProcessBusinessKey();
            SapPermit Permit = sapPermitRepository.findOne(bizId);
            Permit.setStatusId(BizBillStatus.APPLYING.getId());
            sapPermitRepository.save(Permit);
        }
    }

    @Override
    protected Map<String, Object> getProcessBizParams(String bizId) {
        return ClassHelper.toMap(sapPermitRepository.getOne(bizId));
    }

    @Override
    protected String saveBizAndApprovalData() {
        super.saveBizAndApprovalData();
        SapPermit permit = getBizEntity(SapPermit.class);
        if (permit.isNew()) {
            permit.setStatusId(BizBillStatus.APPLYING.getId());
        } else {
            permit = (SapPermit) commonDomainService.loadAndFillinProperties(permit);
        }
        permit = sapPermitRepository.save(permit);
        List<SapPermitItem> items = getBizEntities(SapPermitItem.class, "items");
        if (items.size()<1){
           throw new IllegalArgumentException("没有填写携带物品信息!");
        }
        sapPermitItemApplication.saveSapPermitItems(permit.getId(),items);
        //更新附件ID为主键ID
//        if (!(Permit.getId().equals(Permit.getAttbizId()))) {
//            List<Attachment> attachmentList = attachmentApplication.queryAttachments("sapRetirementInfo", Permit.getAttbizId());
//            for (Attachment attachment : attachmentList) {
//                attachment.setBizId(Permit.getId());
//                attachmentApplication.saveAttachment(attachment);
//            }
//        }
        return permit.getId();
    }

    /**
     * 设置任务名称
     */
    @Override
    protected void setTaskDescription(DelegateTask delegateTask) {
        String bizId = delegateTask.getExecution().getProcessBusinessKey();
        delegateTask.setDescription(this.getApprovalSubjectName(bizId));
    }

    /**
     * 获取任务标题
     *
     * @param bizId
     * @return
     */
    private String getApprovalSubjectName(String bizId) {
        SapPermit sapPermit = this.sapPermitRepository.findOne(bizId);
        //查询 单据日期
        String fillinDateStr = DateUtil.getDateFormat("yyyy-MM-dd HH:mm:ss", sapPermit.getFillinDate());
        //设置标题
        return String.format("%s-%s(%s)", "放行条", sapPermit.getBillCode(), fillinDateStr);
    }

    @Override
    public void saveSapPermitVo(SapPermitVo sapPermitVo){
        SapPermit sapPermit = new SapPermit();
        BeanUtil.copyProperties(sapPermitVo,sapPermit);
        //初始化用户信息
        Operator operator = operatorApplication.createOperatorByPersonMemberId(sapPermitVo.getApplyPerson());
        sapPermit.setDefaultValues(new OrgUnit(operator.getFullId(), operator.getFullName()));

        Map<String, Object> formData = BeanUtil.beanToMap(sapPermit);
        //保存明细
        List<SapPermitItemVo> itemVos = sapPermitVo.getItemVos();
        List<SapPermitItem> sapPermitItems = new ArrayList<>();
        if (!CollectionUtils.isEmpty(itemVos)){
            sapPermitItems= itemVos
                    .stream()
                    .map(itemVo -> {
                        SapPermitItem sapPermitItem = new SapPermitItem();
                        BeanUtil.copyProperties(itemVo, sapPermitItem);
                        return sapPermitItem;
                    }).collect(Collectors.toList());
        formData.put("items", JSONUtil.toString(sapPermitItems));
        //启动流程实例
        this.startProcessInstance(SapPermitApplication.PROCESS_DEFINITION_KEY, formData);
        //sapPermit.setId(bizId);
        //this.sapPermitRepository.save(sapPermit);
        }
    }

    public String startProcessInstance(String processDefinitionKey,Map<String, Object> formData){
        Map<String, Object> variables = new HashMap();
        SDO localSdo = this.buildSDO(formData);
        ThreadLocalUtil.putVariable(Constants.SDO, localSdo);
        variables.put("startModel", ProcessStartModel.MANUAL.getId());
        Operator operator = localSdo.getOperator();
        variables.put("executorFullId", operator.getFullId());
        variables.put("executorFullName", operator.getFullName());
        ThreadLocalUtil.putOperator(operator);
        ThreadLocalUtil.putVariable("client.ip", "127.0.0.1");
        ProcessInstance processInstance = this.workflowApplication.startProcessInstanceByKey(processDefinitionKey, variables);
        String businessKey = processInstance.getBusinessKey();
        return businessKey;
    }

    private SDO buildSDO(Map<String, Object> formData) {
        String createdById = (String) formData.get("applyPerson");
        Operator operator = operatorApplication.createOperatorByPersonMemberId(createdById);
        SDO localSdo = new SDO();
        // 将业务数据传递给工作流
        formData.forEach(localSdo::putProperty);
        // 将业务流程信息传递给工作流
        localSdo.putProperty("processAction", ProcessAction.SAVE);
        localSdo.putProperty("procUnitId", "Apply");
        localSdo.setOperator(operator);
        return localSdo;
    }

    public ByteArrayOutputStream printInfo(HttpServletResponse response, String id) {

        SapPermit permit=this.sapPermitRepository.findOne(id);
        List <SapPermitItem> itemList=this.sapPermitItemRepository.findBySapPermitId(id);
        if (itemList.size()<10){
            int s=itemList.size();
            for (int u=0;u<10-s;u++) {
                SapPermitItem item = new SapPermitItem();
                item.setBelongings("&nbsp;");
                itemList.add(item);
            }
        }
        String sql="select s.code,w.handler_name,w.handler_id,w.dept_name,w.full_id,w.HANDLED_DATE  FROM WF_PROCUNITHANDLER w left join sa_oporg s on s.id=w.HANDLER_ID";
        sql+="  where  biz_id='"+id+"' order  by w.HANDLED_DATE desc ";
        List<Map<String, Object>> mapList=sqlExecutorDao.queryToListMap(sql);
        Map<String ,Object> data = new HashMap<>();
        if  (mapList.size()>0){
            String lastAuditPerson=mapList.get(0).get("handlerName").toString();
            data.put("lastAuditPerson",lastAuditPerson);
        }
        if  (mapList.size()>1) {
            String preLastAuditPerson = mapList.get(1).get("handlerName").toString();
            data.put("preAuditPerson",preLastAuditPerson);
        }
        data.put("head",permit);
        data.put("itemList",itemList);

         //Document document = null;
         ByteArrayOutputStream byteArrayOutputStream = null;
        try {
            response.reset();
            response.setHeader("Content-Type", "application/pdf-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("放行条.pdf", "UTF-8"));
            String randoms=CommonUtil.createGUID().substring(0,10);
            /*File  fileDir=new File("bar");
            if(!fileDir.exists()) {
               fileDir.mkdirs();
            }*/
            File  file = new File("bar-"+permit.getBillCode()+".png");
            if(!file.exists()) {
                String IMG_TYPE_PNG = "image/png";
                data.put("barCode", CommonUtils.genBarCode128(permit.getBillCode(), IMG_TYPE_PNG, file,128,10, HumanReadablePlacement.HRP_NONE));
            } else {
                data.put("barCode",file);
            }
            File  fileb = new File("baoshen.png");
            data.put("baoshen",fileb);
            Template template = freemarkerConfigurer.getConfiguration().getTemplate("fxt.ftl");
            byteArrayOutputStream = CommonUtils.createPDF(data,template);

        }catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("PDF生成失败！");
        } finally {

        }
       return  byteArrayOutputStream;
    }


}
