package shkd.utils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.util.*;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.io.ByteStreams;
import kd.bos.cache.CacheFactory;
import kd.bos.cache.TempFileCache;
import kd.bos.context.RequestContext;
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.servicehelper.AttachmentServiceHelper;
import kd.bos.servicehelper.MetadataServiceHelper;
import kd.bos.util.FileNameUtils;

public class AttachmentFileUtil {

    private static final Log logger = LogFactory.getLog(AttachmentFileUtil.class);

    /**将第三方提供的某个在线文件上传至星瀚对应单据附件上
     * @param entity 目标单据实体标识
     * @param pk 目标数据id
     * @param fileUrl 待存入文件的url
     * @param fileName 待存入文件名称
     * @param fileSize 待存入文件大小
     * @param attachKey 附件面板标识
     * @throws IOException
     */
    public static boolean saveUrlFile2Attchment(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<>();
        //文件名称
        attachItem.put("name", fileName);
        //将url文件转换成输入流
        InputStream inputStream = null;
        HttpURLConnection conn = null;
        String tempUrl = null;
        try {
            URL url = new URL(fileUrl);
            conn = (HttpURLConnection)url.openConnection();
            //设置超时间为30秒
            conn.setConnectTimeout(30000);
            //防止屏蔽程序抓取而返回403错误
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            //得到输入流
            inputStream = conn.getInputStream();
            //文件大小
            attachItem.put("size",  fileSize);
            //获取临时文件缓存
            TempFileCache cache = CacheFactory.getCommonCacheFactory().getTempFileCache();
            //将文件流存入临时文件缓存(拷贝完成)(最后一个参数为缓存有效期,600秒)
            tempUrl = cache.saveAsFullUrl(fileName, inputStream, 600);

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            //关闭流
            try {
                inputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            //关闭连接
            conn.disconnect();
        }
        //获取文件的缓存路径
//        tempUrl = EncreptSessionUtils.encryptSession(tempUrl);
//        //获取域名前缀
//        String address = RequestContext.get().getClientFullContextPath();
//        if (!address.endsWith("/")) {
//            address = address + "/";
//        }
//        //拼接url路径
//        String tempUrl3 = address + tempUrl;
        //修改时间
        attachItem.put("lastModified",System.currentTimeMillis());
        //获取appId
        MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType(entity);
        String appId = dataEntityType.getAppId();
        //将文件缓存中的附件文件上传到正式文件服务器
        String actUrl = AttachmentServiceHelper.saveTempToFileService(tempUrl,appId,entity, pk, (String)attachItem.get("name"));

        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);
        FileItem fileItem = new FileItem(fileName, pathParam, in);
        // cache.remove(url);
        // 上传附件到文件服务器
        String downUrl =service.upload(fileItem);

        //将新文件的物理路径存入map
        attachItem.put("url", actUrl);
        attachments.add(attachItem);
        //维护单据和附件的关系(非文件上传)
        AttachmentServiceHelper.upload(entity, pk, attachKey, attachments);
        return true;
    }

