package nckd.jimin.jyyy.fi.webapi;

import kd.bos.cache.CacheFactory;
import kd.bos.cache.TempFileCache;
import kd.bos.context.RequestContext;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.entity.MainEntityType;
import kd.bos.fileservice.FileItem;
import kd.bos.fileservice.FileService;
import kd.bos.fileservice.FileServiceFactory;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.orm.ORM;
import kd.bos.servicehelper.AttachmentServiceHelper;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.MetadataServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.bos.servicehelper.user.UserServiceHelper;
import kd.bos.util.FileNameUtils;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import nckd.base.helper.CommonHelperUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author lxl
 */
public class AttachmentFileUtil {

    private final static Log logger = LogFactory.getLog(AttachmentFileUtil.class);
    /**
     * @param entity 目标单据实体标识
     * @param pk 目标数据id
     * @param fileUrl 待存入文件的url
     * @param fileName 带存入文件名称
     * @param fileSize 带存入文件大小
     * @param attachKey 附件面板标识
     * @throws IOException
     * 温馨提示：如果不在attachItem对象中添加uid这个属性，会出现上传多个附件，但是最终跟单据绑定的都是第一个附件。
     */
    public static Map<String, Object> saveUrlFile2Attchment(String uid1,String entity, Object pk, String fileUrl, String fileName,String fileSize, String attachKey){
        List<Map<String, Object>> attachments = new ArrayList<>();
        Map<String, Object> attachItem = new HashMap<>();
        Map<String, Object> result = new HashMap<>();
        attachItem.put("name", fileName);
        attachItem.put("uid", getUid());
        InputStream inputStream = null;
        ByteArrayOutputStream outStream = null;
        String tempUrl = null;
        long size = 0;
        ChannelSftp ftpClient = null;
        Session sshSession = null;
        try {
            JSch jsch = new JSch();
            // 连接到FTP服务器
            Map<String, String> conf = CommonHelperUtils.getCommonParams("FTP");
            String loginName = conf.get("USER");
            String loginPassword = conf.get("PASSWD");
            String server = conf.get("IP");
            Integer port = Integer.parseInt(conf.get("PORT"));
            logger.info("FTP:"+loginName+server+conf.get("PORT"));
            ChannelSftp.LsEntry isEntity = null;
            // 获取sshSession
            sshSession = jsch.getSession(loginName, server, port);
            // 添加s密码
            sshSession.setPassword(loginPassword);
            Properties sshConfig = new Properties();
            sshConfig.put("StrictHostKeyChecking", "no");
            sshSession.setConfig(sshConfig);
            // 开启sshSession链接
            sshSession.connect();
            // 获取sftp通道
            ftpClient = (ChannelSftp) sshSession.openChannel("sftp");
            // 开启
            ftpClient.connect();

            inputStream = ftpClient.get(fileUrl);
            //logger.info("FTP inputStream -- size:"+inputStream.available());
            //System.out.println("inputStream:"+inputStream);

            TempFileCache cache = CacheFactory.getCommonCacheFactory().getTempFileCache();
            tempUrl = cache.saveAsFullUrl((String) attachItem.get("name"), inputStream, 1600);
            size = CacheFactory.getCommonCacheFactory().getTempFileCache().getInputStream(tempUrl).available();
            logger.info("FTP tempUrl -- inputStream -- size:" + size);
            System.out.println(":tempUrl"+tempUrl);
        } catch (Exception e) {
            logger.info("FTP 附件上传失败,堆栈信息:",e.getMessage());
            result.put("isSuccess", "false");
            result.put("msg", "转文件流异常"+e.getMessage());
            return result;
        } finally {
            try {
                if(inputStream!=null){
                    inputStream.close();
                }
                if(outStream !=null){
                    outStream.close();
                }
                if(ftpClient.getSession().isConnected()){
                    ftpClient.getSession().disconnect();
                }
            } catch (Exception e) {
                logger.info("附件上传失败,堆栈信息01:",e.getMessage());
                result.put("isSuccess", "false");
                result.put("msg", ",文件流关闭异常："+e.getMessage());
                return result;
            }
        }
        try{
            attachItem.put("lastModified",System.currentTimeMillis());
            MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType(entity);
            String appId = dataEntityType.getAppId();

            //上传到临时文件服务器
            String actUrl = AttachmentServiceHelper.saveTempToFileService(tempUrl,appId,entity, pk, (String)attachItem.get("name"));
            logger.info("actUrl:"+actUrl);
            System.out.println("actUrl:"+actUrl);
            TempFileCache cache = CacheFactory.getCommonCacheFactory().getTempFileCache();
            InputStream in = cache.getInputStream(tempUrl);
            FileService service = FileServiceFactory.getAttachmentFileService();
            RequestContext requestContext = RequestContext.get();
            String uuid = UUID.randomUUID().toString().replace("-", "");
            String pathParam = FileNameUtils.getAttachmentFileName(requestContext.getTenantId(),
                    requestContext.getAccountId(), uuid, fileName);
            logger.info("FTP pathParam:"+pathParam);

            attachItem.put("size", size);

            result.put("pathParam", pathParam);
            FileItem fileItem = new FileItem(fileName, pathParam, in);

            //从临时上传至 文件服务器
            String downUrl = service.upload(fileItem);
            logger.info("FTP downUrl:"+downUrl);

            /**
             * 附件有2个地址
             * 一个是 downloadID  示例：1ebecb8a91003c00
             * 一个是 url  示例：http://192.168.1.1/1ebecb8a91003c00
             */
            attachItem.put("downUrl", downUrl);
            attachItem.put("url", actUrl);
            result.put("url", actUrl);
            result.put("downUrl", downUrl);
            attachments.add(attachItem);
            //绑定单据
            AttachmentServiceHelper.upload(entity, pk, attachKey, attachments);

        }catch(Exception e1){
            logger.info("FTP 附件上传失败,堆栈信息e1:",e1.getMessage());
            result.put("isSuccess", "false");
            result.put("msg", "上传服务器异常："+e1.getMessage());
            return result;
        }
        result.put("isSuccess", "true");
        result.put("msg", "附件上传成功");
        return result;
    }

