package com.bcxin.backend.domain.signature.service.impls;

import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bcxin.backend.core.utils.ExceptionUtils;
import com.bcxin.backend.core.utils.JsonUtil;
import com.bcxin.backend.domain.enums.HnCertCatalog;
import com.bcxin.backend.domain.models.Result;
import com.bcxin.backend.domain.models.SignatureQueuesDTO;
import com.bcxin.backend.domain.repositories.SignatureQueuesRepository;
import com.bcxin.backend.domain.services.impls.ConvertServiceImpl;
import com.bcxin.backend.domain.signature.service.QzSignatureStrategy;
import com.bcxin.backend.domain.utils.FileUtils;
import com.bcxin.backend.domain.utils.JwtUtil;
import com.google.common.collect.Maps;
import io.jsonwebtoken.lang.Collections;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Paths;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@Service
public class HuNanInSignatureToPDFCompare implements QzSignatureStrategy {

    private final SignatureQueuesRepository signatureQueuesRepository;
    @Value("${myapps.domain.url}")
    String urlHead;
    @Value("${myapps.signature.tempPDF}")
    String tempPDF;
    @Value("${myapps.signature.mobanPDF}")
    String mobanPDF;
    @Value("${myapps.signature.cgiApi}")
    String cgiApi;
    @Value("${myapps.storage.root}")
    String rootPath;
    @Value("${myapps.supervise.target-app}")
    String targetApp;
    @Autowired
    private ConvertServiceImpl convertService;

    //token生成jwt字符串存（计算过期时间）
    private static String jwt_token = "";

    //base64前缀
    private static final String BASE64_PREFIX="data:image/png;base64,";

    private static final String XML_TEMPLATE =
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
                    + "<license>"
                    + "<catalog catalogId=\"%s\" catalogName=\"%s\" templateId=\"%s\" templateName=\"%s\" version=\"%s\"/>"
                    + "<surface>"
                    + "<item alias=\"holderCodeType\" code=\"certificateHolderTypeCode\" name=\"证件类型\" require=\"1\" value=\"\"/>"
                    + "<item alias=\"issueUnitname\" catetype=\"0\" code=\"certificateIssuingAuthorityName\" name=\"颁证单位\" require=\"1\" type=\"banzhengdanwei\" value=\"\"/>"
                    + "<item alias=\"licenseNumber\" catetype=\"0\" code=\"certificateNumber\" name=\"证照编号\" require=\"1\" type=\"string\" value=\"\"/>"
                    + "<item alias=\"issueDate\" catetype=\"0\" code=\"certificateIssuedDate\" dateFormat=\"yyyy-MM-dd\" name=\"颁证时间\" require=\"1\" type=\"riqi\" value=\"\"/>"
                    + "<item alias=\"validTimeBegin\" catetype=\"0\" code=\"certificateEffectiveDate\" dateFormat=\"yyyy-MM-dd\" name=\"有效期（起始）\" require=\"1\" type=\"riqi\" value=\"\"/>"
                    + "<item alias=\"holder\" catetype=\"0\" code=\"certificateHolderName\" name=\"持证者\" require=\"1\" type=\"string\" value=\"\"/>"
                    + "<item alias=\"validTimeEnd\" catetype=\"0\" code=\"certificateExpiringDate\" dateFormat=\"yyyy-MM-dd\" name=\"有效期（截止）\" require=\"1\" type=\"riqi\" value=\"\"/>"
                    + "<item alias=\"holderCode\" catetype=\"0\" code=\"certificateHolderCode\" name=\"证件号码\" require=\"1\" type=\"string\" value=\"\"/>"
                    + "<item alias=\"csny\" catetype=\"1\" code=\"KZ_csny\" dateFormat=\"yyyy-MM-dd\" name=\"出生年月\" require=\"1\" type=\"riqi\" value=\"\"/>"
                    + "<item alias=\"zz\" catetype=\"1\" code=\"KZ_zz\" name=\"住址\" require=\"1\" type=\"string\" value=\"\"/>"
                    + "<item alias=\"zp\" catetype=\"1\" code=\"KZ_zp\" fileName=\"\" name=\"照片\" require=\"1\" type=\"tupian\" value=\"\"/>"
                    + "<item alias=\"MJXM\" catetype=\"1\" code=\"KZ_MJXM\" name=\"民警姓名\" require=\"1\" type=\"string\" value=\"\"/>"
                    + "<item alias=\"MJSFZHM\" catetype=\"1\" code=\"KZ_MJSFZHM\" name=\"民警身份证号码\" require=\"1\" type=\"string\" value=\"\"/>"
                    + "<item alias=\"MJJH\" catetype=\"1\" code=\"KZ_MJJH\" name=\"民警警号\" require=\"0\" type=\"string\" value=\"\"/>"
                    + "<item alias=\"YHID\" catetype=\"1\" code=\"KZ_YHID\" name=\"用户Id\" require=\"1\" type=\"string\" value=\"\"/>"
                    + "<item alias=\"EWM\" catetype=\"1\" code=\"KZ_EWM\" name=\"二维码\" require=\"1\" type=\"p_qrcode\" value=\"\"/>"
                    + "</surface>"
                    + "</license>";

