package com.emr.service.batchExport;

import com.emr.dao.ExportTaskDetailsMapper;
import com.emr.dao.emrPdfWaterSet.EmrPdfWaterSetMapper;
import com.emr.entity.emrPdfWaterSet.EmrPdfWaterSet;
import com.emr.util.ExceptionPrintUtil;
import com.emr.util.Logger;
import com.emr.util.img2PdfUtil;
import com.emr.vo.ExportDetailsVo;
import com.emr.vo.ExportTaskDetailsVo;
import com.emr.vo.commomSearch.ScanPathVo;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import static com.emr.util.img2PdfUtil.addWaterMark;

/**
 * @ClassName BatchExportServiceImpl
 * @Description 国家病历批量导出实现类
 * @Author linjj
 * @Date 2024/4/12 11:41
 * @Version 1.0
 */
@Service
public class BatchExportServiceImpl implements BatchExportService {
    //private static Logger logger = new Logger();

    @Resource
    private Logger logger;

    @Autowired
    ExportTaskDetailsMapper exportTaskDetailsMapper;

    @Autowired
    private EmrPdfWaterSetMapper pdfWaterSetMapper;

    @Value("${export_pdf_hospital_info}")
    private String flieName;


    @Value("${export_pdf_path}")
    private String exportPdfPath;


