package yem.base.common.utils;

import com.alibaba.fastjson.JSONObject;
import kd.bos.context.RequestContext;
import kd.bos.dataentity.OperateOption;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.entity.OrmLocaleValue;
import kd.bos.dataentity.metadata.dynamicobject.DynamicObjectType;
import kd.bos.entity.operate.result.OperationResult;
import kd.bos.exception.KDBizException;
import kd.bos.fileservice.FileItem;
import kd.bos.fileservice.FileService;
import kd.bos.fileservice.FileServiceFactory;
import kd.bos.ksql.util.StringUtil;
import kd.bos.orm.ORM;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.AttachmentServiceHelper;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.operation.DeleteServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.bos.servicehelper.user.UserServiceHelper;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 附件面板工具类
 *
 * @author longh
 * @description:
 * @date 2021年8月20日 下午4:33:59
 */
public class AttachmentUtil extends FileUtil {

    public AttachmentUtil(String formId) {
        super(formId);
    }

    /**
     * 上传附件至附件面板
     *
     * @param appId         应用标识
     * @param formId        单据标识
     * @param pkId          单据内码
     * @param attachmentKey 附件面板标识
     * @param fileName      文件名
     * @param filePath      文件物理地址
     * @return
     * @throws IOException
     */
    public static DynamicObject uploadAttachment(String appId, String formId, String pkId, String attachmentKey, String fileName, String filePath) throws IOException {
        Date today = new Date();
        DateFormat df = new SimpleDateFormat("yyyyMM");
        String NewDateStr = df.format(today);
        String attachmentPath = "/" + RequestContext.get().getTenantId() + "/" + RequestContext.get().getAccountId()
                + "/" + NewDateStr + "/" + appId + "/" + formId + "/" + pkId + "/attachments/";
        DynamicObject newAtt = BusinessDataServiceHelper.newDynamicObject("bos_attachment");
        File file = new File(filePath);
        if (file.isFile()) {
            @SuppressWarnings("resource")
            int size = new FileInputStream(file).available();
            FileService fs = FileServiceFactory.getAttachmentFileService();
            String path = attachmentPath + fileName;
            FileItem fi = new FileItem(fileName, path, new FileInputStream(file.getPath()));
            fi.setCreateNewFileWhenExists(true);
            String url = fs.upload(fi);
            if (url != null && !"".equals(url)) {
                newAtt.set("fnumber", "upload_" + formId);
                newAtt.set("FBillType", formId);
                newAtt.set("FInterID", pkId);
                newAtt.set("FModifyTime", today);
                newAtt.set("fcreatetime", today);
                newAtt.set("FaliasFileName", fileName);
                newAtt.set("FAttachmentName", fileName);
                newAtt.set("FFileId", url);
                newAtt.set("FExtName", fileName != null ? fileName.substring(fileName.lastIndexOf(46) + 1) : "");
                newAtt.set("FATTACHMENTSIZE", size);
                newAtt.set("FCREATEMEN", RequestContext.get().getCurrUserId());
                newAtt.set("fattachmentpanel", attachmentKey);
                newAtt.set("fdescription", "");
                SaveServiceHelper.save(new DynamicObject[]{newAtt});
            } else {
                new Exception("附件【" + fileName + "】上传失败！");
            }
        }
        return newAtt;
    }