    @Autowired
    @Qualifier("primaryJdbcTemplate")
    protected JdbcTemplate jdbcTemplate;

    public HuNanInSignatureToPDFCompare(SignatureQueuesRepository signatureQueuesRepository) {
        this.signatureQueuesRepository = signatureQueuesRepository;
    }

    private String getToken(){
        String token = "";
        if(StringUtils.isEmpty(jwt_token)||!JwtUtil.isTokenExpired(jwt_token)){
            token = HuNanECUtil.getToken(cgiApi);
            jwt_token = JwtUtil.createJWT(token);
        }else{
            token = JwtUtil.parseData(jwt_token);
        }

        return token;
    }


    @Override
    public void cerSignatureQueues() {
        System.err.println("====> 证书过滤生成有效签章记录 定时任务开始：cerSignatureQueues star................");
        String sqlQId = " select a.id from tlk_Certificate a where a.ITEM_signatured_processed_status IN (0) and a.ITEM_CERTIFICATETYPE='1' and a.ITEM_isCertified != '0' and instr(a.item_certificatefrom,'湘潭') order by item_certificateDate desc, ITEM_signatured_time desc limit 300";
        List<String> strList = jdbcTemplate.query(sqlQId, new RowMapper<String>() {
            @Override
            public String mapRow(ResultSet rs, int rowNum) throws SQLException {
                return rs.getString("id");
            }});
        if(strList.size() == 0){
            return;
        }
        String dupsql ="";
        String dupsql2 ="";
        String dupsql3 ="";
        String dupsql4 ="";
        String dupsql5 ="";
        String upsql ="";
        String insql ="";
        String insql2 ="";
        String insql3 ="";
        String insql4 ="";
        String insql5 ="";
        String operator = "";//getWebUser().getName();

        String now = DateUtil.today();
        String array = "(";
        for (String str : strList) {
            array+="'";
            array+=str;
            array+="',";
        }
        array = array.substring(0,array.length()-1);
        array += ")";
        String sql = "select id,item_securityname,item_documentid,item_idaddress,item_certificateno,item_certificatefrom,item_certificatedate,item_headphoto,created,item_signatured_processed_status from tlk_certificate where id in "+array+"";
        System.out.println(sql);
        List<Map<String,String>> list = jdbcTemplate.query(sql,new RowMapper<Map<String,String>>() {
            @Override
            public Map<String,String> mapRow(ResultSet rs, int rowNum) throws SQLException {
                Map<String,String> map = Maps.newHashMap();
                map.put("id", rs.getString("id"));
                map.put("item_securityname", rs.getString("item_securityname"));
                map.put("item_documentid", rs.getString("item_documentid"));
                map.put("item_idaddress", rs.getString("item_idaddress"));
                map.put("item_certificateno", rs.getString("item_certificateno"));
                map.put("item_certificatefrom", rs.getString("item_certificatefrom"));
                map.put("item_certificatedate", rs.getString("item_certificatedate"));
                map.put("item_headphoto", rs.getString("item_headphoto"));
                map.put("created", rs.getString("created"));
                map.put("item_signatured_processed_status", rs.getString("item_signatured_processed_status"));
                return map;
            }});
        if(list.size()>0){
            dupsql = "UPDATE tlk_certificate SET ITEM_signatured_processed_status = 3,ITEM_last_signatured_processed_result = '证书信息不全' WHERE id in(";
            dupsql2 = "UPDATE tlk_certificate SET ITEM_signatured_processed_status = 3,ITEM_last_signatured_processed_result = '身份证信息无效' WHERE id in(";
            dupsql3 = "UPDATE tlk_certificate SET ITEM_signatured_processed_status = 3,ITEM_last_signatured_processed_result = '证书信息不全（身份证住址）' WHERE id in(";
            dupsql4 = "UPDATE tlk_certificate SET ITEM_signatured_processed_status = 3,ITEM_last_signatured_processed_result = '证书信息不全（身份证头像）' WHERE id in(";
            dupsql5 = "UPDATE tlk_certificate SET ITEM_signatured_processed_status = 3,ITEM_last_signatured_processed_result = '证书信息不全（身份证头像、身份证住址）' WHERE id in(";
            upsql = "UPDATE tlk_certificate SET ITEM_last_signatured_processed_result = '',ITEM_signatured_processed_status = 1,ITEM_signatured_operator = '"+operator+"',ITEM_signatured_time = now(),ITEM_CERTIFICATEDATE = IFNULL(ITEM_CERTIFICATEDATE, NOW()) WHERE id in(";
            insql = "INSERT INTO obpm2_security.signature_queues (template_url,DATA,STATUS,business_id,createdTime,creator,certificatedate)VALUES";
            insql2 = "INSERT INTO obpm2_security.signature_queues (template_url,DATA,STATUS,business_id,createdTime,creator,certificatedate)VALUES";
            insql3 = "INSERT INTO obpm2_security.signature_queues (template_url,DATA,STATUS,business_id,createdTime,creator,certificatedate)VALUES";
            insql4 = "INSERT INTO obpm2_security.signature_queues (template_url,DATA,STATUS,business_id,createdTime,creator,certificatedate)VALUES";
            insql5 = "INSERT INTO obpm2_security.signature_queues (template_url,DATA,STATUS,business_id,createdTime,creator,certificatedate)VALUES";
            int i = 0;
            for(Map<String,String> map1 : list){
                i+=1;
                String created = map1.get("created");
                String securityname = map1.get("item_securityname");
                String documentid = map1.get("item_documentid");
                String IdAddress = map1.get("item_idaddress");
                String certificateno = map1.get("item_certificateno");
                String certificatefrom = map1.get("item_certificatefrom");
                String certificatedate = map1.get("item_certificatedate");
                String headphoto = map1.get("item_headphoto");
                String signaturestatus = map1.get("item_signatured_processed_status");
                String id = map1.get("id");
                if(StringUtils.isEmpty(signaturestatus)){
                    continue;
                }
                signaturestatus = signaturestatus.contains(".")?signaturestatus.split(".")[0]:signaturestatus;
                if(StringUtils.isEmpty(created)){
                    created = DateUtil.today();
                }
                boolean boolean1 = true;
                if(StringUtils.isNotEmpty(documentid)){
                    if(documentid.length()!=18){
                        boolean1 = false;
                    }
                }
                boolean boolean2 = true;
                boolean boolean3 = true;
                boolean boolean4 = true;
                String IdAddressTemp = IdAddress;
                IdAddress = StringUtils.isNotEmpty(IdAddress)?IdAddress.trim():IdAddress;
                if(StringUtils.isEmpty(IdAddress)){
                    boolean2 = false;
                }else{
                    IdAddress = IdAddress.replace("，","");
                    boolean endsWithRegion = IdAddress.endsWith("省")?true:IdAddress.endsWith("市")?true:IdAddress.endsWith("区")?true:IdAddress.endsWith("县")?true:false;
                    if(endsWithRegion){
                        boolean3 = false;
                    }else{
                        String[] arrAddr = IdAddressTemp.trim().split(" ");
                        if(arrAddr.length==2){
                            if(arrAddr[1].contains(arrAddr[0])){
                                IdAddress = arrAddr[1];
                            }else if(arrAddr[1].contains(arrAddr[0].substring(0,3))){
                                IdAddress = arrAddr[1];
                            }else if(arrAddr[1].contains(arrAddr[0].substring(0,2))){
                                IdAddress = arrAddr[1];
                            }
                            IdAddress = IdAddress.replace(" ", "");
                        }
                    }
                }
                if(StringUtils.isEmpty(headphoto)){
                    boolean2 = false;
                }else{
                    if(headphoto.contains("null")||headphoto.contains("b.photoUrl")){
                        boolean4 = false;
                    }
                }

                if(StringUtils.isNotEmpty(securityname) && StringUtils.isNotEmpty(documentid) && StringUtils.isNotEmpty(IdAddress) && StringUtils.isNotEmpty(certificateno) && StringUtils.isNotEmpty(certificatefrom) && StringUtils.isNotEmpty(headphoto) && boolean1){

                    if("0".equals(signaturestatus) || "3".equals(signaturestatus)){
                        String[] arrphoto = headphoto.split("originalPath");
                        String[] arrphoto1 = headphoto.split("uid");
                        if(arrphoto.length == 2){
                            headphoto = headphoto.replace("[","");
                            headphoto = headphoto.replace("]","");
                            JSONObject rtJsonStrData = JSONObject.parseObject(headphoto);
                            headphoto = rtJsonStrData.get("path")+"";
                        }else if(arrphoto1.length == 2){
                            headphoto = headphoto.replace("[","");
                            headphoto = headphoto.replace("]","");
                            JSONObject rtJsonStrData = JSONObject.parseObject(headphoto);
                            headphoto = rtJsonStrData.get("path")+"";
                        }
                        String year = documentid.substring(6, 10);
                        String month = documentid.substring(10, 12);
                        String day = documentid.substring(12, 14);
                        String moban = mobanPDF;

                        if(StringUtils.isEmpty(certificatedate)){
                            certificatedate = DateUtil.today();
                        }else{
                            certificatedate = DateUtil.format(DateUtil.parseDate(certificatedate), "yyyy-MM-dd");
                        }
                        String json = "{\"name\":\""+securityname+"\",\"address\":\""+IdAddress+"\",\"headphoto\":\""+headphoto+"\",\"idcardno\":\""+documentid+"\",\"year\":\""+year+"\",\"month\":\""+month+"\",\"day\":\""+day+"\",\"certificateno\":\""+certificateno+"\",\"certificatefrom\":\""+certificatefrom+"\",\"isSignature\":\"1\",\"fzDate\":\""+certificatedate+"\"}";

                        if(i<=200){
                            insql += "('"+moban+"','"+json+"',0,'"+id+"',NOW(),'"+operator+"','"+certificatedate+"'),";
                        }else if(i>200 && i<=400){
                            insql2 += "('"+moban+"','"+json+"',0,'"+id+"',NOW(),'"+operator+"','"+certificatedate+"'),";
                        }else if(i>400 && i<=600){
                            insql3 += "('"+moban+"','"+json+"',0,'"+id+"',NOW(),'"+operator+"','"+certificatedate+"'),";
                        }else if(i>600 && i<=800){
                            insql4 += "('"+moban+"','"+json+"',0,'"+id+"',NOW(),'"+operator+"','"+certificatedate+"'),";
                        }else{
                            insql5 += "('"+moban+"','"+json+"',0,'"+id+"',NOW(),'"+operator+"','"+certificatedate+"'),";
                        }
                        upsql += "'"+id+"'";
                        upsql += ",";
                    }
                }else{
                    if(!boolean1){
                        dupsql2 += "'"+id+"'";
                        dupsql2 += ",";
                    }else if(!boolean2){
                        dupsql5 += "'"+id+"'";
                        dupsql5 += ",";
                    }else if(!boolean3){
                        dupsql3 += "'"+id+"'";
                        dupsql3 += ",";
                    }else if(!boolean4){
                        dupsql4 += "'"+id+"'";
                        dupsql4 += ",";
                    }else{
                        dupsql += "'"+id+"'";
                        dupsql += ",";
                    }
                }
            }
        }
        if(!("INSERT INTO obpm2_security.signature_queues (template_url,DATA,STATUS,business_id,createdTime,creator,certificatedate)VALUES").equals(insql)){
            insql = insql.substring(0,insql.length()-1);
            jdbcTemplate.update(insql);
        }
        if(!("INSERT INTO obpm2_security.signature_queues (template_url,DATA,STATUS,business_id,createdTime,creator,certificatedate)VALUES").equals(insql2)){
            insql2 = insql2.substring(0,insql2.length()-1);
            jdbcTemplate.update(insql2);
        }
        if(!("INSERT INTO obpm2_security.signature_queues (template_url,DATA,STATUS,business_id,createdTime,creator,certificatedate)VALUES").equals(insql3)){
            insql3 = insql3.substring(0,insql3.length()-1);
            jdbcTemplate.update(insql3);
        }
        if(!("INSERT INTO obpm2_security.signature_queues (template_url,DATA,STATUS,business_id,createdTime,creator,certificatedate)VALUES").equals(insql4)){
            insql4 = insql4.substring(0,insql4.length()-1);
            jdbcTemplate.update(insql4);
        }
        if(!("INSERT INTO obpm2_security.signature_queues (template_url,DATA,STATUS,business_id,createdTime,creator,certificatedate)VALUES").equals(insql5)){
            insql5 = insql5.substring(0,insql5.length()-1);
            jdbcTemplate.update(insql5);
        }
        if(!("UPDATE tlk_certificate SET ITEM_last_signatured_processed_result = '',ITEM_signatured_processed_status = 1,ITEM_signatured_operator = '"+operator+"',ITEM_signatured_time = now(),ITEM_CERTIFICATEDATE = IFNULL(ITEM_CERTIFICATEDATE, NOW()) WHERE id in(").equals(upsql)){

            upsql = upsql.substring(0,upsql.length()-1);
            upsql += ");";
            jdbcTemplate.update(upsql);
        }
        if(!("UPDATE tlk_certificate SET ITEM_signatured_processed_status = 3,ITEM_last_signatured_processed_result = '证书信息不全' WHERE id in(").equals(dupsql)){
            dupsql = dupsql.substring(0,dupsql.length()-1);
            dupsql += ");";
            jdbcTemplate.update(dupsql);
        }
        if(!("UPDATE tlk_certificate SET ITEM_signatured_processed_status = 3,ITEM_last_signatured_processed_result = '身份证信息无效' WHERE id in(").equals(dupsql2)){
            dupsql2 = dupsql2.substring(0,dupsql2.length()-1);
            dupsql2 += ");";
            jdbcTemplate.update(dupsql2);
        }
        if(!("UPDATE tlk_certificate SET ITEM_signatured_processed_status = 3,ITEM_last_signatured_processed_result = '证书信息不全（身份证头像、身份证住址）' WHERE id in(").equals(dupsql5)){
            dupsql5 = dupsql5.substring(0,dupsql5.length()-1);
            dupsql5 += ");";
            jdbcTemplate.update(dupsql5);
        }
        if(!("UPDATE tlk_certificate SET ITEM_signatured_processed_status = 3,ITEM_last_signatured_processed_result = '证书信息不全（身份证住址）' WHERE id in(").equals(dupsql3)){
            dupsql3 = dupsql3.substring(0,dupsql3.length()-1);
            dupsql3 += ");";
            jdbcTemplate.update(dupsql3);
        }
        if(!("UPDATE tlk_certificate SET ITEM_signatured_processed_status = 3,ITEM_last_signatured_processed_result = '证书信息不全（身份证头像）' WHERE id in(").equals(dupsql4)){
            dupsql4 = dupsql4.substring(0,dupsql4.length()-1);
            dupsql4 += ");";
            jdbcTemplate.update(dupsql4);
        }
    }

