package com.bcxin.signature.service.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bcxin.signature.config.FileModeConfig;
import com.bcxin.signature.config.FileWriteConfig;
import com.bcxin.signature.entity.SignatureQueuesBazgz;
import com.bcxin.signature.entity.SignatureQueuesDocument;
import com.bcxin.signature.service.SignatureService;
import com.bcxin.signature.util.ftp.DownloadResult;
import com.bcxin.signature.util.ftp.FtpUtil;
import com.bcxin.signature.util.ftp.FtpWriteUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Instant;
import java.time.Duration;
import java.util.*;

/**
 * <b> 签章业务相关 </b>
 * @author ZXF
 * @create 2024/11/20 0020 18:14
 * @version
 * @注意事项 </b>
 */
@Slf4j
@Service
public class SignatureServiceImpl implements SignatureService {

    @Value("${myapps.signature.api}")
    String api;
    @Value("${myapps.signature.appid}")
    String appid;
    @Value("${myapps.signature.sealno}")
    String sealno;
    @Value("${myapps.signature.license.ip_address}")
    String ip_address;
//    @Value("${myapps.signature.license.item_code}")
//    String item_code;
    @Value("${myapps.signature.license.app_key}")
    String app_key;
    @Value("${myapps.signature.license.app_secret}")
    String app_secret;
    @Value("${myapps.signature.license.account}")
    String account;
    @Value("${myapps.signature.license.password}")
    String password;

    //签章接口（单文档单章 支持PDF|OFD）
    private static final String STAMPFILE = "/channel/stampFile";
    //4.2.2.签章接口（不同文档不同章 支持PDF|OFD）
    private static final String FLEXIBLESEALFILE = "/channel/flexibleSealFile";
    //验章接口（支持PDF|OFD）
    private static final String VERIFYFILE = "/channel/verifyFile";
    //文书业务目录
    private static final String DOCUMENTPATH = "/document";
    //文书业务目录
    private static final String SIGNATUREATH = "/signature";

    //京通靓证 登录 获取token
    private static final String LICENSE_LOGIN = "/license-app/v1/security/login";
    //京通靓证 2.2.1 制证签发接口
    private static final String LICENSE_ISSUE= "/license-app/v1/license/{item_code}/issue?access_token=";
    //京通靓证 2.2.2 废止证照
    private static final String LICENSE_ABOLISH= "/license-app/v1/license/{item_code}/abolish?access_token=";

    // 静态 Map 存储 token 及其生成时间
    private static Map<String, Instant> tokenMap = new HashMap<>();

    private static int count_jtlz = 0;
    private static int count_jtlz_document = 0;

    private final ThreadPoolTaskExecutor taskExecutor;
    public SignatureServiceImpl(ThreadPoolTaskExecutor taskExecutor) {
        this.taskExecutor = taskExecutor;
    }

    /**
     * <b> 文书签章业务 </b>
     * @author ZXF
     * @create 2024/11/20 0020 17:33
     * @version
     * @注意事项 </b>
     */
    @Override
    public void documentSignature() {
        //ftp文件存储路径
//        String ftpIn = FileModeConfig.getFilePath()+FileModeConfig.getInPath() + DOCUMENTPATH + "/" + DateUtil.today();
//        String ftpOut = FileModeConfig.getFilePath()+FileModeConfig.getOutPath() + DOCUMENTPATH + "/" + DateUtil.today();
        String ftpIn = FileModeConfig.getFilePath();
        String ftpOut = FileModeConfig.getFilePath();
        List<String> list = FtpUtil.filenames(ftpIn,"");
        for (String filename: list) {
            System.err.println("====> 文书签章定时任务.documentSignature.filename：" + filename);
            String content = FtpUtil.getFileContent(ftpIn,filename);
            System.err.println("====> 文书签章定时任务.documentSignature.content：" + content);
            if(StringUtils.isEmpty(content)){
                continue;
            }
            String[] arr = filename.split("-");
            // 保安资格证业务类型编号01 参考类DocumentType.BAZGZ
            if("01".equals(arr[1])){
                bazgzServer(ftpIn, ftpOut, filename, content);
            }else{
                documentServer(ftpIn, ftpOut, filename, content, arr[1]);
            }
        }

    }