    /**
     * 源单中的附件面板上传到目标单的附件面板上
     *
     * @param from 源单
     * @param to   目标单
     */
    public static void uploadAttachmentPanel(DynamicObject from, DynamicObject to) {
        String selectProp = "id,fnumber,fmodifytime,fcreatetime,faliasfilename,fattachmentname,ffileid,fextname,fattachmentsize,fcreatemen,fattachmentpanel,fdescription";
        DynamicObject[] Attachments = BusinessDataServiceHelper.load("bos_attachment", selectProp,
                new QFilter[]{new QFilter("FInterID", "=", String.valueOf(from.getLong("id"))), new QFilter("fbilltype", "=", from.getDataEntityType().getName())});

        DynamicObject[] toAttachments = BusinessDataServiceHelper.load("bos_attachment", selectProp,
                new QFilter[]{new QFilter("FInterID", "=", String.valueOf(to.getLong("id"))), new QFilter("fbilltype", "=", to.getDataEntityType().getName())});

        //记录日志
        CreateLogBill(from, to, Attachments, toAttachments);

        //删除to里面的附件信息
        if (toAttachments != null && !YEM.isEmpty(toAttachments)) {
            List<Object> attIds = new ArrayList<>();
            DynamicObjectType attType = new DynamicObjectType();
            for (DynamicObject toAttachment : toAttachments) {
                attType = toAttachment.getDynamicObjectType();
                attIds.add(toAttachment.getPkValue());
            }
            DeleteServiceHelper.delete(attType, attIds.toArray());
        }
        JSONObject json = new JSONObject();
        if (to.getDataEntityType().getProperties().containsKey("yem_attachmentcon")) {
            String jsonStr = to.getString("yem_attachmentcon_tag");
            json = YEM.isEmpty(jsonStr) ? null : JSONObject.parseObject(jsonStr);
        }

        for (DynamicObject attach : Attachments) {
            String fileName = (String) attach.get("fattachmentname");
            String fileId = (String) attach.get("fnumber");

            //修改变更单上名字时不要new直接修改bos_attachment的名字
            DynamicObject newAtt = BusinessDataServiceHelper.newDynamicObject("bos_attachment");
            Long id = ORM.create().genLongId("bos_attachment");
            newAtt.set("id", id);
            String newAttUid = "upload_" + id;
            //修改json里面保存的数据
            if (json != null) {
                JSONObject innerJson = json.getJSONObject(fileId);
                innerJson.put("uid", newAttUid);
                Object value = json.remove(fileId);
                json.put(newAttUid, value);
//                to.set("yem_attachmentcon_tag", json);
            }

            newAtt.set("fnumber", newAttUid);
            newAtt.set("FBillType", to.getDataEntityType().getName());
            newAtt.set("FInterID", to.getString("id"));
            newAtt.set("FModifyTime", attach.get("fmodifytime"));
            newAtt.set("fcreatetime", attach.get("fcreatetime"));
            newAtt.set("FaliasFileName", fileName);
            newAtt.set("FAttachmentName", fileName);
            newAtt.set("FFileId", attach.get("ffileid"));
            newAtt.set("FExtName", attach.get("fextname"));
            newAtt.set("FATTACHMENTSIZE", attach.get("fattachmentsize"));
            newAtt.set("FCREATEMEN", attach.get("fcreatemen"));
            newAtt.set("fattachmentpanel", attach.get("fattachmentpanel"));
            newAtt.set("fdescription", attach.get("fdescription"));
            SaveServiceHelper.save(new DynamicObject[]{newAtt});
        }

        if (json != null){
            DynamicObject toForm = BusinessDataServiceHelper.loadSingle(to.getDataEntityType().getName(),
                    new QFilter[]{new QFilter("id", QCP.equals, to.getLong("id"))});
            toForm.set("yem_attachmentcon_tag",json);
            SaveServiceHelper.save(new DynamicObject[]{toForm});
        }

    }

