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

import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
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.domain.enums.SxCertDn;
import com.bcxin.backend.domain.models.SignatureQueuesDTO;
import com.bcxin.backend.domain.services.impls.ConvertServiceImpl;
import com.bcxin.backend.domain.signature.service.QzSignatureStrategy;
import com.bcxin.backend.domain.syncs.dtos.SharedConvertDto;
import com.bcxin.backend.domain.utils.FileUtils;
import com.bcxin.backend.domain.utils.MD5Util;
import com.bcxin.backend.domain.utils.SM.SM3Utils;
import com.google.common.collect.Maps;
import io.jsonwebtoken.lang.Collections;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.DateUtils;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.bouncycastle.util.encoders.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;


@Slf4j
@Service
public class ShanXiInSignatureToPDFCompare 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;
    @Autowired
    private ConvertServiceImpl convertService;

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

    @Autowired
    private Environment cenv;

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

//    public ShanXiInSignatureToPDFCompare(SignatureQueuesRepository signatureQueuesRepository) {
//        this.signatureQueuesRepository = signatureQueuesRepository;
//    }


    @Override
    public void cerSignatureQueues() {
        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' 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;
                IdAddress = StringUtils.isNotEmpty(IdAddress)?IdAddress.replace(" ",""):IdAddress;
                if(StringUtils.isEmpty(IdAddress) && StringUtils.isEmpty(headphoto)){
                    boolean2 = false;
                }else if(StringUtils.isEmpty(IdAddress)||IdAddress.contains(" ")){
                    boolean3 = false;
                }else if(StringUtils.isEmpty(headphoto)||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")+"";
                        }else if(headphoto.contains("path")){
                            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;
    }

    private static String handleSignParam(String path,String fileName) {
        SxCertDn sxCertDn = SxCertDn.getByAreaName(fileName);
        if(sxCertDn == null){
            return "";
        }
        HashMap m1 = new LinkedHashMap();
        HashMap content = new LinkedHashMap(); // 业务参数
        byte[] base = FileUtils.readFileTobytes(path);
        content.put("fileData", org.apache.commons.codec.binary.Base64.encodeBase64String(base));
        content.put("appId", sxCertDn.getAppId()); // 第三方应用appid
        content.put("certId", sxCertDn.getCertId());
        content.put("fileName", fileName);// 文件名称，传实际签章文件名称

        // 位置签章参数
        List list = new ArrayList();
        HashMap data = new LinkedHashMap();
        data.put("sealId", sxCertDn.getSealId()); // 印章ID
        data.put("pageNum", "1"); // 签章页码 ofd从0开始，pdf从1开始
        data.put("zx", "150"); // 签章位置坐标 ofd以左上角为原点，pdf以左下角为原点
        data.put("zy", "193"); // 签章位置坐标
        data.put("certDN", sxCertDn.getCertDN());
        data.put("secretKey", sxCertDn.getSecretKey()); // 密钥
        data.put("keyPin", "");
        list.add(data);
        content.put("signList", list);

        m1.put("message_header", handleHeader1(content,sxCertDn.getAppKey()));
        m1.put("message_content", content);
        JSONObject o1 = new JSONObject(m1);
        String re = o1.toJSONString();
        return re;
    }

    private static HashMap handleHeader1(HashMap content,String appKey) {
        HashMap header = new LinkedHashMap();
        header.put("sign", "");
        header.put("ctime", DateUtils.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
        header.put("version", "1.0");
        JSONObject o = new JSONObject(content);
        String re1 = o.toJSONString();
        String mac = null;
        try {
            mac = SM3Utils.hmac(appKey, re1);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        header.put("hmac", mac);
        return header;
    }

    /**
     * 处理头参数
     */
    private static HashMap handleHeader(String re1, String key) {
        HashMap header = new LinkedHashMap();
        header.put("sign", "");
        header.put("ctime", DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));
        header.put("version", "1.0");
        String mac = null;
        try {
            mac = SM3Utils.hmac(key, re1);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        header.put("hmac", mac);
        return header;
    }

    /**
     * <b> 批量生成pdf文件 </b>
     * @author ZXF
     * @create 2022/10/31 0031 13:33
     * @version
     * @注意事项 </b>
     */
    private void createPDF() {
        String sql = "select id,template_url,`data`,status,business_id,last_processed_time,certificatedate,last_processed_result from obpm2_security.signature_queues where `status`=0 order by certificatedate desc limit 0,300";
        //1.查询签章队列表需要签章的数据
        List<SignatureQueuesDTO> queues = null;
        try {
            queues = jdbcTemplate.query(sql,new RowMapper<SignatureQueuesDTO>(){
                @Override
                public SignatureQueuesDTO mapRow(ResultSet rs, int rowNum) throws SQLException {
                    SignatureQueuesDTO dto = new SignatureQueuesDTO();
                    dto.setId(rs.getString("id"));
                    dto.setTemplate_url(rs.getString("template_url"));
                    dto.setData(rs.getString("data"));
                    dto.setStatus(Integer.parseInt(rs.getString("status")));
                    dto.setBusiness_id(rs.getString("business_id"));
                    dto.setLast_processed_time(rs.getDate("last_processed_time"));
                    dto.setCertificatedate(rs.getDate("certificatedate"));
                    dto.setLast_processed_result(rs.getString("last_processed_result"));
                    System.err.println("====> 电子签章（无章PDF生成）定时任务开始：SignatureQueuesDTO:"+JSON.toJSONString(dto));
                    return dto;
                }
            });
        }catch (Exception e){
            log.error("====> 电子签章定时任务开始.createPDF.sql.ERR=",e.getMessage());
        }
        if (Collections.isEmpty(queues)) {
            return;
        }
        log.error("====> 电子签章定时任务开始.createPDF.sql.data.length=",queues.size());
        for (SignatureQueuesDTO queuesDTO:queues) {
            accept(queuesDTO);
        }

    }

    public static String postFileMultiPart(String url,Map<String, ContentBody> reqParam) throws IOException{
        CloseableHttpClient httpclient = HttpClients.createDefault();
        System.err.println("=======> existsPdfCopy.signPdf.postFileMultiPart.url:"+url);
        try {
            // 创建http
            HttpPost httppost = new HttpPost(url);
            //setConnectTimeout：设置连接超时时间，单位毫秒。setConnectionRequestTimeout：设置从connect Manager获取Connection 超时时间，单位毫秒。
            RequestConfig defaultRequestConfig = RequestConfig.custom().setConnectTimeout(15000).setConnectionRequestTimeout(15000).setSocketTimeout(115000).build();
            httppost.setConfig(defaultRequestConfig);
            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
            for(Map.Entry<String, ContentBody> param : reqParam.entrySet()){
                multipartEntityBuilder.addPart(param.getKey(), param.getValue());
            }
            HttpEntity reqEntity = multipartEntityBuilder.build();
            httppost.setEntity(reqEntity);
            // 执行post请求.
            CloseableHttpResponse response = httpclient.execute(httppost);
            System.err.println("got response");
            try {
                // 获取响应实体
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    return EntityUtils.toString(response.getEntity(), "UTF-8");
                }
            } finally {
                response.close();
            }
        } finally {
            // 关闭连接,释放资源
            try {
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * OFD位置签章
     */
    public void signPdf(String url,String fileName) throws IOException {
        Map<String, ContentBody> reqParam = new HashMap<>();
        File file = new File(rootPath+tempPDF.replace("temp","in")+"/"+fileName);
//        File file = new File("D:\\data\\share\\in\\"+fileName);
        String token = MD5Util.string2MD5("BCXIN" + fileName + DateUtil.today());
        //普通类型
        reqParam.put("token", new StringBody(token, org.apache.http.entity.ContentType.MULTIPART_FORM_DATA));
        reqParam.put("fileName", new StringBody(fileName, org.apache.http.entity.ContentType.MULTIPART_FORM_DATA));
        //文件
        reqParam.put("signpdf", new FileBody(file, org.apache.http.entity.ContentType.MULTIPART_FORM_DATA));
        System.err.println("=======> existsPdfCopy.signPdf.reqParam:"+reqParam);
        String res = postFileMultiPart(url,reqParam);
        Map<String, Object> re = JSONObject.parseObject(res, Map.class);
        System.err.println("=======> existsPdfCopy.signPdf.re:"+re);
        if (null != re && !re.isEmpty()) {
            String errorCode = (String) re.get("errorCode");
            if ("0".equals(errorCode)) {
                String base64 = (String) re.get("file");
                base64 = base64.replace("&#43;", "+"); // base64的数据，传输中 + 被转义为&#43;，需要替换
                byte[] fileData = Base64.decode(base64);
                FileUtils.write(fileData, rootPath+tempPDF.replace("temp","out")+"/"+fileName);
//                FileUtils.write(fileData, "D:\\data\\share\\out\\"+fileName);
                System.err.println("====> 电子签章定时任务开始.signPdf.ret：完成");
            } else {
                System.err.println("====> 电子签章定时任务开始.signPdf.ret：" + re.get("errorText"));
            }
        } else {
            System.err.println("====> 电子签章定时任务开始.signPdf.ret：请求异常");
        }
    }

    public static void main(String[] args) throws IOException {
        String d = "{\"name\":\"郑少雄\",\"address\":\"西安市临潼区秦陵办上陈村下陈组\",\"headphoto\":\"[{\"name\":\"\",\"path\":\"https://02obs.baibaodun.cn/2024/11-06/55f0cd87-0f79-4def-888d-96003ecab085/1730884732083.jpg\"}]\",\"idcardno\":\"610115199207240779\",\"year\":\"1992\",\"month\":\"07\",\"day\":\"24\",\"certificateno\":\"陕012024020343\",\"certificatefrom\":\"西安市公安局\",\"isSignature\":\"1\",\"fzDate\":\"2024-12-13\"}";

        SignatureData data = JSONObject.parseObject(d,SignatureData.class);
        SxCertDn sxCertDn = SxCertDn.getByAreaName(data.getCertificatefrom());
        System.err.println("====> 电子签章（无章PDF生成）定时任务开始：accept.sxCertDn:"+sxCertDn);
//        signPdf("http://signature.baibaodun.com.cn/signature/api/file/yesign","queueId_1.pdf");
//        signPdf("http://localhost:8097/signature/api/file/yesign","queueId_1.pdf");
        /*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) {

        System.err.println("====> 电子签章定时任务开始.createPDF.accept.单次生成文件 star   -----------------------");
        Long a = System.currentTimeMillis();
        if(queue.getData().contains("b.photoUrl")||queue.getData().contains("uid")){
            useSql(queue.getId(),queue.getBusiness_id(),"签章失败：证书信息不全（身份证头像）");
            return;
        }
        SignatureData data = JSONObject.parseObject(queue.getData(),SignatureData.class);
        if(StringUtils.isEmpty(data.getAddress()) || data.getAddress().contains(" ")){
            useSql(queue.getId(),queue.getBusiness_id(),"签章失败：证书信息不全（身份证住址）");
            return;
        }
        SxCertDn sxCertDn = SxCertDn.getByAreaName(data.getCertificatefrom());
        System.err.println("====> 电子签章（无章PDF生成）定时任务开始：accept.sxCertDn:"+sxCertDn);
        if(sxCertDn==null || StringUtils.isEmpty(sxCertDn.getSealId())){
            useSql(queue.getId(),queue.getBusiness_id(),"证书所属区域无有效电子印章");
            return;
        }
        System.err.println("====> 电子签章（无章PDF生成）定时任务开始：accept.sxCertDn.SealId:"+sxCertDn.getSealId());
        //先将文件命名为.temp
        data.setUnSignaturePDF(tempPDF+"/"+System.currentTimeMillis()+sxCertDn.toString()+"queueId_"+queue.getId()+".temp");
        String toDay = data.getFzDate();
        if(StringUtils.isEmpty(toDay)){
            toDay = DateUtil.today();
        }
        System.err.println("====> 电子签章（无章PDF生成）定时任务开始：accept.toDay:"+toDay);
        data.setZYear(toDay.split("-")[0]);
        data.setZMonth(toDay.split("-")[1]);
        data.setZDay(toDay.split("-")[2]);
        try{
            byte[] imageBytes = HttpUtil.downloadBytes(data.getHeadphoto());
            String base64Str = Base64Encoder.encode(imageBytes);
            data.setHeadphoto(BASE64_PREFIX+base64Str);
        }catch (Exception e){
            useSql(queue.getId(),queue.getBusiness_id(),"头像信息参数异常:"+e.getMessage());
            return;
        }

        String result = "";
        SharedConvertDto sharedConvertDto = new SharedConvertDto();
        sharedConvertDto.setTempUrl(queue.getTemplate_url());
        sharedConvertDto.setFormData(data);
        try {
            //最终输出为.pdf文件，主要是为了避免pdf 0kb时就被剪切走
            result = convertService.execConvertHtmltopdfForTemp(sharedConvertDto);
        } catch (IOException e) {
            result = "";
            System.err.println("====> 电子签章定时任务开始.createPDF.accept.pdf生成异常："+e.getMessage());
        }
        System.err.println("====> 电子签章（无章PDF生成）定时任务开始：accept.result:"+result);
        if(StringUtils.isNotEmpty(result)){
            //成功
            String sql = "UPDATE obpm2_security.signature_queues s SET s.status=3,s.last_processed_time=NOW(),s.last_processed_result='PDF已生成待签章' WHERE s.id="+queue.getId()+";";
            jdbcTemplate.update(sql);
        }else{
            //失败
            useSql(queue.getId(),queue.getBusiness_id(),"PDF生成失败:");
        }
        System.err.println("====> 电子签章定时任务开始.createPDF.accept.单次生成文件耗时："+(System.currentTimeMillis()-a));
    }

    private void useSql(String id,String business_id, String errMsg){
        String sql = "DELETE FROM obpm2_security.signature_queues s WHERE s.id="+id+";";
        //失败
        jdbcTemplate.update(sql);
        String updateSql = "UPDATE tlk_certificate SET ITEM_SIGNATURED_PROCESSED_STATUS=\"3\",ITEM_LAST_SIGNATURED_PROCESSED_TIME=NOW(),ITEM_LAST_SIGNATURED_PROCESSED_RESULT=\""+ errMsg +"\" WHERE ID=\"" + business_id + "\";";
        jdbcTemplate.update(updateSql);
        log.info("====> 电子签章定时任务开始.createPDF.accept.单次业务"+errMsg+"，end");
    }

    public void delInPDF(){
        SharedConvertDto sharedConvertDto = new SharedConvertDto();
        sharedConvertDto.setTempUrl(tempPDF);
        convertService.delInPDF(sharedConvertDto);
    }

    @Override
    public void signQuicklyExCGI() {
        Long a = System.currentTimeMillis();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("tempUrl", tempPDF);
        jsonObject.put("formData", 230);
        try {
            //到文件夹剪切一个文件到out目录
            SharedConvertDto sharedConvertDto = new SharedConvertDto();
            String tempUrl = jsonObject.getString("tempUrl");
            String formData = jsonObject.getString("formData");
            sharedConvertDto.setTempUrl(tempUrl);
            sharedConvertDto.setFormData(formData);
            new Thread(()->{
                try {
                    //先检索in目录存在的删除
                    convertService.delInPDF(sharedConvertDto);
                } catch(Exception e) {
                    log.error("====> 电子签章定时任务开始.signQuicklyExCGI签章前比对in文件删除："+ e.getMessage());
                }
            }).start();
            //剪切文件到in目录下
            convertService.existsPdfCopy(sharedConvertDto);
            //每次盖章前先清除0kb文件
            convertService.delInPDF(tempPDF);
            //先触发对需要签章目录下文件进行签章
            //activateXMPSignQuicklyExCGI();
            File[] fis = convertService.findInFile(sharedConvertDto.getTempUrl());
            System.err.println("=======> existsPdfCopy.fis:"+fis);
            if(fis != null){
                for (File file : fis) {
                    new Thread(()->{
                        try {
                            System.err.println("=======> existsPdfCopy.signPdf:star");
                            signPdf(cgiApi,file.getName());
                        } catch (IOException e) {
                            log.error("====> 电子签章定时任务开始.signPdf error："+ e.getMessage());
                        }
                    }).start();
                    //每一次都等待500毫秒
                    Thread.sleep(500);
                }
            }
            System.err.println("=======> existsPdfCopy.signPdf:end");

            new Thread(()->{
                try {
                    //先检索in目录存在的删除
                    convertService.delInPDF(sharedConvertDto);
                } catch(Exception e) {
                    log.error("====> 电子签章定时任务开始.signQuicklyExCGI签章后比对in文件删除："+ e.getMessage());
                }
            }).start();
            System.err.println("====> 电子签章定时任务开始.signQuicklyExCGI.签章接口耗时："+(System.currentTimeMillis()-a));
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void changeStatus() {
        String updateSql = "update signature_queues set status = '0' where status = '3' and TIMESTAMPDIFF(HOUR, last_processed_time, NOW()) > 3";
        jdbcTemplate.update(updateSql);
    }

    public void scan() {
        StringBuilder sb = new StringBuilder();
        try {
            Long a = System.currentTimeMillis();
            String pdfFile = tempPDF.replace("/temp","/out");// "/uploads/pdf/dianziqianzhangout/out"


            String dayFilePath = pdfFile.replace("/out", "/"+DateUtil.today());
            SharedConvertDto sharedConvertDto = new SharedConvertDto();
            sharedConvertDto.setTempUrl(pdfFile);
            sharedConvertDto.setFormData(null);
            String result = convertService.existsScanSignatureByDayFile(sharedConvertDto);
            if (StringUtils.isEmpty(result)) {
                System.err.println("====> 电子签章定时任务开始.scan.result：空");
                return;
            }
            System.err.println("====> 电子签章定时任务开始.scan.批量剪切到日期目录结束耗时：" + (System.currentTimeMillis() - a));
            JSONObject json = JSONObject.parseObject(result);
            Object success = json.get("success");
            Object fail = json.get("fail");
//            String successQidS = "";
//            String failQidS = "";
            List<String> failList = null;
            String successFile = "";
            String failFile = "";
            if (success != null){
                successFile = (String) success;//queueId_134147.pdf,queueId_134148.pdf,queueId_134149.pdf
                /*if(StringUtils.isNotEmpty(successFile)){
                    successQidS = "(" + successFile.replace(".pdf", "'").replace("queueId_", "'") + ")";
                }*/
            }
            if (fail != null){
                failFile = (String) fail;//queueId_134147.pdf,queueId_134148.pdf,queueId_134149.pdf
                if(StringUtils.isNotEmpty(failFile)){
//                    failQidS = "(" + failFile.replace(".pdf", "'").replace("queueId_", "'") + ")";
                    String[] failS = failFile.replace(".pdf", "").split("queueId_")[1].split(",") ;
                    if(failS.length>0){
                        failList = Arrays.asList(failS);
                    }
                }
            }
            String fileNames = successFile+failFile;
            new Thread(()->{
                try {
                    //只要ftp有跑过的都要比对删除
                    convertService.delSetFtpFile(tempPDF,fileNames);
                } catch(Exception e) {
                    log.error("====> 电子签章定时任务开始.scan.剪切到日期目录操作过的文件删除："+ e.getMessage());
                }
            }).start();

            if (StringUtils.isNotEmpty(successFile)) {
                String updateSql;
                //成功
                String[] successSplit = successFile.split(",");
                for (String string : successSplit) {
                    String successFilePath = dayFilePath+"/"+string;
                    String id = string.split("queueId_")[1].replace(".pdf","");
                    System.err.println("====> 电子签章定时任务开始.scan.successSplit.id:"+id);
                    String sqlqueue = "select business_id from obpm2_security.signature_queues where id="+id+";";
                    System.err.println("====> 电子签章定时任务开始.scan.successSplit.sqlqueue:"+sqlqueue);
                    Map<String,Object> map = jdbcTemplate.queryForMap(sqlqueue);
                    System.err.println("====> 电子签章定时任务开始.scan.successSplit.map:"+map);
                    String business_id = map.get("business_id") == null?"":map.get("business_id").toString();
                    System.err.println("====> 电子签章定时任务开始.scan.successSplit.business_id:"+business_id);
//                    String business_id = signatureQueuesRepository.getBuId(id);
                    if(StringUtils.isEmpty(business_id)){
                        String sql = "UPDATE obpm2_security.signature_queues s SET s.status=2,s.last_processed_time=NOW(),s.last_processed_result='签章对象业务来源不存在' WHERE s.id ="+id+";";
                        System.out.println("====> 电子签章定时任务开始.scan.successSplit.sql:"+sql);
                        jdbcTemplate.update(sql);
                    }else{
                        updateSql = "UPDATE tlk_certificate SET ITEM_SIGNATURED_PROCESSED_STATUS=\"2\",ITEM_LAST_SIGNATURED_PROCESSED_TIME=NOW(),ITEM_CERTIFICATEDATE=IFNULL(ITEM_CERTIFICATEDATE,NOW()),ITEM_LAST_SIGNATURED_PROCESSED_RESULT=\"完成\",ITEM_ATTACHMENT=\"" + successFilePath + "\" WHERE ID=\"" + business_id + "\";";
                        System.err.println("====> 电子签章定时任务开始.scan.successSplit.updateSql:"+updateSql);
                        jdbcTemplate.update(updateSql);
                        business_id = business_id.replace("__TTeElnX8IULbf7iTxsM","__jlNfVcjppSliMYH6FkJ");
                        String detailSql = "UPDATE obpm2.tenant_user_credential_details SET update_time=NOW(),electronCerUrl=\"" + successFilePath + "\" WHERE ID=\"" + business_id + "\";";
                        System.err.println("====> 电子签章定时任务开始.scan.successSplit.detailSql:"+detailSql);
                        jdbcTemplate.update(detailSql);
//                    signatureQueuesRepository.updateSignature("1", new Date(), "成功", id);
                        String sql = "DELETE FROM obpm2_security.signature_queues WHERE id="+id+";";
                        System.err.println("====> 电子签章定时任务开始.scan.successSplit.sql:"+sql);
                        jdbcTemplate.update(sql);
                    }
                }
            }
            if (failList != null){
//                signatureQueuesRepository.updateSignatures("2", new Date(), "未成功签章", failList);
                String sql = "UPDATE obpm2_security.signature_queues s SET s.status=2,s.last_processed_time=NOW(),s.last_processed_result='未成功签章' WHERE s.id in ("+failList+");";
                System.err.println("====> 电子签章定时任务开始.scan.failList.sql:"+sql);
                jdbcTemplate.update(sql);
            }
            System.err.println("====> 电子签章定时任务开始.scan.50个PDF已签章文件存日期目录耗时：" + (System.currentTimeMillis() - a));
        } catch (Exception e) {
            System.err.println("====> 电子签章定时任务开始.scan.updateSql error：" + ExceptionUtils.getStackMessage(e));
        }
    }

    @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;
    }
}