    @Override
    public void cerPDF() {
        //后执行要创建签章中业务的逻辑
        createPDF();
    }

    /**
     * <b> 激活电子印章签验接口服务器完成签章 </b>
     * @author ZXF
     * @create 2022/11/21 0021 10:44
     * @version
     * @注意事项 </b>
     */
    private boolean activateXMPSignQuicklyExCGI() {
        StringBuilder sb = new StringBuilder();
        try {
            JSONObject json = new JSONObject();
            json.put("service", "wss://127.0.0.1:8800");
            json.put("sn", "2171101001009256");
            json.put("pin", "88888888");
            json.put("in", "/data/share/in");
            json.put("out", "/data/share/out");
            JSONArray arr = new JSONArray();
            JSONObject pos = new JSONObject();
            pos.put("centerX", 405);
            pos.put("centerY", 312);
            pos.put("page", 1);
            arr.add(pos);
            json.put("signOnPos", arr);
            String ret = HttpUtil.post(cgiApi, json.toJSONString());
            log.info("====> 电子签章定时任务开始.activateXMPSignQuicklyExCGI.ret：" + ret);
            if (StringUtils.isEmpty(ret)) {
                return false;
            }
            JSONObject result = JSON.parseObject(ret.replace("#", ""));
            if ("1".equals(String.valueOf(result.get("code")))) {
                return true;
            }
            return false;
        } catch (Exception e){
            log.info("====> 电子签章定时任务开始.activateXMPSignQuicklyExCGI message:"+e.getMessage());
        }
        return false;
    }

