package com.inkasso.factoring.file.controller;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.util.StringUtil;
import com.inkasso.adapter.enums.FileBusinessInterface;
import com.inkasso.adapter.response.ResponseData;
import com.inkasso.factoring.common.util.onlineConverter.OfficeConverterUtil;
import com.inkasso.factoring.common.util.onlineConverter.TextConverterPdfUtil;
import com.inkasso.factoring.file.entity.FileStorageDO;
import com.inkasso.factoring.file.enums.FileTypeEnum;
import com.inkasso.factoring.file.service.FileService;
import com.inkasso.factoring.file.util.FileUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 *
 */
@RestController
@RequestMapping("system")
public class FileController {

    private Logger log = LogManager.getLogger(FileController.class);
    private static String PREFIX = "sys/fileStorage/";

    @Autowired
    private FileService fileService;

    /**
     * 文件上传
     *
     * @param fileType
     * @param request
     * @return
     */
    @PostMapping(value = "fileStorage")
    public ResponseData doUploadFiles(@RequestParam("fileType") String fileType, HttpServletRequest request) {
        FileTypeEnum fileTypeEnum = FileTypeEnum.getByCode(fileType);
        FileStorageDO fileStorageDO = fileService.uploadFile(request, fileTypeEnum);
        return ResponseData.success(fileStorageDO);
    }

    /**
     * 删除附件
     *
     * @param id
     * @return
     */
    @DeleteMapping(value = "fileStorage/{id}")
    public ResponseData delete(@Validated @PathVariable("id") Long id) {
        fileService.delete(id);
        return ResponseData.success();
    }

    /**
     * 文件上传
     *
     * @param files
     * @param request
     * @return
     */
    @PostMapping(value = "fileStorages")
    public ResponseData doUploadFiles(@RequestParam("fileType") List<String> files, HttpServletRequest request) {
        if (CollectionUtil.isNotEmpty(files)) {
            List<FileBusinessInterface> list = new ArrayList<>();
            for (String s : files) {
                FileTypeEnum fileTypeEnum = FileTypeEnum.getByCode(s);
                if (fileTypeEnum != null) {
                    list.add(fileTypeEnum);
                }
            }
            fileService.uploadFiles(request, list);
        }
        return ResponseData.success();
    }


    /**
     * 预览非图片的</br>
     * 文档预览，不使用流直接输出到页面上，因为浏览器不支持这样的格式。通常word、excel都是用流下载的</br>
     * 根据文件的类型，用不同的处理方式来预览文件
     */
    @RequestMapping("/fileStorage/preview")
    public String previewTest(Long fileId, HttpServletResponse response, Model model) {
        FileStorageDO fileStorage = fileService.getById(fileId);
        if (null != fileStorage && StringUtil.isNotEmpty(fileStorage.getBusinessType())) {
            String fileType = fileStorage.getBusinessType();
            String fileName = fileStorage.getOriginalName().replace(",", "");
            String sourceFilePath = fileStorage.getAbsolutePath();
            // 1、处理以及预览doc、docx、rtf文件。使用了openOffice转换成pdf
            if (fileType.equalsIgnoreCase(".doc") || fileType.equalsIgnoreCase(".docx")
                    || fileType.equalsIgnoreCase(".rtf") || fileType.equalsIgnoreCase(".wps")) {
                String destFile = FileUtil.getFileOnlinePreviewPath() + "/word.pdf";
                File newPDFile = OfficeConverterUtil.office2Pdf(sourceFilePath, destFile);
                previewPdf(response, newPDFile, fileName, null);
            } else if (fileType.equalsIgnoreCase(".txt")) {
                // 2、单独处理txt文件，转换成pdf。没有使用openOffice
                TextConverterPdfUtil p = TextConverterPdfUtil.getInstance();
                String pdf = FileUtil.getFileOnlinePreviewPath() + "/txt.pdf";
                p.text2Pdf(sourceFilePath, pdf);
                previewPdf(response, new File(pdf), fileName, null);
            } else if (fileType.equalsIgnoreCase(".xls") || fileType.equalsIgnoreCase(".xlsx")
                    || fileType.equalsIgnoreCase(".et") || fileType.equalsIgnoreCase(".csv")) {
                // 3、处理Excel、使用openOffice转换成HTML
                String destFile = FileUtil.getFileOnlinePreviewPath() + "/excel.html";
                File htmlFile = OfficeConverterUtil.office2Pdf(sourceFilePath, destFile);
                //2023.4.25 如果excel嵌套有图片，需要替换下文件的路径
                htmlFile = replaceImgSrc(htmlFile);
                previewHtmlFile(response, htmlFile);
            } else if (fileType.equalsIgnoreCase(".pdf")) {
                File pdfFile = new File(fileStorage.getAbsolutePath());
                previewPdf(response, pdfFile, fileName, "original");
            } else if (fileType.equalsIgnoreCase(".zip") || fileType.equalsIgnoreCase(".rar")) {
                fileService.downloadFile(fileId);
            } else {
                // 图片的预览
                String filePath = null;
                if (null != fileStorage) {
                    filePath = fileStorage.getPath();
                }
                model.addAttribute("filePath", filePath);
                return PREFIX + "fileStoragePreview";
            }
        }
        return null;
    }