    /**将文件服务器上某个目录下的所有文件上传至星瀚对应单据附件上
     * @param appId 目标单据所属应用标识
     * @param entity 目标单据实体标识
     * @param pk 目标数据id
     * @param attachKey 附件面板标识
     * @param dirpath 文件目录路径
     * @param filenames 文件名称集合
     * @author yuxueliang
     */
    public static boolean saveDirFile2Attchment(String appId, String entity, Object pk, String dirpath, String attachKey, JSONArray filenames) throws Exception {
        //先删除合同对应附件面板中已存在的附件,再从nas上传新的附件
        List<Map<String, Object>> contfiles = AttachmentServiceHelper.getAttachments(entity,pk,attachKey);
        if(contfiles != null && !contfiles.isEmpty()){
            for (Map<String, Object> attItem : contfiles){
                logger.info(attachKey+"删除附件:"+attItem.get("name"));
                AttachmentServiceHelper.remove(entity,pk,attItem.get("uid"));
            }
        }
        logger.info("传入的文件夹路径"+dirpath);
        List<Map<String, Object>> attachments = new ArrayList<>(1);
        Map<String, Object> attachItem;
        String fileName;
        JSONObject destFile;
        String tempUrl;//星瀚临时文件url
        String actUrl;//星瀚正式文件url
        //获取临时文件缓存
        TempFileCache cache = CacheFactory.getCommonCacheFactory().getTempFileCache();
        InputStream inputs;
        FileService service = FileServiceFactory.getAttachmentFileService();
        byte[] filecontent;
        //遍历目标目录,得到所有文件
        for (int i = 0; i < filenames.size(); i++) {
            destFile = filenames.getJSONObject(i);
            attachments.clear();
//            service = FileServiceFactory.getAttachmentFileService();
//            cache = CacheFactory.getCommonCacheFactory().getTempFileCache();
            fileName = destFile.getString("fileName");//文件名称可能涉及字符集转义,需要注意
            attachItem = new HashMap<>();
            //附件编号 如果不设置,在前台删除某一个文件时,会把所有编号为空的都删掉
            attachItem.put("uid", "nas"+System.currentTimeMillis());
            //文件名称
            attachItem.put("name", fileName);
            logger.info("文件名称"+fileName);
            inputs = service.getInputStream(dirpath+"/"+fileName);
//            inputs = service.getInputStream("E:\\dobews\\dobe_cosmic6\\replay_pid13348.log");
//            logger.info("文件大小"+inputs.available());//Linux服务器上此方法不能返回文件大小,都是0
            //文件大小
            filecontent = ByteStreams.toByteArray(inputs);
            attachItem.put("size", filecontent.length);
            logger.info("文件大小"+filecontent.length);
            if(filecontent.length == 0){
                attachItem.put("size", 60000);
            }
            //将文件流存入临时文件缓存(拷贝完成)(最后一个参数为缓存有效期,600秒)
            tempUrl = cache.saveAsUrl(fileName, filecontent, 600);//此方法执行后inputs会被自动关闭,后续不能再对inputs操作

            //修改时间
            attachItem.put("lastModified",System.currentTimeMillis());
            logger.info("文件临时路径"+tempUrl);
            //将文件缓存中的附件文件上传到正式文件服务器
            actUrl = AttachmentServiceHelper.saveTempToFileService(tempUrl,appId,entity,pk,fileName);
            logger.info("文件正式路径"+actUrl);
            //将新文件的物理路径存入map
            attachItem.put("url", actUrl);

            attachments.add(attachItem);
            //维护单据和附件的关系(非文件上传)
            AttachmentServiceHelper.upload(entity, pk, attachKey, attachments);
        }
        return true;
    }

    /**将文件服务器上某个目录下的所有文件上传至星瀚对应单据附件上-由于file server的限制,此方法不可行,无法读取到对应目录
     * @param appId 目标单据所属应用标识
     * @param entity 目标单据实体标识
     * @param pk 目标数据id
     * @param attachKey 附件面板标识
     * @param dirpath 文件目录路径
     * @throws IOException
     */
    public static boolean saveDirFile2Attchment(String appId,String entity,Object pk,String dirpath,String attachKey) throws IOException {
        File currentDir = new File(".");
        logger.info("当前系统路径"+currentDir.getAbsolutePath());

        logger.info("传入的路径"+dirpath);
        File dirfile = new File(dirpath);
        if(!dirfile.isDirectory()){
            //传入的路径不是目录或者目录不存在
            logger.info("不是目录或者目录不存在"+dirpath);
            return false;
        }
        File[] files = dirfile.listFiles();
        if(files.length == 0){
            //目录下没有文件,不需要处理
            logger.info("目录下没有文件,不需要处理"+dirpath);
            return false;
        }
        List<Map<String, Object>> attachments = new ArrayList<>();
        Map<String, Object> attachItem;
        String fileName;
        File destFile;
        String tempUrl;//星瀚临时文件url
        String actUrl;//星瀚正式文件url
        //获取临时文件缓存
        TempFileCache cache = CacheFactory.getCommonCacheFactory().getTempFileCache();
        //遍历目标目录,得到所有文件
        for (int i = 0; i < files.length; i++) {
            destFile = files[i];
            fileName = destFile.getName();
            attachItem = new HashMap<>();
            //文件名称
            attachItem.put("name", fileName);
            //文件大小
            attachItem.put("size", destFile.length());
            //将文件流存入临时文件缓存(拷贝完成)(最后一个参数为缓存有效期,600秒)
            tempUrl = cache.saveAsFullUrl(fileName, Files.readAllBytes(destFile.toPath()), 900);
            //修改时间
            attachItem.put("lastModified",System.currentTimeMillis());
            //将文件缓存中的附件文件上传到正式文件服务器
            actUrl = AttachmentServiceHelper.saveTempToFileService(tempUrl,appId,entity,pk,fileName);
            //如下代码功能与saveTempToFileService实际功能重复,先注释掉,待调试确认
//            FileService service = FileServiceFactory.getAttachmentFileService();
//            RequestContext requestContext = RequestContext.get();
//            String uuid = UUID.randomUUID().toString().replace("-", "");
//            // 生成文件路径-上传附件时远程服务器需要存储文件的位置
//            String pathParam = FileNameUtils.getAttachmentFileName(requestContext.getTenantId(),
//                    requestContext.getAccountId(), uuid, fileName);
//            FileItem fileItem = new FileItem(fileName, pathParam, cache.getInputStream(tempUrl));
//            // 上传附件到文件服务器
//            service.upload(fileItem);

            //将新文件的物理路径存入map
            attachItem.put("url", actUrl);
            attachments.add(attachItem);
        }
        //维护单据和附件的关系(非文件上传)
        AttachmentServiceHelper.upload(entity, pk, attachKey, attachments);
        return true;
    }

