package com.kingdee.eas.custom.esign.osf;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.bos.bsf.service.app.IHRMsfService;
import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
import com.kingdee.bos.metadata.entity.SelectorItemCollection;
import com.kingdee.bos.metadata.entity.SelectorItemInfo;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.eas.custom.esign.*;
import com.kingdee.eas.custom.esign.bizEnum.ComponentTypeEnum;
import com.kingdee.eas.custom.esign.bizEnum.EsignStatusEnum;
import com.kingdee.eas.custom.esign.tsign.hz.comm.EsignHttpResponse;
import com.kingdee.eas.custom.esign.tsign.hz.exception.EsignException;
import com.kingdee.eas.custom.esign.util.EsignConfig;
import com.kingdee.eas.custom.esign.util.EsignHttpUtil;
import com.kingdee.eas.util.app.DbUtil;
import com.kingdee.jdbc.rowset.IRowSet;
import org.apache.commons.lang3.StringUtils;

import java.net.URISyntaxException;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * description: Create_by_fileOSFService <br>
 * date: 28/11/2025 上午 9:46 <br>
 * author: lhbj <br>
 * version: 1.0 <br>
 */
public class Create_by_fileOSFService implements IHRMsfService {
    private static final String SUCCESS_CODE = "0";
    private static final String PREVIEW_OPERATION = "预览";

    private static final int MAX_RETRY_COUNT = 20;
    private static final int RETRY_INTERVAL_SECONDS = 3;

    @Override
    public Object process(Context context, Map map) throws EASBizException, BOSException {

        String mack = (String) map.get("mack");
        String data = (String) map.get("data");
        Map<String, Object> resul = Maps.newHashMap();
        try {
            JSONObject jsonObject = JSON.parseObject(data);
            if ("preview".equals(mack)) {
                for (Map.Entry<String, Object> fileEntry : jsonObject.entrySet()) {
                    JSONObject fieldObject = (JSONObject) fileEntry.getValue();
                    EsignHttpResponse response = this.previewFile(context, fieldObject, "预览");
                    if (response.getStatus() >= 200 && response.getStatus() < 300) {
                        resul.putAll(this.processFileResponse(response, context));
                    } else {
                        resul.put("code", response.getStatus());
                        resul.put("message", "网络异常");
                        resul.put("data", null);
                    }
                }
            } else {
                Map<String, Object> signMap = Maps.newHashMap();
                String sourceId = jsonObject.getString("sourceId");
                String signFlowTitle = jsonObject.getString("signFlowTitle");
                String personId = jsonObject.getString("personId");
                String operatorId = jsonObject.getString("operatorId");
                //文件
                JSONObject templateInfo = jsonObject.getJSONObject("templateInfo");
                //设置待签署文件信息
                List<Map<String, Object>> docs = null;

                    docs = this.addDocs(context, jsonObject, templateInfo);
                    List<Map<String, Object>> signDocs = Lists.newArrayList();
                    for (Map<String, Object> doc : docs) {
                        Map<String, Object> docNew = new HashMap<>(doc);
                        docNew.remove("signListGroup");
                        signDocs.add(docNew);
                    }
                    signMap.put("docs", signDocs);

                if (null != docs) {
                    //签署流程配置项
                    Map<String, Object> signFlowConfig = this.addSignFlowConfig(context, signFlowTitle, jsonObject);
                    signMap.put("signFlowConfig", signFlowConfig);
                    //签署方信息
                    JSONObject signInfo = jsonObject.getJSONObject("signInfo");
                    JSONArray signs = signInfo.getJSONArray("signers");
                    List<Map<String, Object>> signers = this.addSigners(context, signs, docs, sourceId);
                    signMap.put("signers", signers);
                    //抄送方信息
                    JSONArray copis = signInfo.getJSONArray("copiers");
                    List<Map<String, Object>> copiers = this.addCopiers(context, copis);
                    if (copiers.size() > 0) {
                        signMap.put("copiers", copiers);
                    }
                    //必须要存在签署文件才能签署

                    if (docs.size() > 0) {
                        System.out.println("--------------------------------------------------------------------------------------");
                        System.out.println("signMap:" + JSON.toJSONString(signMap));
                        System.out.println("--------------------------------------------------------------------------------------");
                        EsignHttpResponse response = EsignHttpUtil.create_by_file(context, personId, signFlowTitle, operatorId, sourceId, JSON.toJSONString(signMap));
                        if (response.getStatus() >= 200 && response.getStatus() < 300) {
                            JSONObject body = JSON.parseObject(response.getBody());
                            resul.putAll(body);
                        } else {
                            resul.put("code", response.getStatus());
                            resul.put("message", "网络异常");
                            resul.put("data", null);
                        }
                    }
                }
            }
        } catch (EsignException | URISyntaxException | SQLException e) {
            e.printStackTrace();
            resul.put("code", 400);
            resul.put("message", e.getMessage());
            resul.put("data", null);
        }
        return resul;
    }