    /**
     * 文件下载（预览）
     *
     * @param absolutePath 文件路径
     * @param response
     */
    @GetMapping("/fileStorage/downloadPdfFile")
    public void downloadFile(String absolutePath, HttpServletResponse response) {
        if (absolutePath != null) {
            File file = new File(absolutePath);
            fileService.downloadPdfFile(response, file);
        }
    }


    /**
     * 以流的方式在浏览器上查看pdf文件
     */
    private void previewPdf(HttpServletResponse response, File pdfFile, String fileName, String sourceType) {
        FileInputStream inputStream;
        try {
            if (StringUtil.isNotEmpty(fileName)) {
                int end = fileName.lastIndexOf(".");
                String newName = fileName.substring(0, end);
                if (StringUtil.isNotEmpty(newName)) {
                    response.setHeader("Content-disposition",
                            "filename=" + new String(newName.getBytes("gbk"), "iso8859-1") + ".pdf");
                }
            }
            response.setContentType("application/pdf;charset=gb2312");
            // 通过文件路径获得File对象
            inputStream = new FileInputStream(pdfFile);
            OutputStream os = response.getOutputStream();
            int read;
            while ((read = inputStream.read()) != -1) {
                os.write(read);
            }
            os.flush();
            inputStream.close();
            os.close();
        } catch (Exception e) {

        }
        if (StringUtil.isEmpty(sourceType)) {
            if (pdfFile.exists()) {
                pdfFile.delete();
            }
        }
    }

    /**
     * 替换下文件中嵌套的图片的路径
     *
     * @param htmlFile
     * @return
     */
    private File replaceImgSrc(File htmlFile) {
        try {
            Document doc = Jsoup.parse(htmlFile, "gbk");
            Elements imgElements = doc.getElementsByTag("IMG");
            if (imgElements != null && !imgElements.isEmpty()) {
                for (Element img : imgElements) {
                    String src = img.attr("SRC");
                    if (src != null) {
                        // img.attr("SRC", "/excelImg/" + src);
                        File imgFile = new File(htmlFile.getParent(), src);
                        if (imgFile.exists()) {
                            String type = src.substring(src.lastIndexOf(".") + 1);
                            String head = "data:image/" + type + ";base64,";
                            img.attr("SRC", head + Base64.encode(imgFile));
                            imgFile.delete();
                        }
                    }
                }
                String html = doc.getElementsByTag("HTML").html();

                if (htmlFile.exists()) {
                    boolean delete = htmlFile.delete();
                    if (delete) {
                        File newFile = new File(htmlFile.getAbsolutePath());
                        cn.hutool.core.io.FileUtil.appendString(html, newFile, "gbk");
                        return newFile;
                    }
                }
            }
            return htmlFile;

        } catch (IOException e) {
            e.printStackTrace();
        }
        return htmlFile;
    }

    /**
     * 用流的方式在浏览器上查看html文件
     */
    private void previewHtmlFile(HttpServletResponse response, File xmlFile) {
        response.setContentType("text/html");
        FileInputStream inputStream;
        try {
            inputStream = new FileInputStream(xmlFile);
            OutputStream os = response.getOutputStream();
            int read;
            while ((read = inputStream.read()) != -1) {
                os.write(read);
            }
            os.flush();
            inputStream.close();
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("预览Excel文件出错：" + e.getMessage());
        }
        if (xmlFile.exists()) {
            xmlFile.delete();
        }
    }

}
