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.CaDepartIdMapper;
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.entity.Power_User;
import com.emr.service.Archive_DetailService;
import com.emr.util.Msg;
import com.emr.vo.CaDepartIdVo;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfReader;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
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 okhttp3.*;

import javax.annotation.Resource;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.List;

/**
 * @author 曾文和
 * @description: ca签章类
 * @createTime 2023/7/25 10:27
 */

@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;
    @Resource
    private CaDepartIdMapper caDepartIdMapper;
    @Value("${synDepartUrl}")
    private String synDepartUrl;
    @Value("${signUrl}")
    private String signUrl;

    @Value("${clientId}")
    private String clientId;
    @Value("${clientSecret}")
    private String clientSecret;

    /**
     * @Description: caSignByMasterId方法是根据masterId查询所有文件进行ca签章
     * @param: [masterId]
     * @return: void
     * @author 曾文和
     * @createTime 2023/7/25 15:52
     */
    public Msg caSignByMasterId(String masterId, Power_User user) {
        if (isCaOpen == 0) {
            return Msg.success();
        }
        //根据masterId查询文件集合
        try {
            List<Archive_DetailPdfPathDto> pdfPathList = archiveDetailService.getPdfPathByMasterId(masterId);
            if (!CollectionUtils.isEmpty(pdfPathList)) {
                //判断该部门是否存在签章
                CaDepartIdVo caDepartIdVo = caDepartIdMapper.getDepartId(user.getRemark());
                //没有保存部门签章id时需要请求获取一个新的departId
                if (caDepartIdVo==null){
                    //请求医院科室在医网信标识id
                    String departId = getDepartId(user);
                    caDepartIdMapper.addDepartId(user.getRemark(),departId);
                    return Msg.fail("该用户科室没有在医信网平台申请部门签章请联系医信网人员");
                }
                if (StringUtils.isBlank(caDepartIdVo.getDataId())) {
                    return Msg.fail("部门标识为空");
                }
                String dataId = caDepartIdVo.getDataId();
                //保存文件表数据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) {
                    SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMddHHmmssSSS");
                    //获取今天日期
                    String todayDate = fmt.format(new Date());
                    //签章后地址
                    String newPdfPath = newPath + File.separator + todayDate+".pdf";
                    //获取文件路径
                    String pdfPath = dto.getPdfPath();
                    File file = new File(pdfPath);
                    if (file.isFile()) {
                        String pdfPathString = pdfToBase64(pdfPath);
                        PdfReader pdfReader = new PdfReader(pdfPath);
                        int pageCount = pdfReader.getNumberOfPages();
                        Msg msg = sign(pdfPathString, dataId,caReqParam,pageCount);
                        if (msg.getCode()!=100){
                            return Msg.fail();
                        }
                        String newPdfPathBase64 = msg.getMsg();
                        if (!convertBase64ToPdf(newPdfPathBase64, newPdfPath)){
                            return Msg.fail();
                        }
                        dto.setPdfPath(newPdfPath);
                    } else {
                        return Msg.fail();
                    }
                    list.add(dto);
                }
                //添加签章记录
                updateCaFileState(idList, failIdList, masterId);
                //判断是否存在，存在在先删除
                int caMasterId = caSignatureMapper.getCaMasterId(masterId, 1);
                if (caMasterId > 0) {
                    archiveDetailCaCopyMapper.updateByMasterID(masterId);
                    caSignatureMapper.delCaMasterId(masterId);
                }
                //签章完后保存新的文件表
                archiveDetailCaCopyMapper.addArchiveDetailCaCopyMapper(list);
                //签章完成后保存状态
                caSignatureMapper.addCaSignature(masterId, 1);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Msg.fail("请求失败");
        }
        return Msg.success();
    }

    //将pdf文件base64方法
    public static String pdfToBase64(String filePath) throws IOException {
        File file = new File(filePath);
        // 读取文件内容到字节数组
        byte[] fileContent = Files.readAllBytes(file.toPath());
        // 将字节数组编码为Base64字符串
        return Base64.getEncoder().encodeToString(fileContent);

    }
    //将base64转为pdf方法
    public Boolean convertBase64ToPdf(String base64String, String filePath) {
        try {
            // 解码Base64字符串
            byte[] decodedBytes = Base64.getDecoder().decode(base64String);

            // 将解码后的数据写入PDF文件
            try (FileOutputStream fos = new FileOutputStream(filePath)) {
                fos.write(decodedBytes);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
    //签章接口
    private Msg sign(String pdfPathString,String departId,Archive_Detail_ca_reqParam caReqParam,int pageCount) {
        // 创建OkHttpClient实例
        OkHttpClient client = new OkHttpClient();
        // 定义请求的URL
        String url = signUrl;
        String pdfSignBase64="";
        // 创建请求体
        String json = "{"
                + "\"head\": {"
                + "\"clientId\": \"" + clientId + "\","
                + "\"clientSecret\": \"" + clientSecret + "\","
                + "},"
                + "\"body\": {"
                + "\"pdfBase64\":  \"" + pdfPathString + "\","
                + "\"departId\":  \"" + departId + "\","
//                + "\"keyword\": \"医师签名\","
//                + "\"moveType\": \"1\","
//                + "\"searchOrder\": \"2\","
//                + "\"scale\": \"0.4\","
//                + "\"fileType\": \"2\","
                + "\"positionType\": \"1\","
                + "\"x\": \"" + caReqParam.getSignTop() + "\","
                + "\"y\":  \"" + caReqParam.getSignLeft() + "\","
                + "}"
                + "}";
        // 创建RequestBody
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);

        // 创建Request
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        try {
            // 执行请求
            Response response = client.newCall(request).execute();

            // 检查响应状态码
            if (response.isSuccessful()) {
                // 获取响应体
                String responseData = response.body().string();

                // 解析JSON响应
                JSONObject jsonResponse = new JSONObject(responseData);

                // 获取返回的参数
                pdfSignBase64 = jsonResponse.getJSONObject("data").getString("pdfSignBase64");
                String status = jsonResponse.getString("status");
                if (!status.equals("0")){
                    return Msg.fail("请求失败");
                }
            } else {
                System.out.println("请求失败，状态码：" + response.code());
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Msg.fail();
        }
        return Msg.success(pdfSignBase64);
    }

    //请求医信网标识id
    private String getDepartId(Power_User user) {
        // 创建OkHttpClient实例
        OkHttpClient client = new OkHttpClient();

        // 定义请求的URL
        String url = synDepartUrl;
        String dataId = "";
        // 创建请求体
        String json = "{"
                + "\"head\": {"
                + "\"clientId\": \"" + clientId + "\","
                + "\"clientSecret\": \"" + clientSecret + "\","
                + "},"
                + "\"body\": {"
                + "\"thirdDepartId\": \"3040000\","
                + "\"departName\": \"病案室\","
                + "\"departPhone\":  \"" + user.getUserEmail() + "\","
                + "\"departPerson\": \"" + user.getUserPosition() + "\","
                + "\"clientOrgCode\": \"BAS\","
                + "\"clientOrgType\": \"ORG\""
                + "}"
                + "}";

        // 创建RequestBody
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);

        // 创建Request
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();

        try {
            // 执行请求
            Response response = client.newCall(request).execute();

            // 检查响应状态码
            if (response.isSuccessful()) {
                // 获取响应体
                String responseData = response.body().string();

                // 解析JSON响应
                JSONObject jsonResponse = new JSONObject(responseData);

                // 获取返回的参数
                dataId = jsonResponse.getJSONObject("data").getString("departId");
                String message = jsonResponse.getString("message");
                String status = jsonResponse.getString("status");
                boolean successful = jsonResponse.getBoolean("successful");

                // 输出解析结果
                System.out.println("DepartId: " + dataId);
                System.out.println("Message: " + message);
                System.out.println("Status: " + status);
                System.out.println("Successful: " + successful);
            } else {
                System.out.println("请求失败，状态码：" + response.code());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dataId;
    }

    /**
     * @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);
        }
    }

}
