package com.sifang.modules.esign.service;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.sifang.modules.config.EsignConfig;
import com.sifang.modules.esign.cn.tsign.hz.comm.EsignHttpHelper;
import com.sifang.modules.esign.cn.tsign.hz.comm.EsignHttpResponse;
import com.sifang.modules.esign.cn.tsign.hz.enums.EsignHeaderConstant;
import com.sifang.modules.esign.cn.tsign.hz.enums.EsignRequestType;
import com.sifang.modules.esign.cn.tsign.hz.exception.EsignDemoException;
import com.sifang.modules.esign.constants.ESignConstants;
import com.sifang.modules.esign.utils.ContentMD5Utils;
import com.sifang.modules.esign.vo.ComponentVo;
import com.sifang.modules.esign.vo.ContractTemplateVo;
import com.sifang.modules.esign.vo.FileVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;

/**
 * 上传文件 合同模板 业务
 */

@Service
public class ESignFileService {

    public static Logger logger= LoggerFactory.getLogger(ESignFileService.class);

    private static String eSignHost= EsignConfig.EsignHost;
    private static String eSignAppId=EsignConfig.EsignAppId;
    private static String eSignAppSecret=EsignConfig.EsignAppSecret;

    /**
     *  获取文件上传接口：本接口用于获取上传文件的服务端地址fileUploadUrl和文件fileId，请注意此时获取到的文件fileId为“未上传状态”
     *  返回的数据：fileUploadUrl 将文件流上传到该地址中
     *           fileId  需保存，可用于后续制作模板、签署相关操作
     */
    public static FileVo getUploadUrl(MultipartFile file) throws EsignDemoException, IOException {
         //自定义的文件封装类，传入文件地址可以获取文件的名称大小,文件流等数据
        String contentMd5= ContentMD5Utils.getFileContentMD5(file);
        String apiaddr="/v3/files/file-upload-url";
        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
        Map<String,Object> map=new HashMap<>();
        map.put("contentMd5",contentMd5);
        map.put("fileName",file.getOriginalFilename());
        map.put("fileSize",file.getBytes().length);
        map.put("convertToPDF",true);  //是否需要转换成PDF文档，默认值 false
        map.put("contentType",EsignHeaderConstant.CONTENTTYPE_STREAM.VALUE());
        Gson gson = new Gson();
        String jsonParm=gson.toJson(map);

        //请求方法
        EsignRequestType requestType= EsignRequestType.POST;
        //生成签名鉴权方式的的header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
        //发起接口请求
        EsignHttpResponse httpResponse=EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
        logger.info(">>>>>>>>>>>>>>>>>>>getUploadUrl httpResponse:{},data:{} ",httpResponse.getStatus(),httpResponse.getBody());
        JsonObject getUploadUrlJsonObject = gson.fromJson(httpResponse.getBody(), JsonObject.class);
        if(ESignConstants.SUCCESS.equals(getUploadUrlJsonObject.get("code").getAsString())){
            JsonObject data = getUploadUrlJsonObject.getAsJsonObject("data");
            //文件id后续发起签署使用
            String fileId =data.get("fileId").getAsString();
            String fileUploadUrl =data.get("fileUploadUrl").getAsString();
            logger.info(">>>>>>>>>>>getUploadUrl>获取文件id以及文件上传地址成功，文件id:{},上传链接:{}",fileId,fileUploadUrl);
            //文件流上传
            uploadFile(fileUploadUrl, file, fileId);
            FileVo fileVo=new FileVo();
            fileVo.setFileId(fileId);
            fileVo.setFileUploadUrl(fileUploadUrl);
            return fileVo;
        }else{
            throw new EsignDemoException("获取上传接口失败!失败原因:"+getUploadUrlJsonObject.get("message"));
        }
    }

    /**
     * 文件流上传：通过已获取到的fileUploadUrl（文件上传地址），使用 PUT 请求方法把文件流（二进制字节流）上传到服务端，确保文件流上传完毕后，文件fileId才会变更为“文件上传已完成”或“文件已转换pdf”的状态。
     * uploadUrl ：文件上传接口返回的数据
     */
    public static void uploadFile(String fileUploadUrl,MultipartFile file,String fileId) throws EsignDemoException, IOException {
        //根据文件地址获取文件contentMd5
        //自定义的文件封装类，传入文件地址可以获取文件的名称大小,文件流等数据
        String contentMd5= ContentMD5Utils.getFileContentMD5(file);
        //请求方法
        EsignRequestType requestType= EsignRequestType.PUT;
        EsignHttpResponse httpResponse=EsignHttpHelper.doUploadHttp(fileUploadUrl,requestType,file.getBytes(),contentMd5, EsignHeaderConstant.CONTENTTYPE_STREAM.VALUE(),true);
        logger.info(">>>>>>>>>>>>>>>>>>>uploadFile httpResponse:{},data:{} ",httpResponse.getStatus(),httpResponse.getBody());
        Gson gson = new Gson();
        JsonObject uploadFileResponseJsonObject = gson.fromJson(httpResponse.getBody(), JsonObject.class);
        String code = uploadFileResponseJsonObject.get("errCode").getAsString();
        if(ESignConstants.SUCCESS.equals(code)){
            //上传成功
        }else{
            throw new EsignDemoException("获取上传失败!失败原因:"+uploadFileResponseJsonObject.get("message"));
        }

    }