    private void documentServer(String ftpIn, String ftpOut, String filename, String content, String type){
        SignatureQueuesDocument document = JSON.parseObject(content, SignatureQueuesDocument.class);
        System.err.println("====> 文书签章定时任务.documentSignature.document：" + JSON.toJSONString(document));
        if(document == null){
            return;
        }
        document.setStatus("2");
        String[] arr = document.getFile_url().split("-");
        String baseeContent = FtpUtil.downloadAsBase64(ftpIn,arr[1]);
        Result ret = verifySignature(baseeContent,document.getBusiness_name());
        if("200".equals(ret.status)){
            JSONObject dataJson = JSONObject.parseObject(JSON.toJSONString(ret.data));
            String result = dataJson.getString("result");
            if("FALSE".equals(result)){
                //根据接口返回结果更新数据库
                ret = sendSignature(document.getStamp_xy(), baseeContent,document.getBusiness_name());
                if("200".equals(ret.status)){
                    File file = JSONObject.parseObject(JSON.toJSONString(ret.data),File.class);
                    //base64文件流写入原文件地址
                    try {
                        if(StringUtils.isEmpty(file.fileB64)){
                            throw new IOException("文件不存在");
                        }
//                            base64ToFile(file.fileB64,rootPath+document.getFile_url());

                        //返回结果写入新建ftp out下对应文书文件
                        FtpUtil.uploadBase64(ftpOut, arr[1], file.fileB64);
                        document.setStatus("1");
                        //如果是保安服务许可证书签章，需要推送京通靓证
//                        if("16".equals(type)){
//                            //推送京通靓证
//                            document.setJt_code(syncJT(document.getData(),document.getOperator(),filename,file.fileB64));
//                        }
                    } catch (IOException e) {
                        document.setProcessed_result(e.getMessage());
                    }
                }
            }else{
                //如果文件已存在章，不重复盖章
                document.setStatus("1");
            }
        }

        document.setProcessed_result(ret.getMessage());
        document.setLastmodified(new Date());
        System.err.println("====> 文书签章定时任务.documentSignature.document：" + JSON.toJSONString(document));
        //新内容写入前缀为OUT|的文件
        FtpUtil.uploadBase64(ftpOut, filename.replace("IN|","OUT|"), JSON.toJSONString(document));
    }

    private void bazgzServer(String ftpIn, String ftpOut, String filename, String content){
        SignatureQueuesBazgz bazgz = JSON.parseObject(content, SignatureQueuesBazgz.class);
        System.err.println("====> 资格证签章定时任务.bazgzSignature.bazgz：" + JSON.toJSONString(bazgz));
        if(bazgz == null){
            return;
        }
        bazgz.setStatus("2");
        String[] arr = bazgz.getFile_url().split("-");
        String baseeContent = FtpUtil.downloadAsBase64(ftpIn,arr[1]);
        Result ret = verifySignature(baseeContent,bazgz.getBusiness_name());
        if("200".equals(ret.status)){
            JSONObject dataJson = JSONObject.parseObject(JSON.toJSONString(ret.data));
            String result = dataJson.getString("result");
            if("FALSE".equals(result)){
                //根据接口返回结果更新数据库
                ret = sendSignature(bazgz.getStamp_xy(), baseeContent,bazgz.getBusiness_name());
                if("200".equals(ret.status)){
                    File file = JSONObject.parseObject(JSON.toJSONString(ret.data),File.class);
                    //base64文件流写入原文件地址
                    try {
                        if(StringUtils.isEmpty(file.fileB64)){
                            throw new IOException("文件不存在");
                        }
//                            base64ToFile(file.fileB64,rootPath+document.getFile_url());

                        //返回结果写入新建ftp out下对应文书文件
                        FtpUtil.uploadBase64(ftpOut, arr[1], file.fileB64);
                        bazgz.setStatus("1");
                        //推送京通靓证
//                        bazgz.setJt_code(syncJT(bazgz.getData(),bazgz.getOperator(),filename,file.fileB64));
                    } catch (IOException e) {
                        bazgz.setProcessed_result(e.getMessage());
                    }
                }
            }else{
                //如果文件已存在章，不重复盖章
                bazgz.setStatus("1");
            }
        }

        bazgz.setProcessed_result(ret.getMessage());
        bazgz.setLastmodified(new Date());
        System.err.println("====> 资格证签章定时任务.bazgzSignature.bazgz：" + JSON.toJSONString(bazgz));
        //新内容写入前缀为OUT|的文件
        FtpUtil.uploadBase64(ftpOut, filename.replace("IN|","OUT|"), JSON.toJSONString(bazgz));
    }