    /**将星瀚nfs上某个目录下的所有文件关联至星瀚对应单据附件上,不需要文件上传
     * 此方法在明确文件路径情况下可行,但是删除时,也会将对应文件删掉,不建议使用
     * @param appId 目标单据所属应用标识
     * @param entity 目标单据实体标识
     * @param pk 目标数据id
     * @param attachKey 附件面板标识
     * @param dirpath 文件目录路径
     * @throws IOException
     */
    public static boolean realtionDirFile2Attchment(String appId,String entity,Object pk,String dirpath,String attachKey) {
//        File[] files = new File(dirpath).listFiles();
//        if(files.length == 0){
//            //目录下没有文件,不需要处理
//            return false;
//        }
        List<Map<String, Object>> attachments = new ArrayList<>();
        Map<String, Object> attachItem;
        String fileName = "1.docx";
//        File destFile;
        //遍历目标目录,得到所有文件
//        for (int i = 0; i < files.length; i++) {
//            destFile = files[i];
//            fileName = destFile.getName();
            attachItem = new HashMap<>();
            //文件名称
            attachItem.put("name", fileName);
            //文件大小
            attachItem.put("size", 1);
            //修改时间
            attachItem.put("lastModified",System.currentTimeMillis());
        TempFileCache cache = CacheFactory.getCommonCacheFactory().getTempFileCache();
        FileService service = FileServiceFactory.getAttachmentFileService();
//        service.download("/oa/uat/ht-202502001-nj/232906839800890085/1.docx");
        String tempUrl = cache.saveAsUrl(fileName, service.getInputStream("/oa/uat/ht-202502001-nj/232906839800890085/1.docx"), 900);
        String actUrl = AttachmentServiceHelper.saveTempToFileService(tempUrl,appId,entity,pk,fileName);
            //将文件的物理路径存入map
            attachItem.put("url", actUrl);
            attachments.add(attachItem);
//        }

//        long filesize = service.getFileSize("/oa/uat/ht-202502001-nj/232906839800890085/1.docx");
//        service.download();
//        logger.info("文件大小"+filesize);
        //维护单据和附件的关系(非文件上传)
        AttachmentServiceHelper.upload(entity, pk, attachKey, attachments);
        return true;
    }

    /**将第三方提供的某个在线文件上传至星瀚对应单据附件上
     * @param entity 目标单据实体标识
     * @param pk 目标数据id
     * @param fileUrl 待存入文件的url
     * @param fileName 待存入文件名称
     * @param fileSize 待存入文件大小
     * @param attachKey 附件面板标识
     * @throws IOException
     */
    public static boolean saveUrlFile2Attch(String entity,Object pk,String fileUrl,String fileName,String fileSize,String attachKey) throws IOException{
        List<Map<String, Object>> attachments = new ArrayList<>();
        Map<String, Object> attachItem = new HashMap<>();
        //文件名称
        attachItem.put("name", fileName);
        //将url文件转换成输入流
        InputStream inputStream = null;
        HttpURLConnection conn = null;
        String tempUrl = null;
        try {
            URL url = new URL(fileUrl);
            conn = (HttpURLConnection)url.openConnection();
            //设置超时间为30秒
            conn.setConnectTimeout(30000);
            //防止屏蔽程序抓取而返回403错误
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            //得到输入流
            inputStream = conn.getInputStream();
            //文件大小
            attachItem.put("size",  fileSize);
            //获取临时文件缓存
            TempFileCache cache = CacheFactory.getCommonCacheFactory().getTempFileCache();
            //将文件流存入临时文件缓存(拷贝完成)(最后一个参数为缓存有效期,600秒)
            tempUrl = cache.saveAsFullUrl(fileName, inputStream, 600);

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            //关闭流
            try {
                inputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            //关闭连接
            conn.disconnect();
        }
        //修改时间
        attachItem.put("lastModified",System.currentTimeMillis());
        //获取appId
        MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType(entity);
        String appId = dataEntityType.getAppId();
        //将文件缓存中的附件文件上传到正式文件服务器
        String actUrl = AttachmentServiceHelper.saveTempToFileService(tempUrl,appId,entity,pk,fileName);
        //将新文件的物理路径存入map
        attachItem.put("url", actUrl);
        attachments.add(attachItem);
        //维护单据和附件的关系(非文件上传)
        AttachmentServiceHelper.upload(entity, pk, attachKey, attachments);
        return true;
    }

}