    /**
     * 保留附件更新信息方法类
     *
     * @param from
     * @param to
     */
    public static void CreateLogBill(DynamicObject from, DynamicObject to, DynamicObject[] Attachments, DynamicObject[] toAttachments) {
        DynamicObject logEntity =
                BusinessDataServiceHelper.newDynamicObject("yem_cm_attachupdatelog");

        //给日志单据上的基本信息字段赋值
        String orgName = from.getDataEntityType().getName();
        DynamicObject orgBillObject =
                BusinessDataServiceHelper.loadSingle("bos_entityobject", new QFilter[]{new QFilter("number", "=", orgName)});
        logEntity.set("yem_orghostentity", orgBillObject);//原单据主实体
        logEntity.set("yem_orgbillno", from.getString("id"));//原单据编号
        String newName = to.getDataEntityType().getName();
        DynamicObject newBillObject =
                BusinessDataServiceHelper.loadSingle("bos_entityobject", new QFilter[]{new QFilter("number", "=", newName)});
        logEntity.set("yem_newhostentity", newBillObject);//新单据主实体
        logEntity.set("yem_newbillno", to.getString("id"));//新单据主编号
        logEntity.set("yem_updatedatetime", new Date());
        logEntity.set("yem_operator", UserServiceHelper.getCurrentUser("name"));//修改人

        //给原单据体附件信息分录赋值
        DynamicObjectCollection orgEntryentity = logEntity.getDynamicObjectCollection("yem_orgentryentity");
        for (DynamicObject orgAtt : toAttachments) {//根据附件面板中的值给日志单据的单据体赋值
            DynamicObject orgNewEntry = orgEntryentity.addNew();
            orgNewEntry.set("yem_orgattachname", orgAtt.get("fattachmentname"));
            orgNewEntry.set("yem_orgattachnumber", orgAtt.get("fnumber"));
            orgNewEntry.set("yem_orgattachurl", orgAtt.get("ffileid"));
            orgNewEntry.set("yem_orgattachid", orgAtt.get("id"));
        }

        //给新单据体附件表格赋值
        DynamicObjectCollection newEntryentity = logEntity.getDynamicObjectCollection("yem_newentryentity");
        for (DynamicObject newAtt : Attachments) {//根据附件面板中的值给日志单据的单据体赋值
            DynamicObject newNewEntry = newEntryentity.addNew();
            newNewEntry.set("yem_newattachname", newAtt.get("fattachmentname"));
            newNewEntry.set("yem_newattachnumber", newAtt.get("fnumber"));
            newNewEntry.set("yem_newattachurl", newAtt.get("ffileid"));
            newNewEntry.set("yem_newattachid", newAtt.get("id"));
        }


        OperationResult result = SaveServiceHelper.
                saveOperate("yem_cm_attachupdatelog", new DynamicObject[]{logEntity}, OperateOption.create());
        if (!result.isSuccess()) {
            throw new KDBizException("日志保存失败");
        }

    }

    /**
     * 上传附件至文件服务器
     *
     * @param appId
     * @param formId   单据标识
     * @param pkId     单据内码
     * @param fileName 文件名
     * @param filePath 文件物理地址
     * @return
     * @throws IOException
     */
    public static String uploadFileItem(String appId, String formId, String pkId, String fileName, String filePath) throws IOException {
        Date today = new Date();
        DateFormat df = new SimpleDateFormat("yyyyMM");
        String NewDateStr = df.format(today);
        String attachmentPath = "/" + RequestContext.get().getTenantId() + "/" + RequestContext.get().getAccountId()
                + "/" + NewDateStr + "/" + appId + "/" + formId + "/" + pkId + "/attachments/";
        String url = "";
        File file = new File(filePath);
        if (file.isFile()) {
            FileService fs = FileServiceFactory.getAttachmentFileService();
            String path = attachmentPath + fileName;
            FileItem fi = new FileItem(fileName, path, new FileInputStream(file.getPath()));
            fi.setCreateNewFileWhenExists(true);
            url = fs.upload(fi);
            if (url == null || "".equals(url)) {
                new Exception("附件【" + fileName + "】上传失败！");
            }
        }
        return url;
    }

    /**
     * 下载附件到指定附件面板
     *
     * @param appId
     * @param formId
     * @param pkId
     * @param attachmentKey
     * @param fileName
     * @param downloadUrl
     * @throws IOException
     */
    public DynamicObject downloadFile2Attachment(String appId, String formId, String pkId, String attachmentKey, String fileName, String downloadUrl) throws IOException {
        return uploadAttachment(appId, formId, pkId, attachmentKey, fileName, this.downloadFile(fileName, downloadUrl));
    }

    /**
     * 下载附件到文件服务器
     *
     * @param appId
     * @param formId
     * @param pkId
     * @param fileName
     * @param downloadUrl
     * @return
     * @throws IOException
     */
    public String downloadFile2FileItem(String appId, String formId, String pkId, String fileName, String downloadUrl) throws IOException {
        return uploadFileItem(appId, formId, pkId, fileName, this.downloadFile(fileName, downloadUrl));
    }

}
