package yem.base.common.module.attach.dynamic;

import com.lowagie.text.Document;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfReader;
import kd.bos.cache.CacheFactory;
import kd.bos.context.RequestContext;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.entity.LocaleString;
import kd.bos.dataentity.resource.ResManager;
import kd.bos.entity.EntityMetadataCache;
import kd.bos.entity.MainEntityType;
import kd.bos.entity.datamodel.IDataModel;
import kd.bos.exception.KDBizException;
import kd.bos.fileservice.FileItem;
import kd.bos.fileservice.FileService;
import kd.bos.fileservice.FileServiceFactory;
import kd.bos.form.FormShowParameter;
import kd.bos.form.IFormView;
import kd.bos.form.control.AttachmentPanel;
import kd.bos.form.control.Control;
import kd.bos.form.control.EntryGrid;
import kd.bos.form.events.AfterDoOperationEventArgs;
import kd.bos.form.field.ComboEdit;
import kd.bos.form.field.ComboItem;
import kd.bos.form.plugin.AbstractFormPlugin;
import kd.bos.lang.Lang;
import kd.bos.metadata.dao.MetaCategory;
import kd.bos.metadata.dao.MetadataDao;
import kd.bos.metadata.form.ControlAp;
import kd.bos.metadata.form.FormMetadata;
import kd.bos.metadata.form.control.AttachmentPanelAp;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.user.UserServiceHelper;
import kd.sdk.plugin.Plugin;
import yem.base.common.utils.FileUtil;
import yem.base.common.utils.YEM;

import java.io.*;
import java.net.URLDecoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * PDF 文件合并动态表单插件
 * @author lib
 * @date 2025年01月14日 下午 16:45:51
 */
public class PDFMergeDynamicPlugin extends AbstractFormPlugin implements Plugin {

    @Override
    public void afterCreateNewData(EventObject e) {
        super.afterCreateNewData(e);
        IFormView parentView = this.getView().getParentView();
        String parentFormName = parentView.getModel().getDataEntity().getDataEntityType().getName();
        DynamicObject orgBillObject = BusinessDataServiceHelper.loadSingle("bos_entityobject",
                new QFilter[]{new QFilter("number", QCP.equals, parentFormName)});
        this.getView().getModel().setValue("yem_srcentity",orgBillObject);
        this.getView().setEnable(false,"yem_srcentity");
        Map<String,String> attachControl = getAttachControl(parentFormName);
        Set<String> attachControlKey = attachControl.keySet();
        // 初始化 [目标面板]下拉列表项集合
        String currLCId = Lang.get().toString();// 获取当前语言代码
        List<ComboItem> entryItems = new ArrayList<>();
        for (String name : attachControlKey) {
            ComboItem comboItem = new ComboItem();
            comboItem.setValue(attachControl.get(name));
            comboItem.setCaption(new LocaleString(currLCId, "" + name));
            entryItems.add(comboItem);
        }
        ComboEdit yemTargetkey = this.getControl("yem_targetkey");
        yemTargetkey.setComboItems(entryItems);
        initData(attachControlKey);
    }

    @Override
    public void afterDoOperation(AfterDoOperationEventArgs e) {
        super.afterDoOperation(e);
        String operateKey = e.getOperateKey();
        switch(operateKey){
            case "refreshentry": // 刷新自动重新从父页面更新PDF文件明细
                IFormView parentView = this.getView().getParentView();
                String parentFormName = parentView.getModel().getDataEntity().getDataEntityType().getName();
                Map<String,String> attachControl = getAttachControl(parentFormName);
                Set<String> attachControlKey = attachControl.keySet();
                initData(attachControlKey);
                break;
            default :
                break;
        }
    }

