package com.sifang.modules.bestsign.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.sifang.modules.alioss.AliyunOSSClientUtil;
import com.sifang.modules.bestsign.utils.HttpClientSender;
import com.sifang.modules.bestsign.utils.RSAUtils;
import com.sifang.modules.sunshine.SystemSetting.utils.BusinessException;
import com.sifang.modules.sys.common.service.BaseService;
import com.sifang.modules.sys.common.utils.StringUtil;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//上上签 签约工具系列（目前不用这个里面的接口）
@Service
public class BestSignService extends BaseService {

    /**
     * 上上签功能
     */

    Logger logger = LoggerFactory.getLogger(this.getClass());

    //能辉用户账号
    @Value("${sign.account}")
    private String account;

    //开发者ID
    @Value("${sign.developer_id}")
    private String developerId;
    //开发者私钥
    @Value("${sign.developer_privateKey}")
    private String privateKey;

    @Value("${sign.server_host}")
    private String serverHost;

    @Value("${sign.callback}")
    private String signCallback;


    //上传 并 创建合同
    public String uploadVsCreatContract(String urlPath,String fileName,String title) throws IOException {
        String method = "/storage/contract/upload/";

        //body参数
        JSONObject requestBody = new JSONObject();
        requestBody.put("account",account);
        //文件内容
        //以下为文件转换为BASE64字符串及计算文件MD5的示例代码，请替换
        URL url = new URL(urlPath);
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
        httpConn.connect();
        InputStream fis = httpConn.getInputStream();
        try(
            ByteArrayOutputStream bos = new ByteArrayOutputStream();){
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1){
                bos.write(b, 0, n);
            }
            byte[] bdata = bos.toByteArray();
            String fmd5 = DigestUtils.md5Hex(bdata);
            String fdata = Base64.encodeBase64String(bdata);
            requestBody.put("fmd5",fmd5);
            requestBody.put("fdata", fdata);
            requestBody.put("fpages", "1"); //文件总页数
            requestBody.put("fname", fileName);//文件名称 文件名必须带上后缀名，例如“XXXX.pdf”
            requestBody.put("ftype", "pdf"); //文件类型，目前仅支持pdf
            requestBody.put("title", title);  //合同标题
        }catch (Exception e) {
            e.printStackTrace();
            logger.error("上传 并 创建合同  读取文件异常 e:",e);
            throw new BusinessException("上传并创建合同,读取文件异常,"+e.getMessage());
        }
        String requestJson=requestBody.toJSONString();
        logger.info("上传 并 创建合同   uploadVsCreatContract  requestParam:{}",requestJson);
        JSONObject userObj =postClit(requestJson,method);
        JSONObject data = userObj.getJSONObject("data");
        //对返回data进行处理
        if(data!=null){
            String contractId = data.getString("contractId");  //创建的合同ID，在后续接口中使用
            logger.info("上传 并 创建合同   uploadVsCreatContract  合同id contractId:{}",contractId);
            return contractId;
        }else{
            throw new BusinessException("创建合同失败，上上签没有返回合同id");
        }
    }

    /**
     * 手动获取签署链接
     * @param contractId  合同id
     * @param account   签署人账号  一般
     */
    public String getHandSignUrl(String contractId,String account,String sid,String pageNum,String x,String y){
        String method = "/contract/send/";
        //body参数
        JSONObject requestBody = new JSONObject();
        requestBody.put("contractId",contractId);  //合同编号
        requestBody.put("signer",account);  //签署者账号
        requestBody.put("isAllowChangeSignaturePosition","1");//在有指定signaturePositions参数的情况下，是否允许拖动签名位置。取值1/0。（0：不允许，1：允许，下面都是这样的）
        requestBody.put("sid",sid); //开发者自定义的签署流水号（比如第几次签署之类），如有填写，则在异步推送签署结果时包含此签署流水号
       // requestBody.put("vcodeMobile",account);  //todo 验证码手机号 //
        requestBody.put("returnUrl","");//手动签署时，当用户签署完成后，签署页面指定回跳的页面地址，如果没填此参数则签署完成后跳转到合同预览页面

        List<JSONObject> signaturePositions = Lists.newArrayList(); //签名位置坐标列表
        JSONObject signaturePosition = new JSONObject();
        signaturePosition.put("pageNum", pageNum); //签名位置页码
        signaturePosition.put("x", x); //横坐标，按页面尺寸的百分比计算，取值0.0 - 1.0。以左上角为原点
        signaturePosition.put("y", y); //纵坐标，同上
        signaturePositions.add(signaturePosition);
        JSONObject signaturePosition2 = new JSONObject(); //是为了 日期签署
        signaturePosition2.put("pageNum", ""); //签名位置页码
        signaturePosition2.put("x", ""); //横坐标，按页面尺寸的百分比计算，取值0.0 - 1.0。以左上角为原点
        signaturePosition2.put("y", ""); //纵坐标，同上
        signaturePosition2.put("type","data");
        signaturePosition2.put("rptPageNums","");
        signaturePosition2.put("fontSize","");
       // signaturePosition2.put("dateTimeFormat","yyyy-MM-dd");
       // signaturePositions.add(signaturePosition2);
        requestBody.put("signaturePositions",signaturePositions);

        requestBody.put("pushUrl","");//签署完成推送地址 //todo

        List<String> verifyType=new ArrayList<>();  //签署校验类型
        verifyType.add("sms");
       // requestBody.put("verifyType",verifyType); //todo

        String requestJson=requestBody.toJSONString();
        logger.info("手动获取签署链接   getHandSignUrl  requestParam:{}",requestJson);
        JSONObject userObj =postClit(requestJson,method);
        JSONObject data = userObj.getJSONObject("data");
        if(data!=null){
            String url=data.getString("url");
            logger.info("手动获取签署链接   getHandSignUrl URL:{}",url);
            return url;
        }else {
            throw new BusinessException("手动获取签署链接失败，没有返回合同地址");
        }
    }

    /**
     * 锁定并结束合同
     */
    public void lockVsFinishContract(String contractId){
         logger.info(">>>>>>锁定并结束合同  lockVsFinishContract  contractId：{}",contractId);
        String method = "/storage/contract/lock/";

        //body参数
        JSONObject requestBody = new JSONObject();
        requestBody.put("contractId",contractId);  //合同编号

        String requestJson=requestBody.toJSONString();
        logger.info("锁定并结束合同   lockVsFinishContract  requestParam:{}",requestJson);
        postClit(requestJson,method);
    }


    public JSONObject postClit(String requestJsonStr,String method){
        logger.info("postClit method:{}",method);

        String urlSignParams = "?developerId=%s&rtick=%s&signType=rsa&sign=%s";
        // 生成一个时间戳参数
        String rtick = RSAUtils.getRtick();
        // 计算参数签名
        String paramsSign = RSAUtils.calcRsaSign(developerId,
                privateKey, serverHost, method, rtick, null,
                requestJsonStr);
        // 签名参数追加为url参数
        String fullUrlParams = String.format(urlSignParams, developerId,
                rtick, paramsSign);
        try {
            String responseBody = HttpClientSender.sendHttpPost(serverHost, method,
                    fullUrlParams, requestJsonStr);

            logger.info("postClit 返回数据  responseBody:{}",responseBody);
            // 返回结果解析
            JSONObject userObj = JSON.parseObject(responseBody);
            // 返回errno为0，表示成功，其他表示失败
            if (userObj.getIntValue("errno") == 0) {
                return userObj;
            } else {
                //接口返回异常
                logger.error("上上签请求 失败 error:{},errmsg:{}",userObj.getIntValue("errno"),userObj.getString("errmsg"));
                throw new BusinessException("请求上上签失败，失败原因："+userObj.getString("errmsg"));
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new BusinessException("上上签请求失败！"+e);
        }
    }


    /**
     * GET方法示例
     * 下载合同PDF文件  返回的是 文件的字节，上传到阿里云服务器
     * @param contractId  合同编号
     */
    public Map<String, Object> contractDownload(String contractId,String traderName) throws IOException {
        logger.info("contractDownload contractId:{}",contractId);
        String urlSignParams = "?developerId=%s&rtick=%s&signType=rsa&sign=%s";
        String method = "/storage/contract/download/";
        //uri参数
        //合同ID
        String urlParams = "contractId="+contractId+"";
        // 生成一个时间戳参数
        String rtick = RSAUtils.getRtick();
        // 计算参数签名
        String paramsSign = RSAUtils.calcRsaSign(this.developerId,
                this.privateKey, this.serverHost, method, rtick, urlParams,
                null);
        // 签名参数追加为url参数
        String fullUrlParams = String.format(urlSignParams, this.developerId,
                rtick, paramsSign) + "&" + urlParams;
        byte[] responseBody=HttpClientSender.sendHttpGet(this.serverHost, method,
                fullUrlParams);

        String filename = traderName+"合同.pdf";
        String extName = ".pdf";
        String fileInfo = null;
        Map<String, Object> ret = new HashMap<>();
        try {
            fileInfo = AliyunOSSClientUtil.uploadImage(responseBody, extName, filename);
            if (StringUtils.isNotBlank(fileInfo)) {
                ret.put("path", StringUtil.convertBackSlant(fileInfo));
                ret.put("extName", extName);
                ret.put("filename", filename);
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return ret;
    }

    /**
     * 撤销合同
     */
    public void cancelContract(String contractId){
        logger.info(">>>>>>上上签撤销合同  cancelContract  contractId：{}",contractId);
        String method = "/contract/cancel/";

        //body参数
        JSONObject requestBody = new JSONObject();
        requestBody.put("contractId",contractId);  //合同编号

        String requestJson=requestBody.toJSONString();
        logger.info("上上签撤销合同   cancelContract  requestParam:{}",requestJson);
        postClit(requestJson,method);
    }


    public static void main(String[] args) throws IOException {
        String developerId="1728530588012338059";
        String privateKey="MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAK3dqztB75XwK8OY7EBn1YPrRxjxDw1+NsYahzHIhTlpnPT7FNodHOftfvE1DKE+z24qBblb67/RtsQ7XMh1H2LtRgVdAYU+9zjA4qEUusv4HvxYI/F5bRyCILUF5/8oiE2/MNgkcaNwtTGUHGB+A0jSp4MB1fm4g7PKxvkoBd0fAgMBAAECgYBF6mfbEm63yraulyYZ2CdiPxB+FSHKeUCpdS18dXgtWC0HzpfaBe8DzNtJP93uUYW0dS2MFky8/CYUzxJGgeK2h4JAejcJJ6XZbK5d5ggWCyI+/XAta8RRBcK4SeyX2VgfdzBurb9WMmmAMFC2gkwBm3MCPRsb17T1Q8rwMioKUQJBAPdlULjP+tLSsJWdj9emLAPkM2uDwODgRSRrAT8FKv2d5c79VCyNE506R8EhPi5S5a2wTXb5L9u+KQNE52ZbOYMCQQCz6a5we0GA180X+uLrOz8dMzTyJr0FQE66ynNeFX+oSJCMjp0bLGz+l+TQRZLE2l8lxpCjYvyKpIFjbv3LICc1AkAfMSf/VUGzqRrYklgbgXkVOIV/Lcp4z+4HzHIIxxcHiQv7kBc30sXBUiLP5+gWIR+SSaNKt9pf41b6cYqXbjMPAkA7lbQhKqEaE96oB35p27healwpqqzFdXPdpzkoOsSJrma5Nm5P1pnOg+3TEIe4TH5gm2/BvQHYxPzZOqQxRtfVAkAKtK20URnBre/5cglzuJjwLU6t1QqkgroiD3jwezPr5sRznCHgL9N7vaNicx0iMcC/SJsaizoFK5OOSvaFLgSm";
        String serverHost="https://openapi.bestsign.info/openapi/v2";

        String urlSignParams = "?developerId=%s&rtick=%s&signType=rsa&sign=%s";
        String method = "/storage/contract/upload/";
        //body参数
        JSONObject requestBody = new JSONObject();
        requestBody.put("account","13955174824");
        //文件内容
        //以下为文件转换为BASE64字符串及计算文件MD5的示例代码，请替换
        URL url = new URL("https://nhet-test.oss-cn-shanghai.aliyuncs.com/energy_img/pdf/20240820/f6d6afce27fa4fefbb5adafa05b14d37/137088626a7d4074abe8408d2f19dbcd.pdf");
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
        httpConn.connect();
        InputStream fis = httpConn.getInputStream();
        try(
            /*FileInputStream fis = new FileInputStream("https://nhet-test.oss-cn-shanghai.aliyuncs.com/energy_img/pdf/20240820/f6d6afce27fa4fefbb5adafa05b14d37/137088626a7d4074abe8408d2f19dbcd.pdf");*/
            ByteArrayOutputStream bos = new ByteArrayOutputStream();){
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1){
                bos.write(b, 0, n);
            }
            byte[] bdata = bos.toByteArray();
            String fmd5 = DigestUtils.md5Hex(bdata);
            System.out.println("fmd5:"+fmd5);
            String fdata = Base64.encodeBase64String(bdata);
            System.out.println("base64:"+fdata);
            requestBody.put("fmd5",fmd5);
            requestBody.put("fdata", fdata);
            requestBody.put("fpages", "1");
            requestBody.put("fname", "测试文件.pdf");
            requestBody.put("ftype", "pdf");
            requestBody.put("title", "测试");
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("读取文件异常");
        }
        String requestJson=requestBody.toJSONString();

        // 生成一个时间戳参数
        String rtick = RSAUtils.getRtick();
        // 计算参数签名
        String paramsSign = RSAUtils.calcRsaSign(developerId,
                privateKey, serverHost, method, rtick, null,
                requestJson);
        System.out.println(paramsSign);
        // 签名参数追加为url参数
        String fullUrlParams = String.format(urlSignParams, developerId,
                rtick, paramsSign);
        System.out.println(fullUrlParams);
        // 发送POST请求
        String responseBody = HttpClientSender.sendHttpPost(serverHost, method,
                fullUrlParams, requestJson);


        System.out.println(responseBody);
        // 返回结果解析
        JSONObject userObj = JSON.parseObject(responseBody);
        // 返回errno为0，表示成功，其他表示失败
        if (userObj.getIntValue("errno") == 0) {
            JSONObject data = userObj.getJSONObject("data");
            if (data != null) {
                //对返回data进行处理
                //String taskId = data.getString("taskId");
            }
        } else {
            //接口返回异常
            System.out.println(userObj.getIntValue("errno"));
            System.out.println(userObj.getString("errmsg"));
        }




    }

}
