package com.seeyon.apps.esign.po.signer;

import com.seeyon.apps.esign.config.EsignConfigProvider;
import com.seeyon.apps.esign.po.signfield.NormalSignFieldConfig;
import com.seeyon.apps.esign.po.signfield.SignField;
import com.seeyon.apps.esign.po.signfield.SignFieldPosition;
import org.apache.commons.lang.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JsonSignerBuilder implements SignerBuilder{

    private EsignConfigProvider esignConfigProvider = EsignConfigProvider.getInstance();

    @Override
    public Signer build(List<String> fileIds, List<Object> keywordPos, SignParty party,String appId) {
        if (party.getSignerType() == SignerType.PERSON) {
            return buildPersonSigner(fileIds,keywordPos,party);
        } else if (party.getSignerType() == SignerType.ORG) {
            return buildOrgSigner(fileIds,keywordPos,party);
        } else {
            throw new IllegalArgumentException("不支持的签署方类型");
        }
    }

    private Float toFloat(Object val) {
        return val instanceof Number ? ((Number) val).floatValue() : Float.parseFloat(val.toString());
    }

    private List<SignField> buildSignFields(List<String> fileIds,List<Object> keywordPos, SignParty party) {
        List<SignField> signFields = new ArrayList<>();
        for (String fileId : fileIds) {
            List<SignFieldPosition> signFieldPositions = null;
            if(!Boolean.TRUE.equals(party.getFreeSign())){
                String signKeyword = party.getSignKeyword();
               signFieldPositions = extractPosition(keywordPos, signKeyword);
                for (SignFieldPosition position : signFieldPositions) {
                    NormalSignFieldConfig fieldConfig = new NormalSignFieldConfig();
                    fieldConfig.setSignFieldPosition(position);
                    fieldConfig.setAutoSign(party.getAutoSign());
                    fieldConfig.setSignFieldStyle("ALL".equals(position.getAcrossPageMode()) ? 2 : 1);
                    SignField field = new SignField();
                    field.setSignFieldType(0);
                    field.setNormalSignFieldConfig(fieldConfig);
                    field.setFileId(fileId);
                    signFields.add(field);
                }
                if(signFieldPositions.size() > 0 && !SignerType.PERSON.equals(party.getSignerType())) {
                    SignField field = new SignField();
                    field.setSignFieldType(0);
                    buildQfSignNormalConfig(party);
                    field.setNormalSignFieldConfig(buildFreeModeSignNormalConfig(party));
                    field.setFileId(fileId);
                    signFields.add(field);
                }
            }else {

                SignField field = new SignField();
                field.setSignFieldType(0);
                field.setNormalSignFieldConfig(buildFreeModeSignNormalConfig(party));
                field.setFileId(fileId);
                signFields.add(field);
            }
        }
        return signFields;
    }

    private NormalSignFieldConfig buildFreeModeSignNormalConfig(SignParty party) {
        NormalSignFieldConfig normalSignFieldConfig = new NormalSignFieldConfig();
        normalSignFieldConfig.setAssignedSealId(party.getSealId());
        normalSignFieldConfig.setFreeMode(true);
        normalSignFieldConfig.setAutoSign(false);
        normalSignFieldConfig.setAdaptableSignFieldSize(true);
        return normalSignFieldConfig;
    }

    private NormalSignFieldConfig buildQfSignNormalConfig(SignParty party) {
        NormalSignFieldConfig normalSignFieldConfig = new NormalSignFieldConfig();
        normalSignFieldConfig.setAssignedSealId(party.getSealId());
        normalSignFieldConfig.setFreeMode(false);
        normalSignFieldConfig.setAutoSign(false);
        SignFieldPosition qfengposition = new SignFieldPosition();
        qfengposition.setAcrossPageMode("ALL");
        qfengposition.setPositionY(party.getQfPos());
        normalSignFieldConfig.setSignFieldPosition(qfengposition);
        normalSignFieldConfig.setAdaptableSignFieldSize(true);
        return normalSignFieldConfig;
    }

    private Map<String, Object> mapOf(Object... keyValues) {
        if (keyValues.length % 2 != 0) throw new IllegalArgumentException("key-value 必须成对出现");
        Map<String, Object> map = new HashMap<>();
        for (int i = 0; i < keyValues.length; i += 2) {
            map.put((String) keyValues[i], keyValues[i + 1]);
        }
        return map;
    }

    private List<SignFieldPosition> extractPosition(List<Object> positions, String keyword) {
        if(StringUtils.isBlank(keyword)) {
            return null;
        }
        List<SignFieldPosition> posList = new ArrayList<>();
        for (Object obj : positions) {
            Map<String, Object> position = (Map<String, Object>) obj;
            if (Boolean.TRUE.equals(position.get("searchResult")) && keyword.equals(position.get("keyword"))) {
                Object[] posArray = (Object[]) position.get("positions");
                for (Object o : posArray) {
                    Map<String, Object> posMap = (Map<String, Object>)o;
                    Object[] coords = (Object[]) posMap.get("coordinates");
                    for (Object coord : coords) {
                        Map<String,Object> tempMap = (Map<String, Object>) coord;
                        SignFieldPosition sfp = new SignFieldPosition();
                        sfp.setPositionPage(posMap.get("pageNum") + "");
                        sfp.setPositionX(toFloat(tempMap.get("positionX")) + 160f);
                        sfp.setPositionY(toFloat(tempMap.get("positionY")));
                        posList.add(sfp);
                    }
                }
                return posList;
            }
        }
        return new ArrayList<>();
    }

    private Signer buildPersonSigner(List<String> fileIds,List<Object> keywordPos, SignParty party) {
        PersonInfo psn = party.getPersonInfo();
        if (psn == null) throw new IllegalStateException("个人签署方缺少 PersonInfo");
        Signer signer = new Signer();
        signer.setSignerType(0);
        signer.setSignConfig(mapOf("signOrder", party.getSignOrder()));
        if (!party.getAutoSign()) {
            signer.setNoticeConfig(mapOf("noticeTypes", "1"));
            signer.setPsnSignerInfo(mapOf(
                    "psnAccount", psn.getPhone(),
                    "psnInfo", mapOf(
                            "psnName", psn.getName(),
                            "psnIDCardNum", psn.getIdCardNo(),
                            "psnIDCardType", psn.getIdCardType()
                    )
            ));
        }
        signer.setSignFields(buildSignFields(fileIds,keywordPos,party));
        return signer;
    }

    private Signer buildOrgSigner(List<String> fileIds,List<Object> keywordPos,SignParty party) {
        OrgInfo org = party.getOrgInfo();
        Signer signer = new Signer();
        signer.setSignerType(1);
        signer.setSignConfig(mapOf("signOrder", party.getSignOrder()));
        if (!party.getAutoSign() && org != null) {
            signer.setNoticeConfig(mapOf("noticeTypes", "1"));
            signer.setOrgSignerInfo(mapOf(
                    "orgName", org.getOrgName(),
                    "orgInfo", mapOf(
                            "legalRepName", org.getLegalName(),
                            "legalRepIDCardNum", org.getLegalIdCardNo(),
                            "orgIDCardNum", org.getOrgCode(),
                            "orgIDCardType", "CRED_ORG_USCC"
                    ),
                    "transactorInfo", mapOf(
                            "psnAccount", org.getTransactor().getPhone(),
                            "psnInfo", mapOf(
                                    "psnName", org.getTransactor().getName(),
                                    "psnIDCardNum", org.getTransactor().getIdCardNo()
                            )
                    )
            ));
        }
        signer.setSignFields(buildSignFields(fileIds,keywordPos,party));
        return signer;
    }
}
