package com.bonus.sgzb.system.service.impl;

import cn.hutool.core.util.IdUtil;
import com.bonus.sgzb.common.core.utils.DateTimeHelper;
import com.bonus.sgzb.common.core.utils.GlobalConstants;
import com.bonus.sgzb.common.core.utils.uuid.IdUtils;
import com.bonus.sgzb.common.security.utils.SecurityUtils;
import com.bonus.sgzb.system.config.ConstantPropertiesUtil;
import com.bonus.sgzb.system.domain.FileInfo;
import com.bonus.sgzb.system.mapper.FileInfoMapper;
import com.bonus.sgzb.system.service.SysFileService;
import com.bonus.sgzb.system.service.feign.FileClient;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.region.Region;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hwpf.extractor.WordExtractor;
import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.*;

/**
 * 本地文件存储
 *
 * @author zys
 */
@Slf4j
@Primary
@Service("SysFileService")
public class SysFileServiceImpl implements SysFileService {

    @Resource
    private FileInfoMapper dao;
    /**
     * 上传文件存储在本地的根路径
     */
    @Value("${file.path}")
    private String localFilePath;

    @Resource
    private FileClient fileClient;


    /**
     * 本地文件上传接口
     *
     * @return 访问地址
     * @throws Exception
     */
    @Override
    public FileInfo uploadFile(HttpServletRequest request) throws Exception {
        FileInfo file = new FileInfo();
        StandardMultipartHttpServletRequest req = (StandardMultipartHttpServletRequest) request;
       // String photoType = req.getParameter("fileType");
        Long userId = SecurityUtils.getLoginUser().getUserid();
        HashMap<String, Object> map = getFile(req);
        List<MultipartFile> items = (List<MultipartFile>) map.get("filePath");
        MultipartFile item = items.get(0);
        try {
            //String url = saveFile(request, item, photoType);
            /*AjaxResult res = fileClient.uploadFile(item);
            String url = (String) res.get("msg");*/
            String url = this.uploadFile(item);
            if (url != null) {
                int words = getFileText(item);
                String fileName = item.getOriginalFilename();
                String type = fileName.substring(fileName.lastIndexOf(".") + 1);
                long size = item.getSize() / 1024 / 1024;
                file.setFileName(fileName);
                log.info("文件名为：{}",fileName);
                file.setFileUrl(url);
                file.setCreator(userId.toString());
                file.setType(type);
                file.setSize(size + "M");
                file.setWords(words);
                file.setCreateBy(SecurityUtils.getLoginUser().getUserid().toString());
                file.setCreateTime(new Date());
                dao.insertFileInfo(file);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return file;
    }

    /**
     * 腾讯云文件上传
     * @param file
     * @return
     */
    public String uploadFile(MultipartFile file) {
        // 1 初始化用户身份信息（secretId, secretKey）。
        String secretId = ConstantPropertiesUtil.ACCESS_KEY_ID;
        String secretKey = ConstantPropertiesUtil.ACCESS_KEY_SECRET;
        COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
        // 2 设置 bucket 的地域, COS 地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
        Region region = new Region(ConstantPropertiesUtil.END_POINT);
        ClientConfig clientConfig = new ClientConfig();
        // 这里建议设置使用 https 协议
        clientConfig.setHttpProtocol(HttpProtocol.https);
        clientConfig.setRegion(region);
        // 3 生成 cos 客户端。
        COSClient cosClient = new COSClient(cred, clientConfig);

        // 存储桶的命名格式为 BucketName-APPID，此处填写的存储桶名称必须为此格式
        String bucketName = ConstantPropertiesUtil.BUCKET_NAME;
        // 对象键(Key)是对象在存储桶中的唯一标识。  998u-09iu-09i-333
        //在文件名称前面添加uuid值
        String key = IdUtils.fastSimpleUuid() + file.getOriginalFilename();
        //对上传文件分组，根据当前日期  /2024/04/02
        String dateTime = new DateTime().toString("yyyy/MM/dd");
        key = dateTime+"/"+key;
        try {
            //获取上传文件输入流
            InputStream inputStream = file.getInputStream();
            ObjectMetadata objectMetadata = new ObjectMetadata();
            PutObjectRequest putObjectRequest = new PutObjectRequest(
                    bucketName,
                    key,
                    inputStream,
                    objectMetadata);
            // 高级接口会返回一个异步结果Upload
            PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
            // 返回上传文件路径:https://ggkt-atguigu-1310644373.cos.ap-beijing.myqcloud.com/01.jpg
            return "https://" + bucketName + "." + "cos" + "." + ConstantPropertiesUtil.END_POINT+".myqcloud.com" + "/" + key;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 头像上传
     *
     * @return 访问地址
     * @throws Exception
     */
    @Override
    public FileInfo uploadHeadPic(MultipartFile item,String fileType) {
        FileInfo file = new FileInfo();
        Long userId = SecurityUtils.getLoginUser().getUserid();
        try {
            //String url = saveFilePic(item, fileType);
            /*AjaxResult res = fileClient.uploadFile(item);
            String url = (String) res.get("msg");*/
            String url = this.uploadFile(item);
            if (url != null) {
                int words = getFileText(item);
                String fileName = item.getOriginalFilename();
                String type = fileName.substring(fileName.lastIndexOf(".") + 1);
                long size = item.getSize() / 1024 / 1024;
                file.setFileName(fileName);
                file.setFileUrl(url);
                file.setCreator(userId.toString());
                file.setType(type);
                file.setSize(size + "M");
                file.setWords(words);
                file.setCreateBy(SecurityUtils.getLoginUser().getUserid().toString());
                file.setCreateTime(new Date());
                dao.insertFileInfo(file);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return file;
    }

    public HashMap<String, Object> getFile(StandardMultipartHttpServletRequest request) {
        MultipartFile multipartFile;
        HashMap<String, Object> map = new HashMap<String, Object>(16);
        try {
            List<MultipartFile> tmps = new ArrayList<MultipartFile>();
            Iterator<String> itr = request.getFileNames();
            while (itr.hasNext()) {
                multipartFile = request.getFile(itr.next());
                tmps.add(multipartFile);
            }
            map.put("filePath", tmps);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    public String saveFile(HttpServletRequest request, MultipartFile multipartFile, String fileType) throws Exception {
        String url = "";
        // 完整路径 IE
        String tmpName = multipartFile.getOriginalFilename();
        tmpName = tmpName.substring(tmpName.lastIndexOf("\\") + 1);
        tmpName = IdUtil.fastSimpleUUID() + System.currentTimeMillis() + tmpName.substring(tmpName.lastIndexOf("."), tmpName.length());
        String imageFiles = localFilePath+ "/" + fileType + "/";
        String os = System.getProperty("os.name");
        if (os.toLowerCase().startsWith(GlobalConstants.STRING_WIN)) {
            imageFiles = "D://files/" + fileType + "/";
        }
        String year = DateTimeHelper.getNowYear();
        String month = DateTimeHelper.getNowMonths();
        String day = DateTimeHelper.getNowDay();
        String specfile = imageFiles + year + "/" + month + "/" + day;
        File file = new File(specfile + "/" + tmpName);

        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        url = "/" + fileType + "/" + year + "/" + month + "/" + day + "/" + tmpName;
        if (!multipartFile.isEmpty()) {
            try {
                FileOutputStream fos = new FileOutputStream(file);
                InputStream in = multipartFile.getInputStream();
                byte[] bytes = new byte[1024];
                int len = 0;
                while ((len = in.read(bytes)) != -1) {
                    fos.write(bytes, 0, len);
                }
                fos.close();
                in.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return url;
    }

    public String saveFilePic(MultipartFile multipartFile, String fileType) throws Exception {
        String url = "";
        // 完整路径 IE
        String tmpName = multipartFile.getOriginalFilename();
        tmpName = tmpName.substring(tmpName.lastIndexOf("\\") + 1);
        tmpName = IdUtil.fastSimpleUUID() + System.currentTimeMillis() + tmpName.substring(tmpName.lastIndexOf("."), tmpName.length());
        String imageFiles = localFilePath + fileType + "/";
        String os = System.getProperty("os.name");
        if (os.toLowerCase().startsWith(GlobalConstants.STRING_WIN)) {
            imageFiles = "D://files/" + fileType + "/";
        }
        String year = DateTimeHelper.getNowYear();
        String month = DateTimeHelper.getNowMonths();
        String day = DateTimeHelper.getNowDay();
        String specfile = imageFiles + year + "/" + month + "/" + day;
        File file = new File(specfile + "/" + tmpName);

        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        url = "/" + fileType + "/" + year + "/" + month + "/" + day + "/" + tmpName;
        if (!multipartFile.isEmpty()) {
            try {
                FileOutputStream fos = new FileOutputStream(file);
                InputStream in = multipartFile.getInputStream();
                byte[] bytes = new byte[1024];
                int len = 0;
                while ((len = in.read(bytes)) != -1) {
                    fos.write(bytes, 0, len);
                }
                fos.close();
                in.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return url;
    }

    private int getFileText(MultipartFile file) throws IOException {
        int length = 0;
        String fileName = file.getOriginalFilename();
        InputStream fileInputStream = file.getInputStream();
        try {
            ZipSecureFile.setMinInflateRatio(-1.0d);
            //获取文件后缀名
            String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
            //定义word内容
            String content = "";
            switch (suffix) {
                case "doc":
                    WordExtractor wordExtractor = new WordExtractor(fileInputStream);
                    content = wordExtractor.getText();
                    break;
                case "docx":
                    XWPFDocument document = new XWPFDocument(fileInputStream);
                    XWPFWordExtractor extractor = new XWPFWordExtractor(document);
                    content = extractor.getText();
                    break;
                default:
                    break;
            }
            //中文单词
            String cnWords = content.replaceAll("[^(\\u4e00-\\u9fa5，。《》？；’‘：“”【】、）（……￥！·)]", "");
            int cnWordsCount = cnWords.length();
            //非中文单词
            String noCnWords = content.replaceAll("[^(a-zA-Z0-9`\\-=\';.,/~!@#$%^&*()_+|}{\":><?\\[\\])]", " ");
            int noCnWordsCount = 0;
            String[] ss = noCnWords.split(" ");
            for (String s : ss) {
                if (s.trim().length() != 0) {
                    noCnWordsCount++;
                }
            }
            length = cnWordsCount + noCnWordsCount;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fileInputStream != null) {
                fileInputStream.close();
            }
        }
        return length;
    }

}