    /**
     * 根据”填写模板生成文件“返回的文件id查询文件处理状态
     * 需要阻塞等待这个状态变为2或者5才能调用发起签署接口
     *
     * @param response
     * @param context
     * @return
     */
    public Map<String, Object> processFileResponse(EsignHttpResponse response, Context context) {
        Map<String, Object> result = Maps.newHashMap();
        JSONObject body = JSON.parseObject(response.getBody());

        if (!SUCCESS_CODE.equals(String.valueOf(body.get("code")))) {
            result.putAll(body);
            return result;
        }

        JSONObject jsonData = body.getJSONObject("data");
        String fileId = jsonData.getString("fileId");
        JSONObject pollData = pollFileDownloadUrl(context, fileId);

        if (null != pollData && StringUtils.isNotBlank(pollData.getString("fileDownloadUrl"))) {
            jsonData.putAll(pollData);
        }
        result.putAll(body);
        System.out.println("processFileResponse:" + result);
        return result;
    }

    /**
     * 阻塞循环调用获取文件信息接口
     *
     * @param context
     * @param fileId
     * @return
     */
    private JSONObject pollFileDownloadUrl(Context context, String fileId) {
        for (int i = MAX_RETRY_COUNT; i > 0; i--) {
            try {
                JSONObject data = tryGetFileDownloadUrl(context, fileId);
                if (null != data && StringUtils.isNotBlank(data.getString("fileDownloadUrl"))) {
                    return data;
                }
                TimeUnit.SECONDS.sleep(RETRY_INTERVAL_SECONDS);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            } catch (Exception e) {
                // 记录日志，继续重试
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 等待这个状态变为2或者5才返回
     *
     * @param context
     * @param fileId
     * @return
     */
    private JSONObject tryGetFileDownloadUrl(Context context, String fileId) {
        try {
            EsignHttpResponse response = EsignHttpUtil.getFileStatus(context, fileId, PREVIEW_OPERATION);

            if (response.getStatus() < 200 || response.getStatus() >= 300) {
                return null;
            }

            JSONObject responseBody = JSON.parseObject(response.getBody());
            if (!SUCCESS_CODE.equals(String.valueOf(responseBody.get("code")))) {
                return null;
            }

            JSONObject data = responseBody.getJSONObject("data");
            String fileStatus = data.getString("fileStatus");
            Set<String> COMPLETED_STATUS = Sets.newHashSet();
            COMPLETED_STATUS.add("2");
            COMPLETED_STATUS.add("5");
            if (COMPLETED_STATUS.contains(fileStatus)) {
                return data;
            }
        } catch (EsignException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 设置待签署文件位置信息
     *
     * @param context
     * @param fileId
     * @param keyword
     * @param sourceId
     * @return
     * @throws EsignException
     */
    public JSONObject addPositions(Context context, String fileId, String keyword, String sourceId) throws EsignException {
        List<String> keywords = Lists.newArrayList();
        keywords.add(keyword);
        JSONObject coordinate = null;
        System.out.println("respPosition:fileId:" + fileId);
        System.out.println("respPosition:keywords:" + keywords);
        EsignHttpResponse respPosition = EsignHttpUtil.keyword_positions(context, fileId, keywords, sourceId);
        System.out.println("respPosition:" + respPosition.getBody());
        if (respPosition.getStatus() >= 200 && respPosition.getStatus() < 300) {
            JSONObject resp = JSON.parseObject(respPosition.getBody());
            if ("0".equals(String.valueOf(resp.get("code")))) {
                JSONObject keywordData = (JSONObject) resp.get("data");
                if (null != keywordData) {
                    JSONArray keywordPositions = keywordData.getJSONArray("keywordPositions");

                    if (null != keywordPositions && keywordPositions.size() > 0) {
                        JSONObject keywordPs = keywordPositions.getJSONObject(keywordPositions.size() - 1);

                        if (keywordPs.getBoolean("searchResult")) {
                            if (null != keywordPs) {
                                JSONArray positions = keywordPs.getJSONArray("positions");

                                if (null != positions && positions.size() > 0) {
                                    JSONObject position = positions.getJSONObject(positions.size() - 1);

                                    if (null != position) {
                                        Object pageNum = position.get("pageNum");
                                        JSONArray coordinates = position.getJSONArray("coordinates");

                                        if (null != coordinates && coordinates.size() > 0) {
                                            coordinate = coordinates.getJSONObject(coordinates.size() - 1);
                                            if (null != coordinate) {
                                                coordinate.put("positionPage", pageNum);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            System.out.println("coordinate:" + coordinate);
        }
        return coordinate;
    }

    /**
     * 获取签署人的签署区
     *
     * @param context
     * @param fields
     * @param fileId
     * @param sourceId
     * @return
     * @throws EsignException
     */
    public Map<String, Map<String, Map<String, Object>>> addsignAreaList(Context context, Map<String, Object> fields, String fileId, String sourceId,String docTemplateId) throws EsignException, BOSException, EASBizException, SQLException {
        //Map<String, List<Map<String, Object>>> signListGroup = Maps.newHashMap();
        Map<String, Map<String, Map<String, Object>>> signMapGroup = Maps.newHashMap();
        //获取文件模版字段
        IESignTemplateFileEntry ieSignTemplateFileEntry = ESignTemplateFileEntryFactory.getLocalInstance(context);
        SelectorItemCollection selColl = new SelectorItemCollection();
        selColl.add(new SelectorItemInfo("*"));
        selColl.add(new SelectorItemInfo("fields.*"));
        selColl.add(new SelectorItemInfo("fields.relatedControl.*"));
        String sel = "select fid from CT_ESI_ESignTemplateFileEntry where cfeSignTemplateId = ?";
        IRowSet rs = DbUtil.executeQuery(context,sel.toString(),new Object[]{docTemplateId});
        String Entryid="";
        if(rs.next()){
            Entryid=rs.getString("fid");
        }
        ESignTemplateFileEntryInfo eSignTemplateFileEntry = ieSignTemplateFileEntry.getESignTemplateFileEntryInfo(new ObjectUuidPK(Entryid),selColl);
        Map<String,ESignTemplateFileEntryFieldInfo> fieldsMap = Maps.newHashMap();
        ESignTemplateFileEntryFieldCollection entryFieldCollection = eSignTemplateFileEntry.getFields();
        for(int i=0;i<entryFieldCollection.size();i++){
            ESignTemplateFileEntryFieldInfo fieldInfo=entryFieldCollection.get(i);
            //失效的控件跳过
            if(fieldInfo.isInvalid()){
               continue;
            }
            String fieldId =fieldInfo.getTemplateFieldId().toString();

            JSONObject field= (JSONObject) fields.get(fieldId);
            if (ComponentTypeEnum.SIGN_AREA.equals(fieldInfo.getComponentType())) {
                Map<String, Object> signMap = Maps.newHashMap();
                if(StringUtils.isBlank(fieldInfo.getSigningParty())){
                    Map<String, Object> errMap = Maps.newHashMap();
                    errMap.put("模版", eSignTemplateFileEntry.getName());
                    errMap.put("控件", fieldInfo.getTemplateFieldName());
                    errMap.put("内容", "签署方为空请维护！");
                    throw new EsignException(JSON.toJSONString(errMap));
                }
                signMap.put("key", fieldInfo.getSigningParty());
                signMap.put("fileId", fileId);
                signMap.put("fieldId", fieldInfo.getTemplateFieldId());
                signMap.put("signFieldType", 0);
                String keyword =fieldInfo.getTemplateFieldName();
                if (keyword.indexOf("骑缝") >= 0) {
                    signMap.put("signFieldStyle", 2);
                    signMap.put("positionX", fieldInfo.getPositionX());
                    signMap.put("positionY", fieldInfo.getPositionY());
                    signMap.put("positionPage", fieldInfo.getPageNum());

                }else {
                    signMap.put("signFieldStyle", 1);
                    if(null==fieldInfo.getPositionX()&&null==fieldInfo.getPositionY()){
                        Map<String, Object> errMap = Maps.newHashMap();
                        errMap.put("模版", eSignTemplateFileEntry.getName());
                        errMap.put("控件", fieldInfo.getTemplateFieldName());
                        errMap.put("内容", "印章坐标为空请维护！");
                        throw new EsignException(JSON.toJSONString(errMap));
                    }
                    signMap.put("positionX", fieldInfo.getPositionX());
                    signMap.put("positionY", fieldInfo.getPositionY());
                    signMap.put("positionPage", fieldInfo.getPageNum());
                }
                Map<String, Map<String, Object>> skMap = signMapGroup.get((String) signMap.get("key"));
                if (null == skMap) {
                    skMap = Maps.newHashMap();
                    signMapGroup.put((String) signMap.get("key"), skMap);
                }
                skMap.put(fieldInfo.getTemplateFieldId(),signMap);
            }
            //签署日期
            if(ComponentTypeEnum.DATESIGNATURE.equals(fieldInfo.getComponentType())) {
                fieldsMap.put(fieldId, fieldInfo);
            }
        }
        //签署日期
        for(Map.Entry<String,ESignTemplateFileEntryFieldInfo> fieldLinkEntry : fieldsMap.entrySet()){
            //签署日期
            ESignTemplateFileEntryFieldInfo fieldLink=fieldLinkEntry.getValue();
            //签署方
            ESignTemplateFileEntryFieldInfo fieldInfo=fieldLink.getRelatedControl();
            if(null==fieldInfo){
                Map<String, Object> errMap = Maps.newHashMap();
                errMap.put("模版", eSignTemplateFileEntry.getName());
                errMap.put("控件", fieldLink.getTemplateFieldName());
                errMap.put("内容", "签署方关联关系为空请维护！");
                throw new EsignException(JSON.toJSONString(errMap));
            }
            if(!ComponentTypeEnum.SIGN_AREA.equals(fieldInfo.getComponentType())){
                Map<String, Object> errMap = Maps.newHashMap();
                errMap.put("模版", eSignTemplateFileEntry.getName());
                errMap.put("控件", fieldLink.getTemplateFieldName());
                errMap.put("内容", "关联关系不为签署区，请检查！");
                throw new EsignException(JSON.toJSONString(errMap));
            }
            Map<String, Object> signMap = Maps.newHashMap();
            //签署日期坐标
            Map<String, Object> signDateConfig = Maps.newHashMap();
            signDateConfig.put("showSignDate", 1);
            if (null!=fieldLink.getPositionX()&&null!=fieldLink.getPositionY()) {
                signDateConfig.put("signDatePositionX", fieldLink.getPositionX());
                signDateConfig.put("signDatePositionY", fieldLink.getPositionY());
            }
            if (null!=fieldLink.get("fontSize")) {
                signDateConfig.put("fontSize", fieldLink.get("fontSize"));
            }
            if (null!=fieldLink.get("dateFormat")) {
                signDateConfig.put("dateFormat", fieldLink.get("dateFormat"));
            }
            signMap.put("signDateConfig", signDateConfig);
            signMap.put("key", fieldInfo.getSigningParty());
            signMap.put("fileId", fileId);
            signMap.put("signFieldType", 0);
            String keyword =fieldInfo.getTemplateFieldName();
            if (keyword.indexOf("骑缝") >= 0) {
                signMap.put("signFieldStyle", 2);
                signMap.put("positionX", fieldInfo.getPositionX());
                signMap.put("positionY", fieldInfo.getPositionY());
                signMap.put("positionPage", fieldInfo.getPageNum());
            }else {
                signMap.put("signFieldStyle", 1);
                if(null==fieldInfo.getPositionX()&&null==fieldInfo.getPositionY()){
                    Map<String, Object> errMap = Maps.newHashMap();
                    errMap.put("模版", eSignTemplateFileEntry.getName());
                    errMap.put("控件", fieldInfo.getTemplateFieldName());
                    errMap.put("内容", "印章坐标为空请维护！");
                    throw new EsignException(JSON.toJSONString(errMap));
                }
                signMap.put("positionX", fieldInfo.getPositionX());
                signMap.put("positionY", fieldInfo.getPositionY());
                signMap.put("positionPage", fieldInfo.getPageNum());
            }
            Map<String, Map<String, Object>> skMap = signMapGroup.get((String) signMap.get("key"));
            if (null == skMap) {
                skMap = Maps.newHashMap();
                signMapGroup.put((String) signMap.get("key"), skMap);
            }
            skMap.remove(fieldInfo.getTemplateFieldId());
            skMap.put(fieldLink.getTemplateFieldId(),signMap);
        }

        System.out.println("signMapGroup:" + signMapGroup);
        return signMapGroup;
    }

    /**
     * 设置待签署文件信息
     *
     * @param context
     * @param jsonObject
     * @param templateInfo
     * @return
     * @throws EsignException
     */
    public List<Map<String, Object>> addDocs(Context context, JSONObject jsonObject, JSONObject templateInfo) throws EsignException, EASBizException, BOSException, SQLException {
        //设置待签署文件信息
        Map<String, Object> resul = Maps.newHashMap();
        List<Map<String, Object>> docs = Lists.newArrayList();
        for (Map.Entry<String, Object> fileEntry : templateInfo.entrySet()) {
            JSONObject fieldObject = (JSONObject) fileEntry.getValue();
            String docTemplateId = fieldObject.getString("id");
            String fileName = fieldObject.getString("name");
            Object order = fieldObject.get("order");
            String sourceId = jsonObject.getString("sourceId");

            EsignHttpResponse response = this.previewFile(context, fieldObject, sourceId);
            resul.put("id", docTemplateId);
            resul.put("name", fileName);
            if (response.getStatus() >= 200 && response.getStatus() < 300) {
                Map<String, Object> body = this.processFileResponse(response, context);
                if ("0".equals(String.valueOf(body.get("code")))) {
                    JSONObject file = (JSONObject) body.get("data");
                    Map<String, Object> doc = Maps.newHashMap();
                    doc.put("fileId", file.get("fileId"));
                    doc.put("fileName", fileName);
                    if (null != order) {
                        doc.put("order", Integer.parseInt(String.valueOf(order)));
                    }
                    System.out.println("addDocs:" + fieldObject);
                    JSONObject fields = fieldObject.getJSONObject("fields");
                    //取得这个文件的签署人的签署区
                    Map<String,  Map<String, Map<String, Object>>> signAreaList = this.addsignAreaList(context, fields, (String) file.get("fileId"), sourceId,docTemplateId);
                    doc.put("signListGroup", signAreaList);
                    docs.add(doc);
                } else {
                    //文件模板生成失败
                    resul.putAll(body);
                    throw new EsignException(JSON.toJSONString(resul));
                }
            } else {
                throw new EsignException(JSON.toJSONString(response));
            }
        }
        return docs;
    }

    /**
     * 抄送方信息
     *
     * @param copis
     * @return
     */
    public List<Map<String, Object>> addCopiers(Context context, JSONArray copis) {
        List<Map<String, Object>> copiers = Lists.newArrayList();
        for (int i = 0; i < copis.size(); i++) {
            JSONObject cop = copis.getJSONObject(i);
            Map<String, Object> copierPsn = Maps.newHashMap();
            Map<String, Object> copierPsnInfo = Maps.newHashMap();
            copierPsnInfo.put("psnAccount", cop.getString("psnAccount"));
            copierPsn.put("copierPsnInfo", copierPsnInfo);
            copiers.add(copierPsn);
        }
        return copiers;
    }

    /**
     * 添加签署组织
     *
     * @param context
     * @param orgSignerInfo
     * @param docs
     * @param sourceId
     * @return
     * @throws EsignException
     * @throws URISyntaxException
     */
    public Map<String, Object> addOrgSignerInfo(Context context, JSONObject orgSignerInfo, List<Map<String, Object>> docs, String sourceId) throws EsignException, URISyntaxException {
        List<Map<String, Object>> resulList = Lists.newArrayList();
        List<Map<String, Object>> resulErrList = Lists.newArrayList();
        Map<String, Object> resul = Maps.newHashMap();
        Map<String, Object> signMapInfo = Maps.newHashMap();
        Map<String, Object> orgPsnSignMap = Maps.newHashMap();
        String orgName = orgSignerInfo.getString("orgName");
        EsignHttpResponse response = EsignHttpUtil.getOrgIdentity_infoByOrgName(context, orgName);
        if (response.getStatus() >= 200 && response.getStatus() < 300) {
            JSONObject body = JSON.parseObject(response.getBody());
            if ("0".equals(String.valueOf(body.get("code")))) {
                JSONObject orgPsn = body.getJSONObject("data");
                String orgId = orgPsn.getString("orgId");
                orgName = orgPsn.getString("orgName");
                //自动落章只能传orgId
                if (true == orgSignerInfo.getBoolean("isRadio")) {
                    orgPsnSignMap.put("orgId", orgId);

                } else {
                    orgPsnSignMap.put("orgName", orgName);
                    Map<String, Object> transactorInfo = Maps.newHashMap();
                    transactorInfo.put("psnAccount", orgSignerInfo.getString("psnAccount"));
                    Map<String, Object> psnInfo = Maps.newHashMap();
                    psnInfo.put("psnName", orgSignerInfo.getString("psnName"));
                    transactorInfo.put("psnInfo", psnInfo);
                    orgPsnSignMap.put("transactorInfo", transactorInfo);
                    orgPsnSignMap.put("orgInfo", orgPsn.getJSONObject("orgInfo"));
                }
            } else {
                //失败
                resul.putAll(body);
                throw new EsignException(JSON.toJSONString(resul));
            }
        } else {
            throw new EsignException("网络异常：" + JSON.toJSONString(response));
        }
        Integer signOrder = orgSignerInfo.getInteger("signOrder");
        //设置签署方的签署顺序
        if (null != signOrder) {
            Map<String, Object> signConfig = Maps.newHashMap();
            signConfig.put("signOrder", signOrder);
            signMapInfo.put("signConfig", signConfig);
        }
        signMapInfo.put("orgSignerInfo", orgPsnSignMap);
        //设置签署方的通知方式
        String noticeTypes = orgSignerInfo.getString("noticeTypes");
        Map<String, String> noticeConfig = Maps.newHashMap();
        if (StringUtils.isNotBlank(noticeTypes)) {
            noticeConfig.put("noticeTypes", noticeTypes);
        } else {
            noticeConfig.put("noticeTypes", "1,2");
        }
        signMapInfo.put("noticeConfig", noticeConfig);
        //签署区信息
        String signName = orgSignerInfo.getString("signName");
        if (StringUtils.isBlank(signName)) {
            signName = "签署方" + signOrder;
        }
        List<Map<String, Object>> signFields = Lists.newArrayList();
        for (Map<String, Object> doc : docs) {
            Map<String, Map<String, Map<String, Object>>> signListGroup = (Map<String,Map<String, Map<String, Object>>>) doc.get("signListGroup");
            //判断是否存在签署区
            if(null!=signListGroup && signListGroup.size()>0){
                Map<String, Map<String, Object>> fieldList = signListGroup.get(signName);
                if(null!=fieldList) {
                    for (Map<String, Object> fieldMap : fieldList.values()) {
                        Map<String, Object> field = Maps.newHashMap();
                        field.put("fileId", fieldMap.get("fileId"));
                        field.put("customBizNum", doc.get("fileName"));
                        if (0 == ((int) fieldMap.get("signFieldType"))) {
                            field.put("signFieldType", fieldMap.get("signFieldType"));
                            //签章区配置项（指定signFieldType为 0 - 签章区时，该参数为必传项）
                            Map<String, Object> normalSignFieldConfig = Maps.newHashMap();
                            if (true == orgSignerInfo.getBoolean("isRadio")) {
                                //企业/机构自动落章（autoSign为true），请不要传该参数。
                                orgPsnSignMap.remove("transactorInfo");
                                //自动落章
                                normalSignFieldConfig.put("freeMode", false);
                                normalSignFieldConfig.put("autoSign", true);
                                //印章id
                                normalSignFieldConfig.put("assignedSealId", orgSignerInfo.getString("sealId"));
                                //印章类型：1印章，2骑缝章
                                normalSignFieldConfig.put("signFieldStyle", fieldMap.get("signFieldStyle"));
                                Map<String, Object> signFieldPosition = Maps.newHashMap();
                                if (1 == ((int) fieldMap.get("signFieldStyle"))) {
                                    //正常章
                                    if (null != fieldMap.get("positionPage") && null != fieldMap.get("positionX") && null != fieldMap.get("positionY")) {
                                        signFieldPosition.put("positionPage", fieldMap.get("positionPage"));
                                        signFieldPosition.put("positionX", fieldMap.get("positionX"));
                                        signFieldPosition.put("positionY", fieldMap.get("positionY"));
                                    } else {
                                        Map<String, Object> res = Maps.newHashMap();
                                        //失败
                                        res.put("文件模板："+doc.get("fileName"),signName+"，未匹配到签署区，请检查模板的签署区命名规范。签署区命名规则：如（“甲方：（盖章）_签署方1_X50_Y50“）根据“_”分割字符串，第一个是要盖章的内容位置标识；第二个是签署方用来判断这个签署区是谁的；X50表示：印章位置向右移动50；Y50表示：印章位置向上移动50");
                                        resulErrList.add(res);
                                    }
                                } else {
                                    //骑缝章
                                    signFieldPosition.put("positionY", fieldMap.get("positionY"));
                                }
                                normalSignFieldConfig.put("signFieldPosition", signFieldPosition);
                                Map<String, Object> signDateConfig = (Map<String, Object>) fieldMap.get("signDateConfig");
                                if(null==signDateConfig) {
                                    signDateConfig = Maps.newHashMap();
                                    //signDateConfig.put("showSignDate", 1);
                                }
                                field.put("signDateConfig", signDateConfig);
                            } else {
                                //手动签章
                                normalSignFieldConfig.put("freeMode", true);
                                normalSignFieldConfig.put("autoSign", false);
                            }
                            field.put("normalSignFieldConfig", normalSignFieldConfig);
                        } else {
                            field.put("signFieldType", fieldMap.get("signFieldType"));
                            //签章区配置项（指定signFieldType为 0 - 签章区时，该参数为必传项）
                            Map<String, Object> remarkSignFieldConfig = Maps.newHashMap();
                            remarkSignFieldConfig.put("freeMode", true);
                            remarkSignFieldConfig.put("inputType", 2);
                            field.put("remarkSignFieldConfig", remarkSignFieldConfig);
                        }
                        signFields.add(field);
                    }
                }
                else {
                    Map<String, Object> res = Maps.newHashMap();
                    //失败
                    res.put("文件模板："+doc.get("fileName"),signName+"，未匹配到签署区，请检查模板的签署区命名规范。签署区命名规则：如（“甲方：（盖章）_签署方1_X50_Y50“）根据“_”分割字符串，第一个是要盖章的内容位置标识；第二个是签署方用来判断这个签署区是谁的；X50表示：印章位置向右移动50；Y50表示：印章位置向上移动50");
                    resulList.add(res);
                }
            }
        }
        if(signFields.size()<=0) {
            throw new EsignException(JSON.toJSONString(resulList));
        }
        if(resulErrList.size()>0) {
            throw new EsignException(JSON.toJSONString(resulErrList));
        }

        signMapInfo.put("signFields", signFields);
        signMapInfo.put("signerType", 1);
        return signMapInfo;
    }

    /**
     * 添加签署人
     *
     * @param context
     * @param psnSignerInfo
     * @param docs
     * @param sourceId
     * @return
     * @throws EsignException
     * @throws URISyntaxException
     */
    public Map<String, Object> addPsnSignerInfo(Context context, JSONObject psnSignerInfo, List<Map<String, Object>> docs, String sourceId) throws EsignException, URISyntaxException {
        List< Map<String, Object>> resulList = Lists.newArrayList();
        Map<String, Object> resul = Maps.newHashMap();
        Map<String, Object> signMapInfo = Maps.newHashMap();
        Map<String, Object> orgPsnSignMap = Maps.newHashMap();
        //个人签署方信息
        String psnAccount = psnSignerInfo.getString("psnAccount");
        String psnName = psnSignerInfo.getString("psnName");
        Integer signOrder = psnSignerInfo.getInteger("signOrder");
        //设置签署方的签署顺序
        if (null != signOrder) {
            Map<String, Object> signConfig = Maps.newHashMap();
            signConfig.put("signOrder", signOrder);
            signMapInfo.put("signConfig", signConfig);
        }
        orgPsnSignMap.put("psnAccount", psnAccount);
        Map<String, String> psnInfo = Maps.newHashMap();
        psnInfo.put("psnName", psnName);
        orgPsnSignMap.put("psnInfo", psnInfo);
        //个人签署方信息
        signMapInfo.put("psnSignerInfo", orgPsnSignMap);
        //设置签署方的通知方式
        String noticeTypes = psnSignerInfo.getString("noticeTypes");
        Map<String, String> noticeConfig = Maps.newHashMap();
        if (StringUtils.isNotBlank(noticeTypes)) {
            noticeConfig.put("noticeTypes", noticeTypes);
        } else {
            noticeConfig.put("noticeTypes", "1,2");
        }
        signMapInfo.put("noticeConfig", noticeConfig);
        //签署区信息
        List<Map<String, Object>> signFields = Lists.newArrayList();
//        for (Map<String, Object> doc : docs) {
//            Map<String, Object> field = Maps.newHashMap();
//            field.put("fileId", doc.get("fileId"));
//            field.put("customBizNum", sourceId);
//            field.put("signFieldType", 0);
//            //签章区配置项（指定signFieldType为 0 - 签章区时，该参数为必传项）
//            Map<String, Object> normalSignFieldConfig = Maps.newHashMap();
//            normalSignFieldConfig.put("freeMode", true);
//            normalSignFieldConfig.put("movableSignField", false);
//
//            field.put("normalSignFieldConfig", normalSignFieldConfig);
//            signFields.add(field);
//        }
        //签署区信息
        String signName = psnSignerInfo.getString("signName");
        if (StringUtils.isBlank(signName)) {
            signName = "签署方" + signOrder;
        }
        for (Map<String, Object> doc : docs) {
            Map<String,  Map<String, Map<String, Object>>> signListGroup = (Map<String, Map<String, Map<String, Object>>>) doc.get("signListGroup");
             Map<String, Map<String, Object>> fieldList = signListGroup.get(signName);
            if(null!=fieldList) {
                for (Map<String, Object> fieldMap : fieldList.values()) {
                    Map<String, Object> field = Maps.newHashMap();
                    field.put("fileId", fieldMap.get("fileId"));
                    field.put("customBizNum", doc.get("fileName"));
                    if (0 == ((int) fieldMap.get("signFieldType"))) {
                        field.put("signFieldType", fieldMap.get("signFieldType"));
                        //签章区配置项（指定signFieldType为 0 - 签章区时，该参数为必传项）
                        Map<String, Object> normalSignFieldConfig = Maps.newHashMap();
                        //手动签章
                        normalSignFieldConfig.put("freeMode", false);
                        normalSignFieldConfig.put("autoSign", false);
                        //印章id
                        //normalSignFieldConfig.put("assignedSealId", orgSignerInfo.getString("sealId"));
                        //印章类型：1印章，2骑缝章
                        normalSignFieldConfig.put("signFieldStyle", fieldMap.get("signFieldStyle"));
                        Map<String, Object> signFieldPosition = Maps.newHashMap();
                        if (1 == ((int) fieldMap.get("signFieldStyle"))) {
                            //正常章
                            if (null != fieldMap.get("positionPage") && null != fieldMap.get("positionX") && null != fieldMap.get("positionY")) {
                                signFieldPosition.put("positionPage", fieldMap.get("positionPage"));
                                signFieldPosition.put("positionX", fieldMap.get("positionX"));
                                signFieldPosition.put("positionY", fieldMap.get("positionY"));
                            }
                        } else {
                            //骑缝章
                            signFieldPosition.put("positionY", fieldMap.get("positionY"));
                        }
                        normalSignFieldConfig.put("signFieldPosition", signFieldPosition);
                        Map<String, Object> signDateConfig = (Map<String, Object>) fieldMap.get("signDateConfig");
                        if(null==signDateConfig) {
                            signDateConfig = Maps.newHashMap();
                            signDateConfig.put("showSignDate", 1);
                        }
                        field.put("signDateConfig", signDateConfig);
                        field.put("normalSignFieldConfig", normalSignFieldConfig);
                    } else {
                        field.put("signFieldType", fieldMap.get("signFieldType"));
                        //签章区配置项（指定signFieldType为 0 - 签章区时，该参数为必传项）
                        Map<String, Object> remarkSignFieldConfig = Maps.newHashMap();
                        remarkSignFieldConfig.put("freeMode", true);
                        remarkSignFieldConfig.put("inputType", 2);
                        field.put("remarkSignFieldConfig", remarkSignFieldConfig);
                    }
                    signFields.add(field);
                }
            } else {
                Map<String, Object> res = Maps.newHashMap();
                //失败
                res.put("文件模板："+doc.get("fileName"),signName+"，未匹配到签署区，请检查模板的签署区命名规范。签署区命名规则：如（“甲方：（盖章）_签署方1_X50_Y50“）根据“_”分割字符串，第一个是要盖章的内容位置标识；第二个是签署方用来判断这个签署区是谁的；X50表示：印章位置向右移动50；Y50表示：印章位置向上移动50");
                resulList.add(res);
            }
        }
        if(signFields.size()<=0) {
            throw new EsignException(JSON.toJSONString(resulList));
        }
        signMapInfo.put("signFields", signFields);
        signMapInfo.put("signerType", 0);

        return signMapInfo;
    }


    /**
     * 处理签署方信息
     *
     * @param context
     * @param signs
     * @param docs
     * @param sourceId
     * @return
     * @throws EsignException
     * @throws URISyntaxException
     */
    public List<Map<String, Object>> addSigners(Context context, JSONArray signs, List<Map<String, Object>> docs, String sourceId) throws EsignException, URISyntaxException {
        List<Map<String, Object>> signers = Lists.newArrayList();
        for (int i = 0; i < signs.size(); i++) {
            Map<String, Object> signMapInfo = Maps.newHashMap();
            JSONObject sign = signs.getJSONObject(i);
            Map<String, Object> orgPsnSignMap = Maps.newHashMap();
            JSONObject orgSignerInfo = sign.getJSONObject("orgSignerInfo");
            JSONObject psnSignerInfo = sign.getJSONObject("psnSignerInfo");
            //企业/机构签署方信息
            if (null != orgSignerInfo) {
                signMapInfo = addOrgSignerInfo(context, orgSignerInfo, docs, sourceId);
            } else {
                //个人签署方信息
                signMapInfo = addPsnSignerInfo(context, psnSignerInfo, docs, sourceId);
            }
            signers.add(signMapInfo);
        }
        return signers;
    }

    /**
     * 签署流程配置项
     *
     * @param context
     * @param signFlowTitle
     * @param jsonObject
     * @return
     */
    public Map<String, Object> addSignFlowConfig(Context context, String signFlowTitle, JSONObject jsonObject) {
        Map<String, Object> signFlowConfig = Maps.newHashMap();
        signFlowConfig.put("signFlowTitle", signFlowTitle);
        Boolean autoStart = jsonObject.getBoolean("autoStart");
        if (null != autoStart) {
            signFlowConfig.put("autoStart", autoStart);
        } else {
            signFlowConfig.put("autoStart", true);
        }
        Boolean autoFinish = jsonObject.getBoolean("autoFinish");
        if (null != autoFinish) {
            signFlowConfig.put("autoFinish", autoFinish);
        } else {
            signFlowConfig.put("autoFinish", true);
        }
        String notifyUrl = jsonObject.getString("notifyUrl");
        if (null != notifyUrl) {
            signFlowConfig.put("notifyUrl", notifyUrl);
        } else {
            notifyUrl = EsignConfig.getInstance().get("notifyUrl");
            signFlowConfig.put("notifyUrl", notifyUrl);
        }
        return signFlowConfig;
    }


    /**
     * 根据传入数据调用 ”填写模板生成文件“ 接口
     *
     * @param jsonObject
     * @return
     */
    public EsignHttpResponse previewFile(Context context, JSONObject jsonObject, String sourceId) throws EsignException {
        String docTemplateId = jsonObject.getString("id");
        String fileName = jsonObject.getString("name");
        if (StringUtils.isBlank(docTemplateId)) {
            docTemplateId = jsonObject.getString("tableId");
        }
        if (StringUtils.isBlank(fileName)) {
            fileName = jsonObject.getString("tableName");
        }
        Map<String, Object> map = Maps.newHashMap();
        map.put("docTemplateId", docTemplateId);
        map.put("fileName", fileName);
        List<Map<String, Object>> components = Lists.newArrayList();
        JSONObject fields = jsonObject.getJSONObject("fields");
        for (Map.Entry<String, Object> field : fields.entrySet()) {

            Map<String, Object> component = Maps.newHashMap();
            component.put("componentId", field.getKey());
            JSONObject fieldInfo = (JSONObject) field.getValue();
            String dataType = (String) fieldInfo.get("dataType");
            if (ComponentTypeEnum.SIGN_AREA.getAlias().equals(dataType)) {
                continue;
            }
            if (ComponentTypeEnum.DATESIGNATURE.getAlias().equals(dataType)) {
                continue;
            }
            component.put("componentValue", fieldInfo.get("value"));
            components.add(component);
        }
        map.put("components", components);
        EsignHttpResponse response = EsignHttpUtil.createByDocTemplate(context, JSON.toJSONString(map), sourceId);
        return response;
    }


}