    /**
     * 查询文件上传状态（**合同填充后 获取下载地址，也用该方法）
     * 返回： fileDownloadUrl  文件下载地址
     *      fileStatus   文件状态
     */
    public static  EsignHttpResponse getFileStatus(String fileId) throws EsignDemoException {
        String apiaddr="/v3/files/"+fileId;
        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
        String jsonParm=null;
        //请求方法
        EsignRequestType requestType= EsignRequestType.GET;
        //生成签名鉴权方式的的header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
        //发起接口请求
        EsignHttpResponse httpResponse=EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
        logger.info(">>>>>>>>>>>>>>>>>>>getFileStatus httpResponse:{},data:{} ",httpResponse.getStatus(),httpResponse.getBody());
        return httpResponse;
    }


    /**
     *  获取制作合同模板页面
     *  返回：docTemplateId 合同模板ID
     *       docTemplateCreateUrl  制作合同模板的页面链接（有效期24小时）
     */
    public  static FileVo getTemplateCreateUrl(String fileId,String name) throws EsignDemoException {
        Gson gson = new Gson();
        //文件上传成功后文件会有一个异步处理过程，建议轮询文件状态，正常后发起签署
        //查询文件上传状态
        int i=0;
        Boolean fg=false;
        while(i<5) {
            EsignHttpResponse fileStatus = getFileStatus(fileId);
            JsonObject fileStatusJsonObject = gson.fromJson(fileStatus.getBody(), JsonObject.class);
            String status = fileStatusJsonObject.getAsJsonObject("data").get("fileStatus").getAsString();
            logger.info(String.format(">>>>>>>>>>>>>uploadFile  查询文件状态执行第%s次,status:%s",i+1,status));
            if("2".equalsIgnoreCase(status)||"5".equalsIgnoreCase(status)){//查询状态为2或者5代表文件准备完成
                logger.info(">>>>>>>>>>>>>>>>>>>uploadFile  文件准备完成");
                fg=true;
                break;
            }
            i++;
        }
        if(!fg){
            throw new EsignDemoException("文件转化中,请稍等!");
        }
        String apiaddr="/v3/doc-templates/doc-template-create-url";
        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
        Map<String,Object> map=new HashMap<>();
        map.put("docTemplateName",name);
        map.put("docTemplateType", "0");
        map.put("fileId",fileId);
        map.put("redirectUrl",EsignConfig.NotifyUrl+"/a/main/redirect/eSignSuccess");   //制作模板完成后页面重定向跳转地址（需符合 https /http 协议地址）

        String jsonParm=gson.toJson(map);
        //请求方法
        EsignRequestType requestType= EsignRequestType.POST;
        //生成签名鉴权方式的的header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
        //发起接口请求
        EsignHttpResponse response=EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
        logger.info(">>>>>>>>>>>>>>>>>>>getTemplateCreateUrl httpResponse:{},data:{} ",response.getStatus(),response.getBody());
        JsonObject getTemplateCreateUrlObject = gson.fromJson(response.getBody(), JsonObject.class);
        if(ESignConstants.SUCCESS.equals(getTemplateCreateUrlObject.get("code").getAsString())){
            String docTemplateCreateUrl = getTemplateCreateUrlObject.getAsJsonObject("data").get("docTemplateCreateUrl").getAsString();
            String docTemplateId = getTemplateCreateUrlObject.getAsJsonObject("data").get("docTemplateId").getAsString();
            logger.info(">>>>>>>>>getTemplateCreateUrl>制作合同模板的页面链接:{},合同模板id:{}",docTemplateCreateUrl,docTemplateId);
            FileVo fileVo=new FileVo();
            fileVo.setFileId(docTemplateId);
            fileVo.setFileUploadUrl(docTemplateCreateUrl);
            return fileVo;
        }else {
            throw new EsignDemoException("获取制作合同模板页面失败,失败原因："+getTemplateCreateUrlObject.get("message").getAsString());
        }

    }

