package com.emr.service.ipml;


import cn.org.bjca.seal.esspdf.client.message.ChannelMessage;
import cn.org.bjca.seal.esspdf.client.message.RectangleBean;
import cn.org.bjca.seal.esspdf.client.tools.AnySignClientTool;
import cn.org.bjca.seal.esspdf.client.utils.ClientUtil;
import com.emr.dao.ArchiveDetailCaCopyMapper;
import com.emr.dao.Archive_Detail_ca_reqParamMapper;
import com.emr.dao.CaSignatureMapper;
import com.emr.dto.Archive_DetailPdfPathDto;
import com.emr.entity.Archive_Detail_caSign;
import com.emr.entity.Archive_Detail_ca_reqParam;
import com.emr.service.Archive_DetailService;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfReader;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author 曾文和
 * @description: ca签章类
 * @createTime 2023/7/25 10:27
 */
@Service
@EnableAsync
@Slf4j
public class CaSignServiceImpl {
    AnySignClientTool anySignClientTool = null;
    @Value("${caServerIp}")
    private String caServerIp;
    @Value("${caServerPort}")
    private int caServerPort;
    @Value("${signNo}")
    private String signNo;
    @Value("${isCaOpen}")
    private int isCaOpen;
    @Value("${caCopyPath}")
    private String caCopyPath;
    @Value("${newPdfPath}")
    private String newPdfPath;
    @Resource
    private Archive_DetailService archiveDetailService;
    @Resource
    private Archive_Detai_CaSignServiceImpl archiveDetaiCaSignService;
    @Resource
    private Archive_Detail_ca_reqParamMapper archiveDetailCaReqParamMapper;
    @Resource
    private CaSignatureMapper caSignatureMapper;
    @Resource
    private ArchiveDetailCaCopyMapper archiveDetailCaCopyMapper;