    @Override
    public String batchExportPdf(int taskId) throws Exception {
        //是否存在目录不存在创建
        File file = new File(exportPdfPath);
        if (!file.isDirectory()) {
            file.mkdirs();
        }
        //导出文件名
        String fileName = null;
        //根据taskid查询所有需要导出病历的住院号出院日期
        List<ExportTaskDetailsVo> taskList = exportTaskDetailsMapper.selectAllByTaskId(taskId);
        if (taskList == null) {
            return "没有任务";
        }
        for (ExportTaskDetailsVo list : taskList) {
            //根据住院号出院日期查询需要导出病历路径
            List<ExportDetailsVo> filePathList = exportTaskDetailsMapper.getfilePath(list.getInpNo(), list.getDischargeDateTime());
            if (filePathList == null) {
                logger.log("病案号为：" + list.getInpNo() + "出院时间为:" + list.getDischargeDateTime() + "的病历找不到。");
                continue;
            }
            try {
                //组织导出文件名
                fileName = exportFlieName(list);
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
            Boolean aBoolean = imageToPdf(filePathList, fileName, exportPdfPath);
            //为true时修改任务状态1完成2失败
            if (aBoolean) {
                exportTaskDetailsMapper.upStatc(1, list.getId());
            } else {
                exportTaskDetailsMapper.upStatc(2, list.getId());
                logger.log("病案号为：" + list.getInpNo() + "出院时间为:" + list.getDischargeDateTime() + "的病历保存失败。");
            }

        }
        return "下载完成";
    }


    public static Boolean imageToPdf(List<ExportDetailsVo> scanPathVos, String fileName, String exportPdfPath) {
        ByteArrayOutputStream bos = null;
        FileOutputStream fileOutputStream = null;
        PdfWriter writer = null;
        try {
            bos = new ByteArrayOutputStream();
            Document document = new Document(PageSize.A4, 0, 0, 0, 0); //创建文档容器
            fileOutputStream = new FileOutputStream(exportPdfPath + fileName + ".pdf");
            writer = PdfWriter.getInstance(document, fileOutputStream);//创建编写器（PDF类型）
            //上一个目录名称
            String lastOutline = null;
            //是否增加标签
            boolean outFlag = true;
            //标签顺序
            Integer outNum = 1;
            // 添加目录
            document.open(); //打开容器
            float w, h;
            PdfContentByte cb = writer.getDirectContent();
            cb.setFontAndSize(BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 12);
            cb.beginText();
            cb.showTextAligned(PdfContentByte.ALIGN_CENTER, "目录", 300, 780, 0);
            cb.endText();
            // 创建目录
            PdfOutline root = cb.getRootOutline();
            // 添加图片到PDF
            for (int i = 0; i < scanPathVos.size(); i++) {
                String assortName = scanPathVos.get(i).getAssortName();
                if (StringUtils.isNotBlank(lastOutline) && lastOutline.equals(assortName)) {
                    outFlag = false;
                }
                if (StringUtils.isBlank(lastOutline)) {
                    lastOutline = assortName;
                    outFlag = true;
                }
                if (!lastOutline.equals(assortName)) {
                    lastOutline = assortName;
                    outFlag = true;
                }
                String imagePath = scanPathVos.get(i).getFilePath();
                Image image = Image.getInstance(imagePath);
                /*处理图片缩放比例*/
                w = image.getWidth();
                h = image.getHeight();
                image.setAlignment(com.lowagie.text.Image.ALIGN_CENTER);
                image.scaleAbsolute(PageSize.A4.getWidth(), PageSize.A4.getWidth() * (h / w));
                // 创建新页面并添加图片
                if (i != 0) {
                    document.newPage();
                }
                document.add(image);
                if (outFlag) {
                    //目录跳转页面内容设置。
                    PdfAction action = PdfAction.gotoLocalPage(i + 1, new PdfDestination(PdfDestination.FIT), writer);
                    //标题目录
                    String title = outNum + "." + scanPathVos.get(i).getAssortName();
                    new PdfOutline(root, action, title, false);
                    outNum++;
                }
            }
            document.close(); //关闭容器
        } catch (Exception e) {
            ExceptionPrintUtil.printException(e);
            e.printStackTrace();
            return false;
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }

                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }

                if (bos != null) {
                    bos.flush();
                    bos.close();
                }

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


    public static void imgToPdf(Document document, PdfWriter writer, List<ExportDetailsVo> scanPathVos) throws Exception {

    }


    //生成文件名
    private String exportFlieName(ExportTaskDetailsVo dto) throws ParseException {
        SimpleDateFormat originalFormat = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat targetFormat = new SimpleDateFormat("yyyyMMdd");
        Date date = originalFormat.parse(dto.getDischargeDateTime());
        String formattedDate = targetFormat.format(date);
        return flieName + "_" + dto.getInpNo() + "_" + formattedDate;
    }

    @Override
    public String downloadPdfZip(int taskId, HttpServletResponse response) throws IOException {
        //是否存在目录不存在创建
        File file = new File(exportPdfPath);
        if (!file.isDirectory()) {
            file.mkdirs();
        }
        //根据taskid查询所有需要导出病历的住院号出院日期
        List<ExportTaskDetailsVo> taskList = exportTaskDetailsMapper.selectAllByTaskId(taskId);
        if (taskList == null) {
            return "没有任务";
        }
        response.reset();
        response.setContentType("application/vnd.ms-excel;charset=UTF-8");
        ZipOutputStream zos = null;
        BufferedOutputStream bos = null;
        ByteArrayOutputStream out = null;
        BufferedInputStream bis = null;
        try {
            String zipName = "任务清单pdf压缩包";
            zipName = java.net.URLEncoder.encode(zipName, "UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + zipName + "(" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + ").zip");
            zos = new ZipOutputStream(response.getOutputStream());
            bos = new BufferedOutputStream(zos);
            EmrPdfWaterSet emrPdfWaterSet = pdfWaterSetMapper.selectByPrimaryKey(1);
            for (ExportTaskDetailsVo list : taskList) {
                //根据住院号出院日期查询需要导出病历路径
                List<ExportDetailsVo> filePathList = exportTaskDetailsMapper.getfilePath(list.getInpNo(), list.getDischargeDateTime());
                if (filePathList == null || filePathList.size() == 0) {
                    exportTaskDetailsMapper.upStatc(2, list.getId());
                    logger.log("病案号为：" + list.getInpNo() + "出院时间为:" + list.getDischargeDateTime() + "的病历找不到。");
                    continue;
                }
                //组织导出文件名
                //fileName = exportFlieName(list);
                out = new ByteArrayOutputStream();
                Boolean aBoolean = imageToPdf1(filePathList, out, emrPdfWaterSet);
                //Boolean aBoolean = imageToPdf(filePathList, fileName,exportPdfPath);
                //为true时修改任务状态1完成2失败
                if (aBoolean) {
                    exportTaskDetailsMapper.upStatc(1, list.getId());
                    String inpNo = list.getInpNo();
                    String dischargeDateTime = list.getDischargeDateTime();
                    //格式化日期
                    String disDateStr = dischargeDateTime.substring(0, 4) + dischargeDateTime.substring(5, 7) + dischargeDateTime.substring(8, 10);
                    String pdfNameStr = inpNo + "_" + disDateStr;
                    //每个文件名
                    String filePdfName = flieName + "_" + pdfNameStr;
                    zos.putNextEntry(new ZipEntry(filePdfName + ".pdf"));

                    byte[] file1 = out.toByteArray();       //这个zip文件的字节
                    bis = new BufferedInputStream(new ByteArrayInputStream(file1));
                    //输出
                    int len = 0;
                    byte[] buf = new byte[1024 * 1024];
                    while ((len = bis.read(buf, 0, buf.length)) != -1) {
                        bos.write(buf, 0, len);
                    }

                } else {
                    exportTaskDetailsMapper.upStatc(2, list.getId());
                    logger.log("病案号为：" + list.getInpNo() + "出院时间为:" + list.getDischargeDateTime() + "的病历保存失败。");
                }
            }
        } catch (Exception e) {
            ExceptionPrintUtil.printException(e);
            e.printStackTrace();
        } finally {
            try {
                if (null != bos) {
                    bos.flush();
                    bos.close();
                }
                if (null != bis) {
                    bis.close();
                }
                out.flush();
                out.close();
                if (null != zos) {
                    zos.flush();
                    zos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "下载完成";
    }


    public Boolean imageToPdf1(List<ExportDetailsVo> scanPathVos, ByteArrayOutputStream bos, EmrPdfWaterSet pdfWaterSet) {
        //ByteArrayOutputStream bos = null;
        FileOutputStream fileOutputStream = null;
        PdfWriter writer = null;
        try {
            //bos = new ByteArrayOutputStream();
            Document document = new Document(PageSize.A4, 0, 0, 0, 0); //创建文档容器
            //fileOutputStream = new FileOutputStream(exportPdfPath + fileName + ".pdf");
            //writer = PdfWriter.getInstance(document, fileOutputStream);//创建编写器（PDF类型）
            //是否启用水印
            writer = PdfWriter.getInstance(document, bos);
            //上一个目录名称
            String lastOutline = null;
            //是否增加标签
            boolean outFlag = true;
            //标签顺序
            Integer outNum = 1;
            // 添加目录
            document.open(); //打开容器
            float w, h;
            PdfContentByte cb = writer.getDirectContent();
            cb.setFontAndSize(BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 12);
            cb.beginText();
            cb.showTextAligned(PdfContentByte.ALIGN_CENTER, "目录", 300, 780, 0);
            cb.endText();
            // 创建目录
            PdfOutline root = cb.getRootOutline();
            // 添加图片到PDF
            for (int i = 0; i < scanPathVos.size(); i++) {
                try {
                    String assortName = scanPathVos.get(i).getAssortName();
                    if (StringUtils.isNotBlank(lastOutline) && lastOutline.equals(assortName)) {
                        outFlag = false;
                    }
                    if (StringUtils.isBlank(lastOutline)) {
                        lastOutline = assortName;
                        outFlag = true;
                    }
                    if (!lastOutline.equals(assortName)) {
                        lastOutline = assortName;
                        outFlag = true;
                    }
                    String imagePath = scanPathVos.get(i).getFilePath();

                    Image image = Image.getInstance(imagePath);
                    /*处理图片缩放比例*/
                    w = image.getWidth();
                    h = image.getHeight();
                    image.setAlignment(com.lowagie.text.Image.ALIGN_CENTER);
                    image.scaleAbsolute(PageSize.A4.getWidth(), PageSize.A4.getWidth() * (h / w));
                    // 创建新页面并添加图片
                    if (i != 0) {
                        document.newPage();
                    }
                    document.add(image);
                    if (outFlag) {
                        System.out.println();
                        //目录跳转页面内容设置。
                        PdfAction action = PdfAction.gotoLocalPage(i + 1, new PdfDestination(PdfDestination.FIT), writer);
                        //标题目录
                        String title = outNum + "." + scanPathVos.get(i).getAssortName();
                        new PdfOutline(root, action, title, false);
                        outNum++;
                    }

                } catch (Exception e) {
                    logger.log("导出失败" + scanPathVos.get(i).getFilePath() + e.getMessage());
                    e.printStackTrace();
                }
            }
            document.close();
            //是否启用水印
            Short effective = pdfWaterSet.getDownloadEffective();
            Short isImg = pdfWaterSet.getDownloadIsImg();
            if (effective == 1 || isImg == 1) {
                img2PdfUtil.addWaterMark(bos, null, pdfWaterSet.getUpOrUnder(), pdfWaterSet.getTransparent(),
                        pdfWaterSet.getText(), pdfWaterSet.getTextX(), pdfWaterSet.getTextY(),
                        pdfWaterSet.getTextColor(), pdfWaterSet.getTextSize(), pdfWaterSet.getTextRotation(),
                        effective, isImg, pdfWaterSet.getImgFile(), pdfWaterSet.getImgWidth(),
                        pdfWaterSet.getImgHeight(), pdfWaterSet.getImgX(), pdfWaterSet.getImgY());
            }
        } catch (Exception e) {
            logger.log(e + "");
            ExceptionPrintUtil.printException(e);
            e.printStackTrace();
            return false;
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }

                if (bos != null) {
                    bos.flush();
                    bos.close();
                }

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