package com.brilliance.isc.doc.handle.impl.common;

import com.alibaba.fastjson.JSONObject;
import com.brilliance.isc.common.doc.TextResultVo;
import com.brilliance.isc.common.exception.CommonServiceException;
import com.brilliance.isc.common.trndoc.vo.DoceotVo;
import com.brilliance.isc.doc.constant.DocConstant;
import com.brilliance.isc.doc.handle.ITextProvider;
import com.brilliance.isc.doc.utils.TemplateFactory;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import lombok.Builder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 通用Pdf表单面函处理提供者
 * 一般简单的面函处理，不用每个都写Provider，直接new构建此Provider
 * 面函会通过Pdf表单渲染生成
 * 数据需要使用Map结构
 */
@Builder
public class SimplePdfFormProvider implements ITextProvider<Object> {

    private static Logger log = LoggerFactory.getLogger(SimplePdfFormProvider.class);
    /**
     * 模板名称
     */
    private String templateName;

    /**
     * 面函名称
     */
    private String docName;

    /**
     * 当前提供的面函模板名称
     *
     * @return
     */
    @Override
    public String getDocName() {
        return docName;
    }

    /**
     * 输出报文结果
     *
     * @param dataBo    数据
     * @param doceotVo  单条面函信息
     * @param extraData 附加的数据 键值必须都是String
     * @return
     */
    @Override
    public TextResultVo outputMessage(Object dataBo, DoceotVo doceotVo, Map<String, Object> extraData) {

        Map<String,Object> dataMap = dataToMap(dataBo);
        if(extraData != null) {
            dataMap.putAll(extraData);
        }
        dataMap.put("DOC_NAME",this.getDocName());
        dataMap.put("DEMO","你好，DEMO，这是一个测试语句");
        PdfReader reader = null;
        TextResultVo textResultVo = new TextResultVo();
        textResultVo.setFormat(DocConstant.PDF);
        textResultVo.setExtension("pdf");
        try(ByteArrayOutputStream bos = new ByteArrayOutputStream();
            InputStream ins = TemplateFactory.getPdfTemplateStream(this.templateName,doceotVo.getDocuil());
        ) {
            reader = new PdfReader(ins);
            reader.consolidateNamedDestinations();

            PdfStamper stamper = new PdfStamper(reader, bos);
            // Fields
            AcroFields fields = stamper.getAcroFields();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            //设置字体
            BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            fields.addSubstitutionFont(font);

            for(Map.Entry<String, AcroFields.Item> entry:fields.getFields().entrySet()){
                String key = entry.getKey();
                Object value = dataMap.get(key);
                //只处理支持转为字符串的值
                if(value == null){
                    continue;
                }
                if(value instanceof Date){
                    value = sdf.format((Date)value);
                }else if(value instanceof Integer){
                    value = value.toString();
                }else if(value instanceof BigDecimal){
                    //可能要设置精度
                    value = value.toString();
                }

                if((value instanceof  String)) {
                    fields.setField(key, (String) value);
                }
            }

            stamper.setFormFlattening(true);
            stamper.close();
            reader.close();
            textResultVo.setBinary(bos.toByteArray());
        } catch (IOException | DocumentException e) {
            log.error("模板异常{}",e);
            throw new CommonServiceException("模板异常");
        }

        return textResultVo;
    }

    private Map<String,Object> dataToMap(Object dataBo){
//        ObjectMapper objectMapper = new ObjectMapper();
        try {
            String json = JSONObject.toJSONString(dataBo);
            Map<String,Object> dataMap = JSONObject.parseObject(json,Map.class);
            //展开Map
            Map<String,Object> resultMap = new HashMap<>();
            flatMap(dataMap, resultMap,"");
            return resultMap;
        } catch (Exception e) {
            log.error("PDF表单数据转换失败：{}",e);
        }
        return new HashMap<>();
    }

    private void flatMap(Map<String,Object> dataMap,Map<String,Object> result,String prefix){
        for(Map.Entry<String,Object> entry : dataMap.entrySet()){
            Object value = entry.getValue();
            String key = prefix.isEmpty()?entry.getKey():prefix+"."+entry.getKey();
            if(value instanceof Map){
                flatMap((Map)value, result,key);
            }else{
               result.put(key,value);
            }
        }
    }

}
