package yem.base.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import kd.bos.context.RequestContext;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.exception.KDBizException;
import kd.bos.fileservice.FileItem;
import kd.bos.fileservice.FileServiceFactory;
import kd.bos.form.IFormView;
import kd.bos.orm.ORM;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.AttachmentServiceHelper;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.attachment.AttachmentFieldServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.bos.session.EncreptSessionUtils;
import kd.bos.url.UrlService;
import org.apache.commons.io.FilenameUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;
import java.util.UUID;

/**
 * 附件字段工具类
 *
 * @author longh
 * @description:
 * @date 2021年6月29日 上午11:47:33
 */
public class AttachmentFieldUtil extends FileUtil {

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

    /**
     * 上传附件至文件服务器，并添加至附件字段表
     *
     * @param filePath
     * @return
     * @throws IOException
     */
    public static DynamicObject uploadAttachment(String filePath) throws IOException {
        String fileName = FilenameUtils.getName(filePath);
        return uploadAttachment(fileName, filePath);
    }

    /**
     * 上传附件至文件服务器，并添加至附件字段表
     *
     * @param fileName 文件名
     * @param filePath 文件物理地址
     * @return
     * @throws IOException
     */
    public static DynamicObject uploadAttachment(String fileName, String filePath) throws IOException {
        String tenantId = RequestContext.get().getTenantId();
        String accountId = RequestContext.get().getAccountId();
        DynamicObject attObj = BusinessDataServiceHelper.newDynamicObject("bd_attachment");
        File file = new File(filePath);
        if (file.isFile()) {
            FileInputStream fileInputStream = new FileInputStream(file);
            long attId = ORM.create().genLongId("bd_attachment");
            String path = String.format("/%s/%s/%s/%s/%s",
                    new Object[]{tenantId, accountId, getMonthStr(), attId, replaceSpeSymbol(fileName)});//存储路径
            FileItem fileItem = new FileItem(fileName, path, fileInputStream);
            fileItem.setCreateNewFileWhenExists(true);
            String url = FileServiceFactory.getAttachmentFileService().upload(fileItem);
            if (url != null && !"".equals(url)) {
                Date now = new Date();
                attObj.set("id", Long.valueOf(attId));
                attObj.set("name", fileName);
                attObj.set("size", fileInputStream.available());
                attObj.set("uid", "rc-upload-" + now.getTime() + "-1");
                attObj.set("url", url);
                attObj.set("type", fileName != null ? fileName.substring(fileName.lastIndexOf(46) + 1) : "");
                attObj.set("description", "");
                attObj.set("tempfile", 1);
                attObj.set("status", "B");
                attObj.set("pageid", "");
                attObj.set("number", UUID.randomUUID().toString());
                attObj.set("createtime", now);
                attObj.set("modifytime", now);
                attObj.set("creator", RequestContext.get().getCurrUserId());
                SaveServiceHelper.save(new DynamicObject[]{attObj});
            } else {
                new Exception("附件【" + fileName + "】上传失败！");
            }
            fileInputStream.close();
        }

        return attObj;
    }

    /**
     * 附件字段持久化
     *
     * @param pageId
     */
    public static void saveTempAttachments(String pageId) {
        QFilter[] filters = new QFilter[]{new QFilter("tempfile", "=", "0"), new QFilter("pageid", "=", pageId),
                new QFilter("status", "=", "B").or(new QFilter("status", "=", "success"))};
        String selectFields = "id,name,tempfile,url,pageid,size";
        DynamicObject[] att = BusinessDataServiceHelper.load("bd_attachment", selectFields, filters);
        long compressPicSize = AttachmentServiceHelper.getCompressPicSize();
        for (int i = 0; i < att.length; ++i) {
            String tempUrl = (String) att[i].get("url");
            String name = String.valueOf(att[i].get("name"));
            Object AttPk = att[i].getPkValue();
            if (tempUrl.contains("configKey")) {
                String path = AttachmentFieldServiceHelper.saveTempToFileService(tempUrl, AttPk, name);
                att[i].set("url", path);
                att[i].set("tempfile", Integer.valueOf(1));
                att[i].set("pageid", "");
                if (compressPicSize != 0L && Long.parseLong(att[i].get("size").toString()) > compressPicSize * 1024L) {
                    att[i].set("size", Long.valueOf(compressPicSize * 1024L));
                }
            }
        }
        SaveServiceHelper.save(att);
    }

    /**
     * 通过附件字段地址预览
     *
     * @param url  附件字段url
     * @param fId  单据标识
     * @param view 表单视图
     */
    @SuppressWarnings("deprecation")
    public static void doPreviewByUrl(String url, String fId, IFormView view) {
        String attachmentFullUrl = getEncreptURL(UrlService.getAttachmentFullUrl(URLEncoder.encode(url)));
        attachmentFullUrl = attachmentFullUrl.replace("download.do", "preview.do");
        if (!attachmentFullUrl.contains("&kdedcba=")) {
            attachmentFullUrl = EncreptSessionUtils.encryptSession(attachmentFullUrl);
        }
        attachmentFullUrl = attachmentFullUrl + "&fId=" + fId;
        //发送http请求,如果是返回文件流,则直接打开,否则打开参数url的链接
        String resutlt = sendGet(attachmentFullUrl, null);
        try {
            JSONObject resultMap = (JSONObject) JSON.parse(resutlt);
            if (resultMap != null && "error".equals(resultMap.get("status"))) {
                view.showTipNotification(resultMap.get("description").toString());
                return;
            } else if (resultMap != null && "success".equals(resultMap.get("status"))) {
                attachmentFullUrl = resultMap.get("url").toString();
            }
        } catch (Exception e) {
            //有异常说明返回是文件流,直接openUrl预览
        }
        view.openUrl(attachmentFullUrl);
    }

    private static String getEncreptURL(String url) {
        return EncreptSessionUtils.encryptSession(url);
    }

    /**
     * 向指定URL发送GET方法的请求
     *
     * @param url   发送请求的URL
     * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return URL 所代表远程资源的响应结果
     */
    private static String sendGet(String url, String param) {
        String userAgent = RequestContext.get().getUserAgent();
        StringBuilder result = new StringBuilder();
        String urlNameString = url;
        if (param != null && param.trim().length() > 0) {
            urlNameString = urlNameString + "?" + param;
        }
        BufferedReader in = null;
        URL realUrl;
        // 打开和URL之间的连接
        HttpURLConnection connection = null;
        InputStream is = null;
        try {
            realUrl = new URL(urlNameString);
            connection = (HttpURLConnection) realUrl.openConnection();
            // 设置连接方式：get
            connection.setRequestMethod("GET");
            // 设置连接主机服务器的超时时间：15000毫秒
            connection.setConnectTimeout(15000);
            // 设置读取远程返回的数据时间：60000毫秒
            connection.setReadTimeout(60000);
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    userAgent);
            // 建立实际的连接
            connection.connect();
            if (connection.getResponseCode() == 200) {
                is = connection.getInputStream();
                // 定义 BufferedReader输入流来读取URL的响应
                in = new BufferedReader(new InputStreamReader(is));
                String line;
                while ((line = in.readLine()) != null) {
                    result.append(line);
                }

                return result.toString();
            }
        } catch (IOException e) {
            throw new KDBizException(e.getMessage());
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                connection.disconnect();
            }
        }

        return result.toString();
    }

}