    private static void base64ToFile(String base64String,String filePath) throws IOException {
        // 解码Base64字符串
        byte[] decodedBytes = Base64.decode(base64String);
        // 将字节数组写入文件
        Path path = Paths.get(filePath);
        Files.write(path, decodedBytes);
    }

    /**
     * <b> 资格证签章业务（待定） </b>
     * TODO 资格证可以改造统一走文书签章同一业务规则实现签章及推送靓证
     * @author ZXF
     * @create 2024/11/20 0020 17:33
     * @version
     * @注意事项 </b>
     */
    @Override
    public void bazgzSignature() {
        //ftp文件存储路径
//        String ftpIn = FileModeConfig.getFilePath()+FileModeConfig.getInPath() + SIGNATUREATH + "/" + DateUtil.today();
//        String ftpOut = FileModeConfig.getFilePath()+FileModeConfig.getOutPath() + SIGNATUREATH + "/" + DateUtil.today();
        String ftpIn = FileModeConfig.getFilePath();
        String ftpOut = FileModeConfig.getFilePath();
        List<String> list = FtpUtil.filenames(ftpIn,"");
        SignatureQueuesBazgz bazgz;
        for (String filename: list) {
            System.err.println("====> 资格证签章定时任务.bazgzSignature.filename：" + filename);
            String content = FtpUtil.getFileContent(ftpIn,filename);
            System.err.println("====> 资格证签章定时任务.bazgzSignature.content：" + content);
            if(StringUtils.isEmpty(content)){
                continue;
            }
            bazgzServer(ftpIn, ftpOut, filename, content);

        }
    }

    public static void main(String[] args) {
//        String now = DateUtil.format(DateUtil.date(),"yyyyMMddHHmm");
//        int lastM = Integer.parseInt(now.substring(now.length()-1,now.length()));
//        now = now.substring(0,now.length()-1)+(lastM<=5?0:5);
//        String hourName = DateUtil.format(DateUtil.offsetHour(DateUtil.date(),-8),"yyyyMMddHHmm");
//        System.out.println(now+","+hourName);
//        202412301845
//        202412301045
    }