    /**
     * @Description: caSignByMasterId方法是根据masterId查询所有文件进行ca签章
     * @param: [masterId]
     * @return: void
     * @author 曾文和
     * @createTime 2023/7/25 15:52
     */
    @Async
    public void caSignByMasterId(String masterId) {
        if (isCaOpen == 0) {
            return;
        }
        //根据masterId查询文件集合
        try {
            List<Archive_DetailPdfPathDto> pdfPathList = archiveDetailService.getPdfPathByMasterId(masterId);
            if (!CollectionUtils.isEmpty(pdfPathList)) {
                //保存文件表数据list
                List<Archive_DetailPdfPathDto> list=new ArrayList<>();
                //签章后保存目录
                String newPath = newPdfPath + File.separator + masterId;
                //没有目录创建目录
                if (!new File(newPath).isDirectory()) {
                    new File(newPath).mkdirs();
                }
                //查询签章位置比例
                Archive_Detail_ca_reqParam caReqParam = archiveDetailCaReqParamMapper.selectAll();
                //定义此次需要签章的文件id集合
                List<String> idList = new ArrayList<>();
                //签章失败文件id集合
                List<String> failIdList = new ArrayList<>();
                //遍历文件集合
                for (Archive_DetailPdfPathDto dto : pdfPathList) {
                    //获取文件路径
                    String pdfPath = dto.getPdfPath();
                    File file = new File(pdfPath);
                    if (file.isFile()) {
                        SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMddHHmmssSSS");
                        //获取今天日期
                        String todayDate = fmt.format(new Date());
                        //签章后地址
                        String newpdfPath = newPath + File.separator + todayDate+".pdf";
                        backupsPdf(pdfPath,newpdfPath);
                        //进行签章
                        boolean isSign = caSign(newpdfPath, caReqParam);
                        if (isSign) {
                            idList.add(dto.getId());
                            dto.setPdfPath(newpdfPath);
                        } else {
                            failIdList.add(dto.getId());
                            dto.setPdfPath(newpdfPath);
                        }
                    }
                    list.add(dto);
                }
                //添加签章记录
                updateCaFileState(idList, failIdList, masterId);
                //签章完后保存新的文件表
                archiveDetailCaCopyMapper.addArchiveDetailCaCopyMapper(list);
                //签章完成后保存状态
                caSignatureMapper.addCaSignature(masterId, 1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private void  backupsPdf(String pdfPath,String newpdfPath){
        try (InputStream inputStream = new FileInputStream(pdfPath);
             OutputStream outputStream = new FileOutputStream(newpdfPath)) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description: updateCaFileState方法是更新ca签章
     * @param: [idList, masterId]
     * @return: void
     * @author 曾文和
     * @createTime 2023/7/25 16:19
     */
    private void updateCaFileState(List<String> idList, List<String> failIdList, String masterId) {
        if (!CollectionUtils.isEmpty(idList)) {
            //先删除原有签章记录
            archiveDetaiCaSignService.deletesFromMasterId(masterId);
            //后新增
            List<Archive_Detail_caSign> list = new ArrayList<>();
            Date date = new Date();
            for (String id : idList) {
                Archive_Detail_caSign obj = new Archive_Detail_caSign();
                obj.setArchiveDetailId(id);
                obj.setMasterId(masterId);
                obj.setSignTime(date);
                obj.setCaStatic(1);
                list.add(obj);
            }
            if (!CollectionUtils.isEmpty(failIdList)) {
                for (String id : failIdList) {
                    Archive_Detail_caSign obj = new Archive_Detail_caSign();
                    obj.setArchiveDetailId(id);
                    obj.setMasterId(masterId);
                    obj.setSignTime(date);
                    obj.setCaStatic(2);
                    list.add(obj);
                }
            }
            //批量新增
            archiveDetaiCaSignService.insertBatchCaSign(list);
        }
    }

    /**
     * @Description: caCopyFile方法是备份ca前文件
     * @param: [pdfPath]
     * @return: void
     * @author 曾文和
     * @createTime 2023/7/25 15:51
     */
    private void caCopyFile(String pdfPath, String todayDate, String masterId) {
        String newPath = caCopyPath + File.separator + todayDate + File.separator + masterId;
        if (!new File(newPath).isDirectory()) {
            new File(newPath).mkdirs();
        }
        String newSrc = newPath + File.separator + new File(pdfPath).getName();
        try (InputStream inputStream = new FileInputStream(pdfPath);
             OutputStream outputStream = new FileOutputStream(newSrc)) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            System.out.println("文件拷贝完成");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description: caSign方法是根据pdf文件路径调用ca接口进行每页签章
     * @param: [fileSrc]
     * @return: void
     * @author 曾文和
     * @createTime 2023/7/25 10:30
     *
     * z:docus/caTemp/masterId/病案首页
     */
    private boolean caSign(String newpdfPath, Archive_Detail_ca_reqParam caReqParam) throws Exception {
        //定义是否成功
        boolean flag = false;
        PdfReader pdfReader = null;
        try {
            pdfReader = new PdfReader(newpdfPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (pdfReader != null) {
            try {
                anySignClientTool = new AnySignClientTool(caServerIp, caServerPort);
                File file = new File(newpdfPath);
                byte[] pdfBty = ClientUtil.readFileToByteArray(file);
                //pdf验章
                ChannelMessage messageExist = anySignClientTool.pdfVerify(pdfBty);
                if (!StringUtils.isEmpty(messageExist.getStatusInfo()) && "pdf文档未签章".equals(messageExist.getStatusInfo())) {
                    RectangleBean bean = new RectangleBean();
                    int numberOfPages = pdfReader.getNumberOfPages();
                    for (int i = 0; i < numberOfPages; i++) {
                        if (i != 0) {
                            pdfBty = ClientUtil.readFileToByteArray(file);
                        }
                        bean.setPageNo(i + 1);
                        ChannelMessage message = null;
                        //获取pdf的高宽
                        Rectangle pageSize = pdfReader.getPageSizeWithRotation(i + 1);
                        // 获取页面的宽度和高度
                        float width = pageSize.getWidth();
                        float height = pageSize.getHeight();
                        System.out.println("pdf尺寸：width:" + width + "，height:" + height);
                        bean.setLeft(Float.valueOf(width - caReqParam.getSignLeft()));
                        bean.setTop(Float.valueOf(caReqParam.getSignTop()));
                        bean.setRight(Float.valueOf(width));
                        bean.setBottom(Float.valueOf(caReqParam.getSignBottom()));
                        System.out.println("左：" + bean.getLeft() + "，上：" + bean.getTop() + ",右：" + bean.getRight() + ",下:" + bean.getBottom());
                        message = anySignClientTool.pdfSignByParam(pdfBty, signNo, bean);
                        if ("200".equals(message.getStatusCode())) {//成功
                            ClientUtil.writeByteArrayToFile(new File(newpdfPath), message.getBody());
                            System.out.println("签章成功");
                        } else {
                            String statusCode = message.getStatusCode();
                            String statusInfo = message.getStatusInfo();
                            log.error("statusCode=" + statusCode + ";statusInfo=" + statusInfo);
                        }
                    }
                }
                flag = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            log.error("进行签章pdf：" + newpdfPath + "不存在或损坏");
        }
        System.out.println("完成");
        return flag;
    }
}