    /**
     *  PDF文件合并界面初始化
     * */
    private void initData(Set<String> attachControlKey){
        IFormView view = this.getView();
        IDataModel model = view.getModel();
        IFormView parentView = this.getView().getParentView();
        // 清除分录
        model.deleteEntryData("yem_entryentity");
        for (String attachKey : attachControlKey) {
            // 获取附件
            AttachmentPanel panel = parentView.getControl(attachKey);
            List<Map<String, Object>> attachs = panel.getAttachmentData();
            DynamicObjectCollection entry = model.getEntryEntity("yem_entryentity");
            for (Map<String, Object>  attach:attachs){
                String fileName = (String) attach.get("name");
                String url = (String) attach.get("url");
                if (YEM.isEmpty(fileName)) continue;
                if (fileName.endsWith(".pdf") || fileName.endsWith(".PDF")){
                    int row = model.createNewEntryRow("yem_entryentity");
                    model.setValue("yem_attachmentname",fileName,row);
                    model.setValue("yem_url",url,row);
                }
            }
        }
    }

    @Override
    public void registerListener(EventObject e) {
        super.registerListener(e);
        this.addClickListeners("btnok","btncancel");
    }

    @Override
    public void click(EventObject evt) {
        super.click(evt);
        IFormView view = this.getView();
        IFormView parentView = view.getParentView();
        if (parentView == null)return;
        Control source = (Control) evt.getSource();
        String key = source.getKey();
        // 获取需要合并的文件
        EntryGrid treeEntryEntity = this.getControl("yem_entryentity");
        String yemTargetkey = (String) view.getModel().getValue("yem_targetkey");
        int[] rows = treeEntryEntity.getSelectRows();
        switch(key){
            case "btnok":
                if (rows.length < 2 ){
                    this.getView().showErrorNotification(ResManager.loadKDString("请至少选择两个文件进行合并！", "PDFMergeDynamicPlugin_1", "yem-base"));
                    return;
                }
                if (YEM.isEmpty(yemTargetkey)){
                    this.getView().showErrorNotification(ResManager.loadKDString("请先选择合并附件的目标面板！", "PDFMergeDynamicPlugin_0", "yem-base"));
                    return;
                }
                Arrays.sort(rows);
                try {
                    mergeCreateFile(rows,yemTargetkey);
                } catch (IOException e) {
                    this.getView().showErrorNotification(ResManager.loadKDString("文件合并失败！", "PDFMergeDynamicPlugin_2", "yem-base"));
                    return;
                }
                view.returnDataToParent(yemTargetkey);
                view.close();
                break;
            case "btncancel":
                view.close();
                break;
            default:
                break;
        }
    }