    public static String ioPost(String tempUrl,String fileName,String entity,String size,String attachKey,Object pk){
        List<Map<String, Object>> attachments = new ArrayList<>();
        Map<String, Object> attachItem = new HashMap<>();
        try{
            MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType(entity);
            String appId = dataEntityType.getAppId();

            //上传到临时文件服务器
            System.out.println(tempUrl);
            String actUrl = AttachmentServiceHelper.saveTempToFileService(tempUrl,appId,entity, pk,fileName);
            System.out.println("actUrl:"+actUrl);
            TempFileCache cache = CacheFactory.getCommonCacheFactory().getTempFileCache();
            InputStream in = cache.getInputStream(tempUrl);
            FileService service = FileServiceFactory.getAttachmentFileService();
            RequestContext requestContext = RequestContext.get();
            String uuid = UUID.randomUUID().toString().replace("-", "");
            String pathParam = FileNameUtils.getAttachmentFileName(requestContext.getTenantId(),
                    requestContext.getAccountId(), uuid, fileName);
            System.out.println("pathParam:"+pathParam);
            FileItem fileItem = new FileItem(fileName, pathParam, in);

            //从临时上传至 文件服务器
            String downUrl =service.upload(fileItem);
            System.out.println("downUrl:"+downUrl);

            attachItem.put("name", fileName);
            attachItem.put("size", size);
            attachItem.put("lastModified",System.currentTimeMillis());
            attachItem.put("url", actUrl);

            attachments.add(attachItem);
            attToAttachmentFile(attachItem);
            //        绑定单据
            AttachmentServiceHelper.upload(entity, pk, attachKey, attachments);
        }catch (Exception e){
            System.out.println(e);
            return e.toString();
        }
        return "ss";
    }

    
    /**
     * 将给定的附件属性映射转换为附件实体对象
     * 此方法主要用于将包含附件信息的映射转换为系统中的附件文件对象，包括设置基本属性、唯一标识、状态以及关联的元数据
     *
     * @param attachment 包含附件信息的映射，如名称、大小、类型等
     * @return DynamicObject 表示附件文件的对象，包含完整的附件属性
     */
    public static DynamicObject attToAttachmentFile(Map<String, Object> attachment) {

        //创建一条基础资料数据-附件字段
        DynamicObject attObj = BusinessDataServiceHelper.newDynamicObject("bd_attachment");
        attObj.set("name", attachment.get("name"));
        attObj.set("size", 0);
        attObj.set("uid", attachment.get("uid"));
        //attObj.set("url", attachment.get("url"));
        attObj.set("url", attachment.get("downUrl"));
        String fileType = attachment.get("name").toString();
        if (fileType.contains(".")) {
            fileType = fileType.substring(fileType.lastIndexOf(".") + 1);
        }
        attObj.set("type", fileType);
        //tempfile=1表示持久化附件对象
        attObj.set("tempfile", 1);
        ORM orm = ORM.create();
        long id = orm.genLongId("bd_attachment");
        attObj.set("id", id);
        attObj.set("pageid", "");
        attObj.set("number", UUID.randomUUID().toString());
        attObj.set("status", "B");
        Date now = new Date();
        attObj.set("modifytime", now.getTime());
        attObj.set("createtime", now.getTime());
        attObj.set("creator", UserServiceHelper.getCurrentUserId());
        SaveServiceHelper.save(new DynamicObject[]{attObj});

        return attObj;
    }