    /**
     * 获取编辑合同模板页面
     * @return
     * @throws EsignDemoException
     */
    public static String getTemplateEditUrl(String docTemplateId) throws EsignDemoException {
        String apiaddr="/v3/doc-templates/"+docTemplateId+"/doc-template-edit-url";
        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
        Gson gson=new Gson();
        Map<String,Object> map=new HashMap<>();
        map.put("redirectUrl",EsignConfig.NotifyUrl+"/a/main/redirect/eSignSuccess"); //redirectUrl 编辑模板完成后页面重定向跳转地址
        String jsonParm=gson.toJson(map);
        //请求方法
        EsignRequestType requestType= EsignRequestType.POST;
        //生成签名鉴权方式的的header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
        //发起接口请求
        EsignHttpResponse response=EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
        logger.info(">>>>>>>>>>>>>>>>>>>getTemplateEditUrl httpResponse:{},data:{} ",response.getStatus(),response.getBody());
        JsonObject getTemplateEditUrlObject = gson.fromJson(response.getBody(), JsonObject.class);
        if(ESignConstants.SUCCESS.equals(getTemplateEditUrlObject.get("code").getAsString())){
            String docTemplateEditUrl = getTemplateEditUrlObject.getAsJsonObject("data").get("docTemplateEditUrl").getAsString();
            logger.info(">>>>>>>>>>>>>>>getTemplateEditUrl编辑合同模板的页面链接:{}",docTemplateEditUrl);
            return docTemplateEditUrl;
        }else{
            throw new EsignDemoException("编辑失败!失败原因:"+getTemplateEditUrlObject.get("message"));
        }
    }

    /**
     * 查询合同模板中控件详情 及 合同模板的底稿PDF文件下载链接
     */
    public static ContractTemplateVo getComponentsInfo(String docTemplateId) throws EsignDemoException {
        String apiaddr="/v3/doc-templates/"+docTemplateId;
        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
        String jsonParm=null;
        //请求方法
        EsignRequestType requestType= EsignRequestType.GET;
        //生成签名鉴权方式的的header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
        //发起接口请求
        EsignHttpResponse response=EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
        logger.info(">>>>>>>>>>>>>>>>>>>getComponentsInfo httpResponse:{},data:{} ",response.getStatus(),response.getBody());
        Gson gson=new Gson();
        JsonObject getComponentsInfoObject = gson.fromJson(response.getBody(), JsonObject.class);
        logger.info(">>>>>>>>>>>>>>getComponentsInfo 查询模板控件详情返回："+getComponentsInfoObject);
        ContractTemplateVo contractTemplateVo=new ContractTemplateVo();
        if(ESignConstants.SUCCESS.equals(getComponentsInfoObject.get("code").getAsString())){
            List<ComponentVo> componentVos=new ArrayList<>();
            /*JsonArray componentsArray = getComponentsInfoObject.getAsJsonObject("data").get("components").getAsJsonArray();
            for (JsonElement jsonElement : componentsArray) {
                JsonObject object = jsonElement.getAsJsonObject();
                String componentId=object.get("componentId").getAsString();   //控件ID（设置合同模板时由e签宝系统自动生成）
                String componentKey=object.get("componentKey").getAsString();  //控件Key（设置合同模板时由用户自定义）
                String componentName=object.get("componentName").getAsString();
                ComponentVo vo=new ComponentVo(componentId,componentKey,componentName);
                componentVos.add(vo);
            }
            logger.info(">>>>>>>>>>>>>>getComponentsInfo 查询模板控件详情 docTemplateEditUrl：{}",componentsArray);*/
            contractTemplateVo.setComponents(componentVos);
            String fileDownloadUrl= getComponentsInfoObject.getAsJsonObject("data").get("fileDownloadUrl").getAsString();
            logger.info(">>>>>>>>>>>>>>getComponentsInfo 查询模板控件详情 fileDownloadUrl：{}",fileDownloadUrl);
            contractTemplateVo.setFileDownloadUrl(fileDownloadUrl);
            return contractTemplateVo;
        }else{
            throw new EsignDemoException("查看失败!失败原因:"+getComponentsInfoObject.get("message"));
        }
    }