    // 合并生成文件并回传至源单
    private void mergeCreateFile(int[] rows ,String yemTargetkey ) throws IOException {
        // 获取源单数据
        IFormView parentView = this.getView().getParentView();
        DynamicObject obj = parentView.getModel().getDataEntity();// 源单实体
        SimpleDateFormat format = new SimpleDateFormat("HHmmss");
        String date = format.format(new Date());
        String newfilename = obj.getString("billno")+"_"+date+".pdf";
        String formId = obj.getDataEntityType().getName();
        //创建新的pdf文件作为合并的pdf文件
        Document document = new Document();
        PdfCopy pdfCopy=null;
        FileUtil fileUtil = new FileUtil(formId);
        File newfile = fileUtil.newFile(newfilename);
        FileUtil.createNewFile(newfile);
        FileOutputStream fileOutputStream = new FileOutputStream(newfile);
        try {
            pdfCopy = new PdfCopy(document, fileOutputStream);
            document.open();
            for (int i = 0; i < rows.length; i++) {
                int row = rows[i];
                String url = (String)this.getView().getModel().getValue("yem_url", row);
                InputStream inputStream = null;
                if (url.contains("serversForCache")){
                    inputStream = CacheFactory.getCommonCacheFactory().getTempFileCache().getInputStream(url);

                } else {
                    String path = getPath(url);
                    inputStream = FileServiceFactory.getAttachmentFileService().getInputStream(path);
                }
                PdfReader pdfReader = new PdfReader(inputStream);
                //循环原pdf文件的各页信息，添加到新的pdf文件中
                for (int f=1;f<=pdfReader.getNumberOfPages();f++){
                    pdfCopy.addPage(pdfCopy.getImportedPage(pdfReader,f));
                    pdfReader.close();
                }
            }
        } catch (Exception e) {
            fileOutputStream.close();
            document.close();
            throw new KDBizException(ResManager.loadKDString("合并文件失败！", "PDFMergeDynamicPlugin_3", "yem-base"));
        }
        document.close();
        fileOutputStream.close();
        DateFormat df = new SimpleDateFormat("yyyyMM");
        String NewDateStr = df.format(new Date());
        String path = "/" + RequestContext.get().getTenantId() +
                "/" + RequestContext.get().getAccountId()+
                "/" + NewDateStr +
                "/" + formId + "/" + obj.getString("id") +
                "/"+newfilename;
        FileService fs = FileServiceFactory.getAttachmentFileService();
        FileItem fi = new FileItem(newfilename, path, new FileInputStream(newfile.getPath()));
        fi.setCreateNewFileWhenExists(true);
        String url = fs.upload(fi);
        List<Map<String,Object>>attachDataList= new ArrayList<>();
        Map<String,Object>attachMap =new HashMap<>();
        //获取附件inputstream上传到缓存服务
        InputStream inputStream= FileServiceFactory.getAttachmentFileService().getInputStream(url);
        attachMap.put("size",calculateSize(FileServiceFactory.getAttachmentFileService().getInputStream(url)));//size
        String saveUrl=CacheFactory.getCommonCacheFactory().getTempFileCache().saveAsFullUrl(newfilename,
                new BufferedInputStream(inputStream),2*3600);
        attachMap.put("url", saveUrl);//url
        attachMap.put("uid", UUID.randomUUID().toString());//uid
        attachMap.put("name",newfilename);//name
        attachMap.put("lastModified",new Date().getTime());//lastModified
        attachMap.put("uploadTime",new Date().getTime());
        attachMap.put("status","success");
        long currentUserId = UserServiceHelper.getCurrentUserId();
        DynamicObject user = BusinessDataServiceHelper.loadSingle(currentUserId, "bos_user");
        attachMap.put("creator", user == null ? "金小蝶":user.getString("name"));
        attachMap.put("description", "");//description
        attachMap.put("type", "pdf");
        attachMap.put("fattachmentpanel",yemTargetkey);
        attachMap.put("entityNum", "");
        attachMap.put("billPkId", 0L);
        attachMap.put("billno", "");
        attachMap.put("client", "web");
        attachMap.put("endProgress", true);
        attachMap.put("filesource", 1);
        attachDataList.add(attachMap);
        AttachmentPanel  control = this.getView().getParentView().getControl(yemTargetkey);
        control.upload(attachDataList);
        this.getView().getParentView().updateView(yemTargetkey);
    }



    /**
     * 根据文件下载url截取相对路径
     * @param url 文件下载url
     * */
    private String getPath(String url){
        String path=null;
        if (url.contains("path=")){
            String[] paths = url.split("path=");
            path=paths[1];
        }else {
            path=url;
        }
        try {
            //url解码
            path = URLDecoder.decode(path, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        //移除前面多余的//
        if (path.startsWith("//")){
            path = path.substring(2, path.length());
        }
        return path;
    }



    /**
     * 根据文件流获取新文件的大小
     * */
    public static long calculateSize(InputStream inputStream) {
        long size = 0;
        byte[] buffer = new byte[4096];
        int bytesRead;
        try {
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                size += bytesRead;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return size;
    }


    /**
     * 获取源单实体所有附件面板的key\name
     * @param formName 源单标识
     * */
    private Map<String,String> getAttachControl(String formName){
        MainEntityType entityType = EntityMetadataCache.getDataEntityType(formName);
        FormMetadata taskMeta = (FormMetadata) MetadataDao.readRuntimeMeta(MetadataDao.getIdByNumber(
                                                        entityType.getName(), MetaCategory.Form), MetaCategory.Form);
        List<ControlAp<?>> items = taskMeta.getItems();
         // 附件面板标识集合。
        Map<String,String> attachmentPanelAp = new HashMap<>();
        items.forEach(item ->{
            if(item instanceof AttachmentPanelAp){
                AttachmentPanelAp attachmentPanel = (AttachmentPanelAp) item;
                attachmentPanelAp.put(String.valueOf(attachmentPanel.getName()),attachmentPanel.getKey());
            }
        });
        return attachmentPanelAp;
    }
}