    /**
     * <b> 批量生成pdf文件 </b>
     * @author ZXF
     * @create 2022/10/31 0031 13:33
     * @version
     * @注意事项 </b>
     */
    private void createPDF() {
        System.err.println("====> 有效签章记录查询批量生成pdf文件 定时任务开始：createPDF star................");
        //1.查询签章队列表需要签章的数据
        Page<SignatureQueuesDTO> pageQueues = signatureQueuesRepository.pageQueues(0, PageRequest.of(0, 300));
        List<SignatureQueuesDTO> queues = pageQueues.getContent();
        //Collection<SignatureQueuesDTO> queues = pageQueues.getContent();
        if (Collections.isEmpty(queues)) {
            return;
        }
        System.err.println("====> 有效签章记录查询批量生成pdf文件 queues size："+queues.size()+" ................");
        for (SignatureQueuesDTO queuesDTO:queues) {
            accept(queuesDTO);
        }
    }

    public static void main(String[] args) {
        String con = "{\"address\":\"山西省河津市樊村镇干涧村\",\"certificateno\":\"京2023254021\",\"day\":\"15\",\"fzDate\":\"2023-07-18\",\"headphoto\":\"https://02obs.baibaodun.cn/2024/10-11/1172a4fc-9357-4370-ab7b-c99f69c07f1c/1728630228970.jpg\",\"idcardno\":\"140882200411150018\",\"isSignature\":\"1\",\"month\":\"11\",\"name\":\"史梓彬\",\"unSignaturePDF\":\"/uploads/pdf/dianziqianzhang/temp/queueId_205459.temp\",\"year\":\"2004\",\"zDay\":\"18\",\"zMonth\":\"07\",\"zYear\":\"2023\"}";
        SignatureData data = JSONObject.parseObject(con,SignatureData.class);
        System.out.println(createHtml(data,"长沙市公安局"));
        /*String imageUrl="https://v5qy.te.baibaodun.com.cn/obpm/uploads/2024/07-12/d028b2ba-471a-400b-8a14-8d2d27ecf22b/1720751301674.jpg";
        byte[] imageBytes = HttpUtil.downloadBytes(imageUrl);
        String base64Str = Base64Encoder.encode(imageBytes);
        System.out.println(base64Str);
        byte[] bytes = cn.hutool.core.codec.Base64.decode(base64Str);
        File file = new File("D:\\data\\lb002.jpg");
        try (FileOutputStream fos = new FileOutputStream(file)) {
            // 将字节数组写入文件
            fos.write(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }*/
        /*List<String> queues = new ArrayList<>();
        for (int i = 0; i < 101; i++) {
            queues.add(i+"");
        }
        //2.先判断一共查询了多少条，然后再判断要循环多少次
        int count = ((queues.size()) / 10);
        if(queues.size()%10!=0) {
            count += 1;
        }
        List<String> arrayList;
        //3.将查询到的数据通过每十条为一个线程的方式开启循环调生成pdf接口
        for (int i = 1; i <= count; i++) {
            arrayList = new ArrayList<>();
            for (int j = (i-1)*10; j < i*10; j++) {
                if(j==queues.size()){
                    break;
                }else{
                    arrayList.add(queues.get(j));
                }
            }
            System.out.println(arrayList);
        }
        System.out.println("count为："+count);*/
        //4.循环调生成pdf接口
        //queues.forEach(this::accept);
        /*JSONObject json = new JSONObject();
        json.put("service","wss://127.0.0.1:8800");
        json.put("sn","2171101001009256");
        json.put("pin","88888888");
        json.put("in","/data/share/in");
        json.put("out","/data/share/out");
        JSONArray arr = new JSONArray();
        JSONObject pos = new JSONObject();
        pos.put("centerX","369511");
        pos.put("centerY","488629");
        pos.put("page","1");
        arr.add(pos);
        json.put("signOnPos",arr);
        System.out.println(json.toJSONString());*/
        /*JSONObject j = new JSONObject();
        SignatureData data = new SignatureData();
        data.setName("张小国");
        data.setIdcardno("132302197104241418");
        data.setAddress("北京市市辖区朝阳区来广营臻园小区");
        data.setHeadphoto("https://02obs-file-system-obpm-uploads.obs.cn-north-1.myhuaweicloud.com/2022/10-12/c9a018e2-082a-4afa-b2d4-b761763dff08/1665571917323.jpg");
        data.setYear("1971");
        data.setMonth("04");
        data.setDay("24");
        data.setCertificateno("京2022112852");
        data.setZYear("2022");
        data.setZMonth("10");
        data.setZDay("26");
        j.put("tempUrl","https://bcxin-v5-prod.obs.cn-north-1.myhuaweicloud.com/uploads/2022/10-26/__MIFnVvYFZZjw5fN3OtS/1666772764122/qualicerttemp_zgz.html");
        j.put("formData",data);
        String result = HttpUtil.post("http://v5inmy.test.baibaodun.cn/kms/shared/convert/htmltopdf", j.toJSONString());
        System.out.println(result);*/
    }