    /**
     * 填写模板生成文件(生成的就是合同文件)
     * 返回：fileId 填充后生成的文件ID
     */
    public static  FileVo createByDocTemplate(String docTemplateId,String fileName, List<ComponentVo> componentS) throws EsignDemoException {
        String apiaddr="/v3/files/create-by-doc-template";
        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
        Map<String,Object> map=new HashMap<>();
        map.put("docTemplateId",docTemplateId);
        map.put("fileName",fileName);
        map.put("requiredCheck",false);   // 是否校验PDF模板中必填控件，默认：false
        map.put("components",componentS);
        Gson gson = new Gson();
        String jsonParm=gson.toJson(map);
        //请求方法
        EsignRequestType requestType= EsignRequestType.POST;
        //生成签名鉴权方式的的header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
        //发起接口请求
        EsignHttpResponse response=EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
        logger.info(">>>>>>>>>>>>>>>>>>>createByDocTemplate response:{},data:{} ",response.getStatus(),response.getBody());
        JsonObject createByDocTemplateObject = gson.fromJson(response.getBody(), JsonObject.class);
        if(ESignConstants.SUCCESS.equals(createByDocTemplateObject.get("code").getAsString())){
            String fileId = createByDocTemplateObject.getAsJsonObject("data").get("fileId").getAsString();
            String fileDownloadUrl = createByDocTemplateObject.getAsJsonObject("data").get("fileDownloadUrl").getAsString();
            logger.info(">>>>>>>>>>>>>>>>>>>填充后文件id:{},文件下载链接:{}",fileId,fileDownloadUrl);
            FileVo fileVo=new FileVo();
            fileVo.setFileId(fileId);
            fileVo.setFileUploadUrl(fileDownloadUrl);
            return fileVo;
        }else {
            throw new EsignDemoException("填写模板生成文件失败!失败原因:"+createByDocTemplateObject.get("message"));
        }
    }

    /**
     * 删除模板 ：删除已存在的合同模板，模板删除后不可被恢复，只能再次重新制作模板。
     */
    public static EsignHttpResponse deleteDocTemplate(String docTemplateId) throws EsignDemoException {
        String apiaddr="/v3/doc-templates/"+docTemplateId;
        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
        String jsonParm="{}";
        //请求方法
        EsignRequestType requestType= EsignRequestType.DELETE;
        //生成签名鉴权方式的的header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
        //发起接口请求
        EsignHttpResponse response=EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
        logger.info(">>>>>>>>>>>>>>>>>>>deleteDocTemplate response:{},data:{} ",response.getStatus(),response.getBody());
        return response;
    }

    public static void main(String[] arr) throws EsignDemoException {
       /* Map<String,Object> map=new HashMap<>();
        map.put("contentMd5","eeee");
        map.put("fileName","绝地反击");
        map.put("fileSize",11);
        map.put("convertToPDF",false);  //是否需要转换成PDF文档，默认值 false。  true - 需要转换成PDF false - 无需转换成PDF
        map.put("contentType",EsignHeaderConstant.CONTENTTYPE_STREAM.VALUE());
        Gson gson = new Gson();
        String jsonParm=gson.toJson(map);
        System.out.println(jsonParm);*/
        //自定义的文件封装类，传入文件地址可以获取文件的名称大小,文件流等数据
        /*EsignFileBean esignFileBean = new EsignFileBean("E:\\Hx\\zhongling\\能辉光伏代理商合作协议.docx");
        String apiaddr="/v3/files/file-upload-url";
        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
        Map<String,Object> map=new HashMap<>();
        map.put("contentMd5",esignFileBean.getFileContentMD5());
        map.put("fileName",esignFileBean.getFileName());
        map.put("fileSize",esignFileBean.getFileSize());
        map.put("convertToPDF",false);  //是否需要转换成PDF文档，默认值 false。  true - 需要转换成PDF false - 无需转换成PDF
        map.put("contentType",EsignHeaderConstant.CONTENTTYPE_STREAM.VALUE());
        Gson gson = new Gson();
        String jsonParm=gson.toJson(map);
        //请求方法
        EsignRequestType requestType= EsignRequestType.POST;
        //生成签名鉴权方式的的header
        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(EsignConfig.EsignAppId,EsignConfig.EsignAppSecret,jsonParm,requestType.name(),apiaddr,true);
        //发起接口请求
        EsignHttpResponse httpResponse=EsignHttpHelper.doCommHttp(EsignConfig.EsignHost, apiaddr,requestType , jsonParm, header,true);
        JsonObject getUploadUrlJsonObject = gson.fromJson(httpResponse.getBody(), JsonObject.class);
        System.out.println(getUploadUrlJsonObject.get("code"));*/


        /*
        getTemplateCreateUrl("0486274a64b84eb2b7ec6a53e8859d7d","合同签约模板");*/
        /*getComponentsInfo("2dfac055b06f4c418c642ce98857b73d");*/

       /* List<ComponentVo> componentVos=new ArrayList<>();
        ComponentVo vo=new ComponentVo("01",new Date());
        componentVos.add(vo);
        ComponentVo vo2=new ComponentVo("02",12);
        componentVos.add(vo2);
        ComponentVo vo3=new ComponentVo("03","我的天啊");
        componentVos.add(vo3);
        createByDocTemplate("2dfac055b06f4c418c642ce98857b73d","女神来了",componentVos);*/

      /*  // 发起签署
        ESignSignService.createByFile("8a5e302e200d45e9a3eb4c66e633aae1","好好说话");*/

        //签约链接
      /*  ESignSignService.signUrl("84dc018633664363a8bd933a8aaa15e3");*/
        getFileStatus("5994937ffce84c47b24fba72fccb5bdb");
    }
}