    private static InputStream getInputStreamFromURL(String urlString) throws IOException {
        URL url = null;
        try {
            url = new URL(urlString);
            HttpURLConnection conn = (HttpURLConnection)url.openConnection();
            //设置超时间为3秒
            conn.setConnectTimeout(3*1000);
            //防止屏蔽程序抓取而返回403错误
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            //得到输入流
            return conn.getInputStream();
        } catch (Exception e) {
            System.out.println(e);
        }
        return null;
    }

    /**
     * 处理url里的中文
     * @param url
     * @return
     */
    private static String zhPattern = "[\\u4e00-\\u9fa5]";

    /**
     * 替换字符串卷
     *
     * @param str 被替换的字符串
     * @param charset 字符集
     * @return 替换好的
     * @throws UnsupportedEncodingException 不支持的字符集
     */
    public static String encode(String str, String charset) throws UnsupportedEncodingException {
        Pattern p = Pattern.compile(zhPattern);
        Matcher m = p.matcher(str);
        StringBuffer b = new StringBuffer();
        while (m.find()) {
            m.appendReplacement(b, URLEncoder.encode(m.group(0), charset));
        }
        m.appendTail(b);
        return b.toString();
    }

    public static String getUid() {
        StringBuilder uid = new StringBuilder("rc-upload-");
        uid.append((new Date()).getTime());
        uid.append("-");
        int index = (int) (1.0D + Math.random() * 10.0D);
        uid.append(index);
        return uid.toString();
    }

    public static void downloadFile(String fileUrl, String saveDir) throws IOException {
        URL url = new URL(fileUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");

        int responseCode = connection.getResponseCode();
        if (responseCode == HttpURLConnection.HTTP_OK) {
            String fileName = "";
            String disposition = connection.getHeaderField("Content-Disposition");
            String contentType = connection.getContentType();

            if (disposition != null) {
                int index = disposition.indexOf("filename=");
                if (index > 0) {
                    fileName = disposition.substring(index + 10, disposition.length() - 1);
                }
            } else { fileUrl= URLDecoder.decode(fileUrl);//前面中文encode了，这里decode才能保持原文件名
                fileName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
            }

            InputStream inputStream = connection.getInputStream();
            File saveFile=new File(saveDir);
            if(!saveFile.exists()){
                saveFile.mkdirs();
            }
            String saveFilePath = saveDir + File.separator + fileName;

            FileOutputStream outputStream = new FileOutputStream(saveFilePath);

            int bytesRead;
            byte[] buffer = new byte[1024];
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            outputStream.close();
            inputStream.close();
            System.out.println(saveDir+"文件下载完成");
        } else {
            System.out.println("文件下载失败，错误码：" + responseCode+";错误文件为"+saveDir);
        }
        connection.disconnect();
    }

}