    private void accept(SignatureQueuesDTO queue) {
        Long a = System.currentTimeMillis();
        SignatureData data = JSONObject.parseObject(queue.getData(),SignatureData.class);
        String selectSql = "SELECT a.name,b.number,e.AUTHOR author FROM obpm2_security.tenant_users a,obpm2_security.tenant_user_credentials b,obpm2_security.tenant_employees d,tlk_certificate e WHERE a.id=b.tenant_user_id AND b.credential_type=0 AND a.id=d.tenant_user_id AND d.`status`=0 AND d.id = e.AUTHOR AND e.id='"+queue.getBusiness_id()+"';";
        Map<String, Object> map = jdbcTemplate.queryForMap(selectSql);
        System.err.println("====> 电子签章定时任务开始.createPDF.accept.selectSql："+selectSql);
        System.err.println("====> 电子签章定时任务开始.createPDF.accept.map："+map);
        String infile = tempPDF+"/"+ DateUtil.today();
        String filename = System.currentTimeMillis()+"hnzgz_queueId_" + queue.getId() + ".ofd";
        String path = Paths.get(infile, filename).normalize().toString();
        String result = "";
        String message = "";
        String xml = handleXml(map,data,targetApp+path);// 报文
        Result ret = HuNanECUtil.xmlDataSend(cgiApi, xml, IdUtil.randomUUID(), getToken());
        if(Result.SUCCESS.equals(ret.getRetType())){
            result = ret.getData()+"";
            message = "资格证已申请，证书编码:"+result;
        }else{
            message = ret.getMsg();
        }
        System.err.println("====> 电子签章定时任务开始.createPDF.accept.message："+message);
        if(StringUtils.isNotEmpty(result)){
            //成功
            signatureQueuesRepository.updateSignature(3,new Date(),message,queue.getId());
        }else{
            //失败
            signatureQueuesRepository.updateSignature(2,new Date(),message,queue.getId());
        }
        System.err.println("====> 电子签章定时任务开始.createPDF.accept.单次生成文件耗时："+(System.currentTimeMillis()-a));
    }

