package nckd.jimin.jyyy.fi.common.util;

import com.kingdee.bos.util.backport.Collections;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.utils.StringUtils;
import kd.bos.db.DB;
import kd.bos.db.DBRoute;
import kd.bos.db.SqlParameter;
import kd.bos.exception.KDBizException;
import kd.bos.fileservice.FileServiceFactory;
import kd.bos.form.IFormView;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.print.matchtpl.*;
import kd.bos.servicehelper.AttachmentServiceHelper;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.PrintServiceHelper;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.svc.util.print.PrintFileUtil;
import kd.bos.util.CollectionUtils;
import kd.bos.util.ExceptionUtils;
import kd.bos.web.actions.utils.FilePathUtil;
import kd.tmc.bei.common.helper.ReceiptPrintHelper;
import nckd.jimin.jyyy.fi.common.constant.BillTypeConstants;
import nckd.jimin.jyyy.fi.common.constant.ErPrintSetConstant;
import nckd.jimin.jyyy.fi.common.entity.MergePrintEntity;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class ReceiveTicketUtils {
    private static Log logger = LogFactory.getLog(ReceiveTicketUtils.class);

    /**
     * 打印模板编码合并打印
     * @param view
     * @param tplNumberList
     * @param fileName
     * @return
     */
    public static String mergePrintPdf(IFormView view , List<MergePrintEntity> tplNumberList , String fileName){
        List<byte[]> mergeArray = new ArrayList<>();


        for (MergePrintEntity print : tplNumberList) {
            if(StringUtils.isEmpty(print.getFormId()) || CollectionUtils.isEmpty(print.getPkIds())) {
                continue;
            }
            for(Object printBillId : print.getPkIds()){

                // 电子回单获取附件
                if(BillTypeConstants.BEI_ELECRECEIPT.equals(print.getFormId())){
                    byte[] printBuff = getElecReceiptPrintUrl(printBillId);
                    if(printBuff != null && printBuff.length != 0){
                        logger.info("电子回单文件大小：" + printBuff.length);
                        mergeArray.add(printBuff);
                    }
                } else{
                    if(StringUtils.isNotEmpty(print.getTemplateId())){
                        String tplType = getTplTypeById(print.getTemplateId());

                        int tplParamType = "A".equalsIgnoreCase(tplType)?1:2;
                        byte[] printBuff = PrintPdfUtil.getPrintByte(view.getPageId(),print.getFormId(),print.getTemplateId(),
                                Collections.singletonList(printBillId),"billForm",tplParamType);
                        mergeArray.add(printBuff);
                    }
                }
            }

        }

        if(CollectionUtils.isNotEmpty(mergeArray)){
            byte[] multiPdf = PrintServiceHelper.mergeMultiPdf(mergeArray);//拼接文件流
            // 设置临时文件有效时间
            return "tempfile/print.do?" + PrintFileUtil.saveInputStream2TempFile(fileName+".pdf",
                    new ByteArrayInputStream(multiPdf), 3600 * 2);
        }
        return "";
    }


    public static String getPrintTemplateId(String appId,String formId, Object billId) {
        TplMatcherParam param = new TplMatcherParam();
        param.setEntityId(formId);//表单id
        List<Object> pkIds = new ArrayList<>(1);
        pkIds.add(billId);
        param.setPkIds(pkIds);//单据内码集合
        param.setViewType(ViewType.LIST);
        //param.setAppId(appId);//应用id
        TplMatcherUtil matcherUtil = new TplMatcherUtil(param);

        MatcherResult matcherResult = matcherUtil.runMatcher();
        Map<Object, Set<MatcherTpl>> pkTplMap = matcherResult.getPkTplMap();
        if(pkTplMap.containsKey(billId)){
            Set<MatcherTpl> matcherTpls = pkTplMap.get(billId);
            if(matcherTpls.size() > 1){
                throw new KDBizException("单据存在多条打印模板，请在模板条件中维护。");
            }
            return matcherTpls.iterator().next().getTplId();
        }

        throw new KDBizException(String.format("单据【%s】【%s】没有匹配的打印模板。", formId,billId));
    }


    public static String getTplTypeById(String tplId) {
        String sql = "select ftype from t_svc_printmeta where fid=?";
        SqlParameter[] sqlParams = new SqlParameter[]{new SqlParameter("fid", 12, tplId)};
        String ftype = (String) DB.query(DBRoute.basedata, sql, sqlParams, (dSet) -> {
            return dSet.next() ? dSet.getString("ftype") : null;
        });
        return ftype;
    }

    /**
     * 获取打印模板配置
     * @param formId
     * @param companyId
     * @return
     */
    public static List<MergePrintEntity> getPrintPdfConfig(String formId , Object billId,Object companyId){
        List<MergePrintEntity> mergePrintList = new ArrayList<>();
        // 查询公司为空的打印配置
        DynamicObject printSetConfig = getPrintSetConfig(companyId);
        if(printSetConfig == null){
            throw new KDBizException("未找到公司配置的打印配置信息。");
        }
        // 查询单据对应的分录
        DynamicObjectCollection billEntryCol = printSetConfig.getDynamicObjectCollection(ErPrintSetConstant.BillPtSetEntry.ENTITYID);
        List<DynamicObject> billEntryList = billEntryCol.stream()
                .filter(r -> StringUtils.equals(formId, r.getString(ErPrintSetConstant.BillPtSetEntry.KEY_NCKD_BILLTYPE)))
                .collect(Collectors.toList());
        if(CollectionUtils.isEmpty(billEntryList)){
            throw new KDBizException("请先在打印配置中维护单据信息。");
        }

        if(billEntryList.size() > 1){
            throw new KDBizException("打印配置中单据存在多条配置。");
        }
        DynamicObject billConfigEntry = billEntryList.get(0);

        Map<String, Set<Object>> relationBelowBillMap = ErFindRelationBillUtils.getRelationBelowBillMap(billId.toString(), formId);
        // 打印单据
        if(billConfigEntry.getBoolean(ErPrintSetConstant.BillPtSetEntry.KEY_NCKD_ISPTCOVER)){
            String mainBillTpl = getPrintTemplateId(null, formId, billId);
            mergePrintList.add(new MergePrintEntity(formId,mainBillTpl, Collections.singletonList(billId),billConfigEntry.getInt(ErPrintSetConstant.BillPtSetEntry.KEY_NCKD_COVERORDER),true));
        }

        if(billConfigEntry.getBoolean(ErPrintSetConstant.BillPtSetEntry.KEY_NCKD_ISPTVOUCHER)){
            if(relationBelowBillMap.containsKey(BillTypeConstants.GL_VOUCHER)){
                Set<Object> voucherIdList = relationBelowBillMap.get(BillTypeConstants.GL_VOUCHER);
                List<MergePrintEntity> vcPrintList = new ArrayList<>(voucherIdList.size());
                for(Object voucherId : voucherIdList){
                    String printTemplateId = getPrintTemplateId(null, BillTypeConstants.GL_VOUCHER, voucherId);
                    vcPrintList.add(new MergePrintEntity(BillTypeConstants.GL_VOUCHER,printTemplateId, Collections.singletonList(voucherId),billConfigEntry.getInt(ErPrintSetConstant.BillPtSetEntry.KEY_NCKD_VOUCHERORDER)));
                }

                // 如果不打印业务单据，则从凭证中选一条作为住单据
                if(!billConfigEntry.getBoolean(ErPrintSetConstant.BillPtSetEntry.KEY_NCKD_ISPTCOVER)){
                    //vcPrintList.get(0).setMainBill(true);
                }

                mergePrintList.addAll(vcPrintList);
            }
        }
        if(billConfigEntry.getBoolean(ErPrintSetConstant.BillPtSetEntry.KEY_NCKD_ISPTRECEIPT)){
            if(relationBelowBillMap.containsKey(BillTypeConstants.BEI_ELECRECEIPT)){
                Set<Object> elecReceipt = relationBelowBillMap.get(BillTypeConstants.BEI_ELECRECEIPT);
                // 电子回单特殊处理，直接打印附件
                mergePrintList.add(new MergePrintEntity(BillTypeConstants.BEI_ELECRECEIPT,null, elecReceipt.stream().collect(Collectors.toList()),billConfigEntry.getInt(ErPrintSetConstant.BillPtSetEntry.KEY_NCKD_RECEIPTORDER)));
            }
        }
        return mergePrintList;
    }

    /**
     * 获取打印配置，优先用当前公司匹配，如果没有合适的使用全集团的
     * @param companyId
     * @return
     */
    public static DynamicObject getPrintSetConfig(Object companyId){
        DynamicObjectCollection companyConfigCol = QueryServiceHelper.query(ErPrintSetConstant.ENTITYID, ErPrintSetConstant.ID, new QFilter[]{
                new QFilter(ErPrintSetConstant.KEY_NCKD_ORG, QCP.equals, companyId),
                new QFilter(ErPrintSetConstant.KEY_STATUS, QCP.equals, "C"),
                new QFilter(ErPrintSetConstant.KEY_ENABLE, QCP.equals, Boolean.TRUE)
        });
        if(CollectionUtils.isNotEmpty(companyConfigCol)){

            if(companyConfigCol.size() > 1){
                throw new KDBizException("公司存在多条打印配置，请维护数据后再操作。");
            }
            return BusinessDataServiceHelper.loadSingle(companyConfigCol.get(0).get(ErPrintSetConstant.ID),ErPrintSetConstant.ENTITYID);
        }else{
            DynamicObjectCollection groupConfig = QueryServiceHelper.query(ErPrintSetConstant.ENTITYID, ErPrintSetConstant.ID,new QFilter[]{
                    QFilter.isNull(ErPrintSetConstant.KEY_NCKD_ORG).or(new QFilter(ErPrintSetConstant.KEY_NCKD_ORG,QCP.equals,0L)),
                    new QFilter(ErPrintSetConstant.KEY_STATUS, QCP.equals, "C"),
                    new QFilter(ErPrintSetConstant.KEY_ENABLE, QCP.equals, Boolean.TRUE)
            });
            if(CollectionUtils.isNotEmpty(groupConfig)){
                if(groupConfig.size() > 1){
                    throw new KDBizException("存在多条全集团配置，请维护数据后再操作。");
                }
                return BusinessDataServiceHelper.loadSingle(groupConfig.get(0).get(ErPrintSetConstant.ID),ErPrintSetConstant.ENTITYID);
            }
        }
        return null ;
    }

    /**
     * 获取电子回单文件，已开会沟通，从附件中获取
     * @param receiptId
     * @return
     */
    public static byte[] getElecReceiptPrintUrl(Object receiptId){
        List<Map<String, Object>> attachments = AttachmentServiceHelper.getAttachments(BillTypeConstants.BEI_ELECRECEIPT, receiptId, "attachmentpanel");
        List<byte[]> resList = new ArrayList<>(10);
        for (Map<String, Object> attachmentMap: attachments) {
            if(attachmentMap.get("type") != null
                    && ("pdf".equals(attachmentMap.get("type").toString()) || "jpg".equals(attachmentMap.get("type").toString()))) {

                if(attachmentMap == null) {
                    continue;
                }

                Object relativeUrl = attachmentMap.get("relativeUrl");
                if (relativeUrl == null) {
                    continue;
                }

                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                String path = FilePathUtil.dealPath(relativeUrl.toString(), "attach");
                InputStream inputStream = FileServiceFactory.getAttachmentFileService().getInputStream(path);

                if("jpg".equals(attachmentMap.get("type").toString())){
                    ReceiptPrintHelper.imageConvertPdf(path, resList, inputStream);
                    continue;
                }

                byte[] bytesAtt = null;
                try {
                    bytesAtt = getBytes(inputStream,outputStream);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                if(bytesAtt != null){
                    resList.add(bytesAtt);
                }
            }
        }
        byte[] mergeMultiPdf = null;
        if (!resList.isEmpty()) {
            if (resList.size() > 1) {
                try {
                    mergeMultiPdf = ReceiptPrintHelper.mergeMultiPdf(resList);
                } catch (Exception var5) {
                    throw new KDBizException(ExceptionUtils.getExceptionStackTraceMessage(var5));
                }
            } else {
                mergeMultiPdf = (byte[])resList.get(0);
            }
        } else {
            return null;
        }
        return mergeMultiPdf;
    }

    public static byte[] getBytes(InputStream inputStream, ByteArrayOutputStream outputStream) throws IOException {
        int b;
        while ((b= inputStream.read())!=-1){
            outputStream.write(b);
        }
        byte[] bytes1 = outputStream.toByteArray();
        return bytes1;
    }
}