    /**
     * <b> 京通靓证业务(读取文件推送) </b>
     * @author ZXF
     * @create 2024/11/20 0020 17:33
     * @version
     * @注意事项 </b>
     */
    @Override
    public void signatureJTLZ() {
        long v = System.currentTimeMillis();
        //定义当前时间5分钟前的文件名
        String minuteName = DateUtil.format(DateUtil.offsetMinute(DateUtil.date(),-5),"yyyyMMddHHmm");
        String readFtpName = "INJTLZ-"+minuteName+".bcx";
        //读取文件
        String fileContent = FtpUtil.getFileContent(FileModeConfig.getFilePath(),readFtpName);
        if(StringUtils.isEmpty(fileContent)){
            System.err.println("====> jtlzTask.signatureJTLZ.noFile("+FileModeConfig.getUserName()+" , "+FileModeConfig.getFilePath()+").readFtpName：" + readFtpName);
            return;
        }
        String[] list = fileContent.split(",");
        count_jtlz = list.length;
        System.err.println("====> jtlzTask.signatureJTLZ.fileContent.splitLength：" + count_jtlz);
        int count = 0;
        for (String filename: list) {
            if(count == 5){
                count = 0;
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            this.taskExecutor.execute(() -> {
                long a = System.currentTimeMillis();
                try{
                    String content = FtpUtil.getFileContent( FileModeConfig.getFilePath(),filename);
                    if(StringUtils.isEmpty(content)){
                        jtlzNullRet(filename);
                    }else{
                        jtlzServer( filename, content);
                    }
                }catch (Exception e){
                    jtlzErrRet(filename,e.getMessage());
                    System.err.println("====> jtlzTask.signatureJTLZ.jtlzServer.filename:"+filename+"，ERROR：" + e.getMessage());
                }finally {
                    FtpUtil.delFilename(FileModeConfig.getFilePath(), filename);
                    log.info("========> jtlzTask.signatureJTLZ.filename:"+filename+"，totalTime："+(System.currentTimeMillis()-a)/1000+"s   ****************************");
                    count_jtlz -=1;
                }
            });
            count++;
        }
        //等待15秒，如果线程还没全部完成，则跳出循环
        int i = 0;
        while (count_jtlz > 0) {
            if(i==15){
                break;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            i++;
        }
        System.err.println("====> jtlzTask.signatureJTLZ.lastTotal:"+count_jtlz+" end    ****************************");
        log.info("========> jtlzTask.end.totalTime："+(System.currentTimeMillis()-v)/1000+"s    ****************************");
    }

    /**
     * <b> 京通靓证业务保安服务许可证(读取文件推送) </b>
     * @author ZXF
     * @create 2024/11/20 0020 17:33
     * @version
     * @注意事项 </b>
     */
    @Override
    public void signatureJTLZDocument() {
        long v = System.currentTimeMillis();
        //定义当前时间5分钟前的文件名
        String minuteName = DateUtil.format(DateUtil.offsetMinute(DateUtil.date(),-5),"yyyyMMddHHmm");
        String readFtpName = "INJTLZDOCUMENT-"+minuteName+".bcx";
        //读取文件
        String fileContent = FtpUtil.getFileContent(FileModeConfig.getFilePath(),readFtpName);
        if(StringUtils.isEmpty(fileContent)){
            System.err.println("====> jtlzDocumentTask.signatureJTLZDocument.no find file("+FileModeConfig.getUserName()+" , "+FileModeConfig.getFilePath()+").readFtpName：" + readFtpName);
            return;
        }
        String[] list = fileContent.split(",");
        count_jtlz_document = list.length;
        System.err.println("====> jtlzDocumentTask.signatureJTLZDocument.fileContent.splitLength：" + count_jtlz_document);
        int count = 0;
        for (String filename: list) {
            if(count == 5){
                count = 0;
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            this.taskExecutor.execute(() -> {
                long a = System.currentTimeMillis();
                try{
                    String content = FtpUtil.getFileContent( FileModeConfig.getFilePath(),filename);
                    if(StringUtils.isEmpty(content)){
                        System.err.println("====> jtlzDocumentTask.signatureJTLZDocument.filename:"+filename+",content.length：0");
                        jtlzNullRet(filename);
                    }else{
                        System.err.println("====> jtlzDocumentTask.signatureJTLZDocument.use.filename：" + filename);
                        jtlzServer( filename, content);
                    }
                }catch (Exception e){
                    jtlzErrRet(filename,e.getMessage());
                    System.err.println("====> jtlzDocumentTask.signatureJTLZDocument.jtlzServer.filename:"+filename+"，ERROR：" + e.getMessage());
                }finally {
                    FtpUtil.delFilename(FileModeConfig.getFilePath(), filename);
                    log.info("========> jtlzDocumentTask.signatureJTLZDocument.one.totalTime："+(System.currentTimeMillis()-a)/1000+"s   ****************************");
                    count_jtlz_document -=1;
                }
            });
            count++;
        }
        //等待30秒，如果线程还没全部完成，则跳出循环
        int i = 0;
        while (count_jtlz_document > 0) {
            if(i==15){
                break;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            i++;
        }
        System.err.println("====> jtlzDocumentTask.signatureJTLZDocument.lastTotal:"+count_jtlz_document+" end    ****************************");
        log.info("========> jtlzDocumentTask.signatureJTLZDocument.end.totalTime："+(System.currentTimeMillis()-v)/1000+"s    ****************************");
    }

    /**
     * <b> 京通靓证业务(废止) </b>
     * @author ZXF
     * @create 2024/11/20 0020 17:33
     * @version
     * @注意事项 </b>
     */
    @Override
    public void signatureJTLZ_FZ() {
        long v = System.currentTimeMillis();
        //定义当前时间5分钟前的文件名
        String minuteName = DateUtil.format(DateUtil.offsetMinute(DateUtil.date(),-5),"yyyyMMddHHmm");
        String readFtpName = "INJTLZFZ-"+minuteName+".bcx";
        //读取文件
        String fileContent = FtpUtil.getFileContent(FileModeConfig.getFilePath(),readFtpName);
        if(StringUtils.isEmpty(fileContent)){
            System.err.println("====> jtlzFZTask.signatureJTLZ_FZ.no find file("+FileModeConfig.getUserName()+" , "+FileModeConfig.getFilePath()+").readFtpName：" + readFtpName);
            return;
        }
        String[] list = fileContent.split(",");
        System.err.println("====> jtlzFZTask.signatureJTLZ_FZ.reader file content total size：" + list.length);
        int count = 0;
        for (String filename: list) {
            if(count == 5){
                count = 0;
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            this.taskExecutor.execute(() -> {
                System.err.println("====> jtlzFZTask.signatureJTLZ_FZ.filename：" + filename);
                try{
                    String content = FtpUtil.getFileContent( FileModeConfig.getFilePath(),filename);
                    if(StringUtils.isEmpty(content)){
                        System.err.println("====> jtlzFZTask.signatureJTLZ_FZ.content.length：0");
                        jtlzNullRet(filename);
                    }else{
                        jtlzFzServer( filename, content);
                    }
                }catch (Exception e){
                    System.err.println("====> jtlzFZTask.signatureJTLZ_FZ.jtlzFzServer.filename:"+filename+"，ERROR：" + e.getMessage());
                }finally {
                    FtpUtil.delFilename(FileModeConfig.getFilePath(), filename);
                }
            });
            count++;
        }
        long s = 59000-((System.currentTimeMillis()-v));
        if(s>0){
            try {
                Thread.sleep(s);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void jtlzNullRet(String filename){
        String outFilename = filename.replace("IN-","OUT-");
        String result = "{\"ack_code\":\"FAILURE\",\"errors\":[{\"code\":\"12409\",\"severity\":\"ERROR\",\"message\":\"文件不存在或内容为空\",\"innerCode\":\"\"}],\"sign\":null,\"sign_method\":null,\"timestamp\":null,\"correlation_id\":null,\"response_id\":\"a40e028c-d566-44fc-a2fa-ee4b8df715dc\",\"data\":null}";
        //新内容写入前缀为OUT|的文件
        FtpWriteUtil.uploadBase64(FileWriteConfig.getFilePath(), outFilename, result);
    }
    private void jtlzErrRet(String filename,String msg){
        String outFilename = filename.replace("IN-","OUT-");
        String result = "{\"ack_code\":\"FAILURE\",\"errors\":[{\"code\":\"12409\",\"severity\":\"ERROR\",\"message\":\""+msg+"\",\"innerCode\":\"\"}],\"sign\":null,\"sign_method\":null,\"timestamp\":null,\"correlation_id\":null,\"response_id\":\"a40e028c-d566-44fc-a2fa-ee4b8df715dc\",\"data\":null}";
        //新内容写入前缀为OUT|的文件
        FtpWriteUtil.uploadBase64(FileWriteConfig.getFilePath(), outFilename, result);
    }

    private void jtlzServer(String filename, String content){
        String outFilename = filename.replace("IN-","OUT-");
        String[] arr = filename.split("-");
//        String type = arr[2];
        String item_code = arr[3];
        String result = license_issue(item_code,content);
        //新内容写入前缀为OUT|的文件
        FtpWriteUtil.uploadBase64(FileWriteConfig.getFilePath(), outFilename, result);
    }

    private String license_issue(String item_code,String body) {
        // 生成 token 的逻辑
        try {
            String pathApi = ip_address + LICENSE_ISSUE.replace("{item_code}", item_code) + getLicenseToken();
            String ret = HttpUtil.post(pathApi, body);
            if(StringUtils.isEmpty(ret)||ret.contains("FAILURE")){
                System.err.println("====> 京通靓证信息推送定时任务.license_issue.result.err：" + ret);
            }
            return ret;
        } catch (Exception e) {
            System.err.println("====> 京通靓证信息推送定时任务.license_issue.error:" + e.getMessage());
            return "{\"ack_code\":\"FAILURE\",\"errors\":[{\"code\":\"12409\",\"severity\":\"ERROR\",\"message\":\""+e.getMessage()+"\",\"innerCode\":\"\"}],\"sign\":null,\"sign_method\":null,\"timestamp\":null,\"correlation_id\":null,\"response_id\":\"a40e028c-d566-44fc-a2fa-ee4b8df715dc\",\"data\":null}";
        }
    }

    private void jtlzFzServer(String filename, String content){
//        System.err.println("====> 京通靓证信息废止定时任务.jtlzFzServer.content：" + content);
        String outFilename = filename.replace("IN-","OUT-");
        String[] arr = filename.split("-");
        String type = arr[2];
        String item_code = arr[3];
//        System.err.println("====> 京通靓证信息废止定时任务.jtlzFzServer:type="+type+",item_code=" + item_code);
        String result = license_issue_fz(item_code,content);
//        System.err.println("====> 京通靓证信息废止定时任务.jtlzFzServer.result：" + result);
        //新内容写入前缀为OUT|的文件
        FtpWriteUtil.uploadBase64(FileWriteConfig.getFilePath(), outFilename, result);
    }

    private String license_issue_fz(String item_code,String body) {
        // 生成 token 的逻辑
        try {
            String pathApi = ip_address + LICENSE_ABOLISH.replace("{item_code}", item_code) + getLicenseToken();

            String ret = HttpUtil.post(pathApi, body);
            System.err.println("====> 京通靓证信息废止定时任务.license_issue_fz.返回报文：" + ret);
            return ret;
        } catch (Exception e) {
            System.err.println("====> 京通靓证信息废止定时任务.license_issue_fz.error:" + e.getMessage());
            return "{\"ack_code\":\"FAILURE\",\"errors\":[{\"code\":\"12409\",\"severity\":\"ERROR\",\"message\":\""+e.getMessage()+"\",\"innerCode\":\"\"}],\"sign\":null,\"sign_method\":null,\"timestamp\":null,\"correlation_id\":null,\"response_id\":\"a40e028c-d566-44fc-a2fa-ee4b8df715dc\",\"data\":null}";
        }
    }

    // 生成 token 的方法（示例方法，实际业务逻辑根据需求实现）
    private String generateToken() {
        // 生成 token 的逻辑
        String token = "";
        try {
            JSONObject json = new JSONObject();
            json.put("app_key", app_key);
            json.put("app_secret", app_secret);
            json.put("account", account);
            json.put("password", password);
            String ret = HttpUtil.post(ip_address+LICENSE_LOGIN, json.toJSONString());
            if (StringUtils.isEmpty(ret)) {
                return token;
            }
            JSONObject result = JSONObject.parseObject(ret);
            String ack_code = result.getString("ack_code");
            token = result.getString("access_token");
            if(!"SUCCESS".equals(ack_code)||StringUtils.isEmpty(token)){
                System.err.println("====> 京通靓证获取token.license_login.access_token：fail");
                return token;
            }
            // 记录 token 的生成时间
            tokenMap = new HashMap<>();
            tokenMap.put(token, Instant.now());
            return token;
        } catch (Exception e){
            System.err.println("====> 京通靓证获取token.license_login.error:"+e.getMessage());
            return token;
        }
    }


    /**
     * <b> 京通靓证获取token,每次获取存一天，超时重新获取 </b>
     * @author ZXF
     * @create 2024/11/28 0028 17:59
     * @version
     * @注意事项 </b>
     */
    private String getLicenseToken() {
        // 获取当前时间
        Instant now = Instant.now();
        // 检查 Map 中是否有 token
        if (tokenMap.isEmpty()) {
            // 如果没有 token，生成新的 token
            return generateToken();
        }
        // 获取最新的 token 及其生成时间
        String latestToken = null;
        Instant latestTime = null;
        for (Map.Entry<String, Instant> entry : tokenMap.entrySet()) {
            if (latestTime == null || entry.getValue().isAfter(latestTime)) {
                latestToken = entry.getKey();
                latestTime = entry.getValue();
            }
        }
        // 检查 token 是否过期
        Duration duration = Duration.between(latestTime, now);
        if (duration.toHours() >= 6) {
            // 如果 token 过期，生成新的 token
            return generateToken();
        } else {
            // 如果 token 没有过期，直接返回
            return latestToken;
        }
    }


    /**
     * <b> 签章业务 </b>
     * @author ZXF
     * @create 2024/11/20 0020 17:33
     * @version
     * @注意事项 </b>
     */
    private Result sendSignature(String stamp_xy, String baseeContent, String file_name){
        //TODO 调用接口
        try {
            String[] xyArr = stamp_xy.split(",");
            JSONObject json = new JSONObject();
            json.put("appId", appid);
            json.put("file", new File(file_name,baseeContent, "pdf",file_name+" 签章"));
            JSONObject seal = new JSONObject();
            seal.put("sealInfo", new SealInfo(sealno,"FALSE"));
            JSONObject ruleInfo = new JSONObject();
            ruleInfo.put("version", "1.0");
            ruleInfo.put("ruleId", "");
            ruleInfo.put("ruleType", "RECTANGLE");//RECTANGLE-坐标签章、KEYWORD-关键字签章、ACROSS-骑缝章签章（三选一）
            ruleInfo.put("rectangleRule", new RectangleRule(xyArr[0],xyArr[1],xyArr[2],xyArr[3],xyArr[3]));//印章坐标:page 页码，left 左，right 右，top 上，bottom 下
            seal.put("ruleInfo", ruleInfo);
            json.put("seal", seal);
            String ret = HttpUtil.post(api+STAMPFILE, json.toJSONString());
            log.info("====> 文书签章定时任务开始.sendSignature.ret：" + ret);
            if (StringUtils.isEmpty(ret)) {
                return Result.fail("接口请求失败：返回空");
            }
            return JSON.parseObject(ret,Result.class);
        } catch (Exception e){
            log.info("====> 签章业务定时任务开始.sendSignature message:"+e.getMessage());
            return Result.fail("接口请求异常："+e.getMessage());
        }
    }

    /**
     * <b> 验章业务 </b>
     * @author ZXF
     * @create 2024/11/20 0020 17:33
     * @version
     * @注意事项 </b>
     */
    private Result verifySignature(String baseeContent, String file_name){
        //TODO 调用接口
        try {
            JSONObject json = new JSONObject();
            json.put("appId", appid);
            json.put("file", new File(file_name,baseeContent, "pdf",file_name+" 签章"));
            String ret = HttpUtil.post(api+VERIFYFILE, json.toJSONString());
            log.info("====> 文书验章定时任务开始.verifySignature.ret：" + ret);
            if (StringUtils.isEmpty(ret)) {
                return Result.fail("接口请求失败：返回空");
            }
            return JSON.parseObject(ret,Result.class);
        } catch (Exception e){
            log.info("====> 文书验章定时任务开始.verifySignature message:"+e.getMessage());
            return Result.fail("接口请求异常："+e.getMessage());
        }
    }

    @Data
    public static class Result {
        private String status;
        private String message;
        private Object data;

        public Result(String status,String message){
            this.status = status;
            this.message = message;
            this.data = null;
        }
        public static Result fail(String message){
            return new Result("300",message);
        }
    }

    @Data
    public static class File {
        private String title;
        private String fileB64;
        private String filePath;
        private String fileType;
        private String templateData;
        private String classify;
        private String fileDesc;

        public File(String title, String fileB64, String fileType,String fileDesc){
            this.title = title;
            this.fileB64 = fileB64;
            this.fileType = fileType;
            this.fileDesc = fileDesc;
        }
    }

    @Data
    public static class RectangleRule {
        private String page;
        private String bottom;
        private String top;
        private String left;
        private String right;
        private String moveType;
        private JSON offset;

        public RectangleRule(String page,String left,String right,String top,String bottom){
            this.page = page;
            this.bottom = bottom;
            this.top = top;
            this.left = left;
            this.right = right;
        }
    }

    @Data
    public static class SealInfo {
        private String sealId;
        private String timeStamp;
        private String algo;

        public SealInfo(String sealId, String timeStamp){
            this.sealId = sealId;
            this.timeStamp = timeStamp;
            this.algo = "SM3withSM2";
        }
    }

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

    @Data
    public static class OperatorData {
        private String account;//账号
        private String name;
        private String idcardno;
        private String orgName;//机构名称
        private String roleName;//角色名称
        private String regionName;//归属区域
        private String regionCode;
    }
}