    /**
     * xml 数据处理
     */
    private String handleXml(Map<String,Object> stringMap, SignatureData data,String previewUrl){
        System.err.println("====> 电子签章定时任务开始.createPDF.handleXml.previewUrl："+previewUrl);
        Document document = null;
        try {
            //获取模板数据
            HnCertCatalog cert = HnCertCatalog.getByAreaName(data.getCertificatefrom());
            if(cert == null){
                return "";
            }
            //填充模版数据
            String xml = String.format(XML_TEMPLATE, cert.getCatalogId(), cert.getCatalogName(), cert.getTemplateId(), cert.getTemplateName(), cert.getVersion());
            document = DocumentHelper.parseText(xml);
            Element rootElement = document.getRootElement();
            Element surface = rootElement.element("surface");
            List<Element> itemElementList = surface.elements("item");

            for (Element item : itemElementList) {
                String alias = item.attributeValue("alias");
                switch (alias) {
                    case "holderCodeType":
                        setItemValue(item, alias, "0"); // 证件类型 保安服务许可证是001
                        break;
                    case "issueUnitname":
                        setItemValue(item, alias, cert.getIssueUnitname()); // 颁证单位
                        break;
                    case "licenseNumber":
                        setItemValue(item, alias, data.getCertificateno()); // 证照编号
                        break;
                    case "issueDate":
                        setItemValue(item, alias, data.getFzDate()); // 颁证时间
                        break;
                    case "validTimeBegin":
                        setItemValue(item, alias, data.getFzDate()); // 有效期（起始）
                        break;
                    case "holder":
                        setItemValue(item, alias, data.getName()); // 持证者
                        break;
                    case "validTimeEnd":
                        setItemValue(item, alias, "长期"); // 有效期（截止）
                        break;
                    case "holderCode":
                        setItemValue(item, alias, data.getIdcardno()); // 证件号码
                        break;
                    case "csny":
                        setItemValue(item, alias, data.getYear() + "-" + data.getMonth() + "-" + data.getDay()); // 出生年月
                        break;
                    case "zz":
                        setItemValue(item, alias, data.getAddress()); // 住址
                        break;
                    case "zp":
                        String imageUrl = data.getHeadphoto();
                        if (imageUrl == null || imageUrl.isEmpty()) {
                            System.err.println("图片URL为空");
                            return "";
                        }
                        imageUrl = imageUrl.startsWith("http") ? imageUrl : urlHead + imageUrl;

                        String filename = "";
                        int lastSlashIndex = imageUrl.lastIndexOf('/');
                        if (lastSlashIndex != -1 && lastSlashIndex < imageUrl.length() - 1) {
                            filename = imageUrl.substring(lastSlashIndex + 1);
                        }
                        item.attribute("fileName").setValue(filename);

                        byte[] imageBytes = HttpUtil.downloadBytes(imageUrl);
                        String base64 = Base64Encoder.encode(imageBytes);
                        setItemValue(item, alias, base64); // 照片
                        break;
                    case "MJXM":
                        setItemValue(item, alias, stringMap.get("name") + ""); // 民警姓名
                        break;
                    case "MJSFZHM":
                        setItemValue(item, alias, stringMap.get("number") + ""); // 民警身份证号码
                        break;
                    case "MJJH":
                        setItemValue(item, alias, ""); // 民警警号
                        break;
                    case "YHID":
                        setItemValue(item, alias, stringMap.get("author") + ""); // 用户Id
                        break;
                    case "EWM":
                        String htmlContent = createHtml(data,cert.getIssueUnitname());
//                        String htmlContent = previewUrl;
                        setItemValue(item, alias, htmlContent); // 二维码
                        break;
                    default:
                        System.err.println("未知的项别名: " + alias);
                        break;
                }
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return document.asXML();
    }

    private void setItemValue(Element item, String alias, String value) {
        if (item.attributeValue("alias").equals(alias)) {
            item.attribute("value").setValue(value);
        }
    }

    public static String createHtml(SignatureData data, String issueUnitname){
        String toDay = data.getFzDate();
        if(StringUtils.isEmpty(toDay)){
            toDay = DateUtil.today();
        }
        String zDay = toDay.split("-")[2].substring(0,2);
        String gender = "";
        // 获取倒数第二位字符
        char c = data.getIdcardno().charAt(data.getIdcardno().length() - 2);
        int genderBit = Integer.parseInt(String.valueOf(c));
        // 判断奇偶数
        if (genderBit % 2 == 0) {
            gender = "女";
        } else {
            gender = "男";
        }
        String htmlContent = "证件编号："+data.getCertificateno()+"\n" +
                "姓   名："+data.getName()+"\n" +
                "性   别："+gender+"\n" +
                "出生年月："+data.getYear()+" 年 "+data.getMonth()+" 月 "+data.getDay()+" 日\n" +
                "身份证号："+data.getIdcardno()+"\n" +
                "住   址："+data.getAddress()+"\n" +
                "发证机关："+issueUnitname+"\n" +
                "发证日期："+toDay.split("-")[0]+" 年 "+toDay.split("-")[1]+" 月 "+zDay+" 日\n";
        return htmlContent;
    }

    private static String format(String content, Object formData) {
        net.sf.json.JSONObject data = net.sf.json.JSONObject.fromObject(formData);
        String pattern = "\\$\\{(.+?)\\}";
        Pattern p = Pattern.compile(pattern);
        Matcher m = p.matcher(content);
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            String key = m.group(1);
            Object value = data.get(key);
            m.appendReplacement(sb, value == null ? "" : value.toString());
        }
        m.appendTail(sb);
        return sb.toString();
    }

    public void delInPDF(){
        return;
    }

    @Override
    public void signQuicklyExCGI() {
        System.err.println("====> 临时目录pdf剪切到in目录触发签章 定时任务：signQuicklyExCGI() star ................");
        Long a = System.currentTimeMillis();

        Page<SignatureQueuesDTO> pageQueues = signatureQueuesRepository.pageQueues(3, PageRequest.of(0, 300));
        List<SignatureQueuesDTO> queues = pageQueues.getContent();
        if (Collections.isEmpty(queues)) {
            return;
        }
        String infile = tempPDF+"/"+ DateUtil.today();
        for (SignatureQueuesDTO queuesDTO : queues) {
            processQueue(queuesDTO, infile);
        }

        log.info("====> 电子签章定时任务开始.signQuicklyExCGI.签章接口耗时："+(System.currentTimeMillis()-a));
    }

    private void processQueue(SignatureQueuesDTO queuesDTO, String infile) {
        System.err.println("====> 电子签章定时任务开始.signQuicklyExCGI.processQueue.Last_processed_result：" + queuesDTO.getLast_processed_result());
        if (StringUtils.isEmpty(queuesDTO.getLast_processed_result())) {
            return;
        }
        String fileNumber = queuesDTO.getLast_processed_result().split("证书编码:")[1];
        String filename = System.currentTimeMillis()+"hnzgz_queueId_" + queuesDTO.getId() + ".ofd";
        System.err.println("====> 电子签章定时任务开始.signQuicklyExCGI.processQueue.filename：" + filename);
        String path = Paths.get(infile, filename).normalize().toString();
        System.err.println("====> 电子签章定时任务开始.signQuicklyExCGI.processQueue.path：" + path);
        String base64Str = HuNanECUtil.getFileRequest(cgiApi, fileNumber);
        if (StringUtils.isEmpty(base64Str)) {
            return;
        }
        //创建目录
        FileUtils.mkdirs(rootPath+infile);
        // 将Base64字符串解码为字节数组 存服务器
        byte[] bytes = cn.hutool.core.codec.Base64.decode(base64Str);
        File file = new File(rootPath + path);
        try (FileOutputStream fos = new FileOutputStream(file)) {
            // 将字节数组写入文件
            fos.write(bytes);
        } catch (IOException e) {
            System.err.println("写入文件时发生错误："+ e.getMessage());
            return;
        }
        String updateSql = "UPDATE tlk_certificate SET ITEM_SIGNATURED_PROCESSED_STATUS=?, ITEM_LAST_SIGNATURED_PROCESSED_TIME=NOW(), ITEM_CERTIFICATEDATE=IFNULL(ITEM_CERTIFICATEDATE, NOW()), ITEM_LAST_SIGNATURED_PROCESSED_RESULT=?, ITEM_ATTACHMENT=? WHERE ID=?";
        jdbcTemplate.update(updateSql, "2", "完成", path, queuesDTO.getBusiness_id());
        System.err.println("====> 电子签章定时任务开始.signQuicklyExCGI.processQueue.updateSql：" + updateSql);
        signatureQueuesRepository.updateSignature(1, new Date(), fileNumber, queuesDTO.getId());
    }

    @Override
    public void changeStatus() {
        String updateSql = "update obpm2_security.signature_queues set status = '0' where status = '3' and !instr(last_processed_result,'证书编码:') and TIMESTAMPDIFF(HOUR, last_processed_time, NOW()) > 3";
        jdbcTemplate.update(updateSql);
    }

    public void scan() {
        return;
    }

    @Data
    public static class SignatureData {
        private String name;
        private String address;
        private String headphoto;
        private String idcardno;
        private String year;
        private String month;
        private String day;
        private String certificateno;
        private String certificatefrom;
        private String isSignature;
        //发证日期
        private String fzDate;
        private String zYear;
        private String zMonth;
        private String zDay;
        private String signatureImg;
        //未签章pdf存储路径
        private String unSignaturePDF;
        //已签章pdf扫描路径
        private String signaturePDF;
    }

    /**
     * Restful 接口返回的资源对象
     *
     */
    @Data
    public static class Resource {
        private int errcode;
        private String errmsg;
        private Object data;
    }
}
