package com.seeyon.apps.esign.service;


import com.seeyon.apps.esign.config.EsignConfigProvider;
import com.seeyon.apps.esign.constants.EsignConfigConstants;
import com.seeyon.apps.esign.po.param.JsonParamSource;
import com.seeyon.apps.esign.po.signer.JsonSignerBuilder;
import com.seeyon.apps.esign.po.signer.SignParty;
import com.seeyon.apps.esign.po.signer.Signer;
import com.seeyon.apps.ext.workflow.vo.FieldDataVo;
import com.seeyon.apps.ext.workflow.vo.FormDataVo;
import com.seeyon.ctp.common.AppContext;
import org.apache.commons.lang.StringUtils;

import java.util.*;

public class NormalFormSignParamBuildFactory implements SignParamBuildFactory {

    private EsignConfigProvider configProvider = EsignConfigProvider.getInstance();
    private EsignUploadFileService uploadFileService = (EsignUploadFileService) AppContext.getBean("esignUploadFileService");

    @Override
    public Map<String, Object> buildParam(SignParamSource source) throws Exception {
        Map<String, Object> signParams = new HashMap<>();
        List<String> fileIds = null;
        if (source.isByFile()) {
            String attachmentId = source.getSignFileRefId();
            if (attachmentId == null) throw new RuntimeException("合同文件不能为空");
            List<Map<String, Object>> docs = buildDocs(source.getAppId(),attachmentId);
            fileIds = new ArrayList<>();
            for (Map<String, Object> doc : docs) {
                fileIds.add((String) doc.get("fileId"));
            }
            signParams.put("docs", docs);
        }
        Map<String, Object> signFlowConfig = buildSignFlowConfig(source.getContractTitle(),source.getCallbackUrl());
        JsonSignerBuilder signerBuilder = new JsonSignerBuilder();
        List<SignParty> signerParties = source.getSignerParties();
        List<String> keywords = new ArrayList<>();
        signerParties.forEach(party -> {
            if(StringUtils.isNotBlank(party.getSignKeyword())) {
                keywords.add(party.getSignKeyword());
            }
        });
        List<Object> keywordPos = getKeywordPos(source.getAppId(),fileIds, keywords);
        List<Signer> signers = signerBuilder.buildAll(fileIds,keywordPos,signerParties,source.getAppId());
        signParams.put("signFlowConfig", signFlowConfig);
        signParams.put("signers", signers);
        return signParams;
    }

    private List<Object> getKeywordPos(String appId,List<String> fileIds,List<String> keywords){
        List<Object> pos = new ArrayList<>();
        for (String fileId : fileIds){
            List<Object> signPosition = uploadFileService.getSignPosition(appId,fileId, keywords);
            pos.addAll(signPosition);
        }
        return pos.size() > 0 ? pos : null;
    }

    @Override
    public boolean support(SignParamSource source) {
        return source instanceof JsonParamSource;
    }

    /**
     * 构建文档列表
     * @param attachmentId 如果 byFile=true，则上传并返回 fileId
     */
    public List<Map<String, Object>> buildDocs(String appId,String attachmentId) throws Exception {
        List<String> fileIds = uploadFileService.uploadFileToEsign(appId,attachmentId);
        List<Map<String, Object>> docs = new ArrayList<>();
        for (String fileId : fileIds) {
            Map<String, Object> docMap = new HashMap<>();
            docMap.put("fileId", fileId);
            docs.add(docMap);
        }
        Thread.sleep(1000); // e签宝要求，可考虑异步
        return docs;
    }

    public Map<String, Object> buildSignFlowConfig(String contractName,String callbackUrl) throws Exception {
        if (contractName == null) throw new RuntimeException("合同名称不能为空");
        String signCallBackUrl = configProvider.getBizConfigByKey(EsignConfigConstants.OA_HOST) + callbackUrl;
        Map<String, Object> config = new HashMap<>();
        config.put("signFlowTitle", contractName);
        config.put("autoFinish", true);
        config.put("notifyUrl", signCallBackUrl);
        Map<String, Object> noticeConfig = new HashMap<>();
        noticeConfig.put("noticeTypes", "1");
        config.put("noticeConfig", noticeConfig);
        Map<String, Object> signConfig = new HashMap<>();
        signConfig.put("showBatchDropSealButton", false);
        config.put("signConfig", signConfig);
        return config;
    }

    private String getStringField(FormDataVo vo, String field) {
        try {
            FieldDataVo fieldData = vo.getFieldData(field);
            return fieldData.getStringValue();
        }catch (Exception e) {

            return null;
        }
    }
}