package com.mortals.xhx.module.doc.template.service.impl;

import cn.hutool.core.text.StrSplitter;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.XmlUtil;
import com.alibaba.fastjson.JSON;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.template.MetaTemplate;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.service.impl.AbstractCRUDServiceImpl;
import com.mortals.xhx.common.code.ComponentEnum;
import com.mortals.xhx.common.formdesign.*;
import com.mortals.xhx.common.pdu.NodeEntity;
import com.mortals.xhx.common.pdu.gen.*;
import com.mortals.xhx.common.pdu.gen.OptionsItem;
import com.mortals.xhx.common.pdu.gen.component.ComponentCons;
import com.mortals.xhx.common.utils.ExportDocUtil;
import com.mortals.xhx.module.doc.form.model.DocFormEntity;
import com.mortals.xhx.module.doc.form.model.DocFormQuery;
import com.mortals.xhx.module.doc.form.service.DocFormService;
import com.mortals.xhx.module.doc.template.dao.DocTemplateDao;
import com.mortals.xhx.module.doc.template.model.DocTemplateEntity;
import com.mortals.xhx.module.doc.template.service.DocTemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.w3c.dom.Document;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * DocTemplateService
 * doc模板 service实现
 *
 * @author zxfei
 * @date 2021-10-16
 */
@Service("docTemplateService")
public class DocTemplateServiceImpl extends AbstractCRUDServiceImpl<DocTemplateDao, DocTemplateEntity, Long> implements DocTemplateService {
    @Autowired
    private DocFormService docFormService;

    @Value("${upload.path}")
    private String filePath;

    @Override
    protected void saveAfter(DocTemplateEntity entity, Context context) throws AppException {
        if (!ObjectUtils.isEmpty(entity.getDocFormEntity())) {
            DocFormEntity subEntity = entity.getDocFormEntity();
            subEntity.setFormName(entity.getName() + "表单");
            subEntity.setTemplateId(entity.getId());
            subEntity.setCreateUser(context.getUser().getLoginName());
            subEntity.setCreateUserId(context.getUser().getId());
            subEntity.setCreateTime(new Date());
            docFormService.save(subEntity, context);
        }
        super.saveAfter(entity, context);
    }

    @Override
    protected void updateAfter(DocTemplateEntity entity, Context context) throws AppException {
        if (!ObjectUtils.isEmpty(entity.getDocFormEntity()) && !ObjectUtils.isEmpty(entity.getDocFormEntity().getId())) {
            DocFormEntity subEntity = entity.getDocFormEntity();
            subEntity.setUpdateUser(context.getUser().getLoginName());
            subEntity.setUpdateUserId(context.getUser().getId());
            subEntity.setUpdateTime(new Date());
            docFormService.update(subEntity, context);
        }
        super.updateAfter(entity, context);
    }

    @Override
    protected void removeAfter(Long[] ids, Context context, int result) throws AppException {
        for (int i = 0; i < ids.length; i++) {
            Long[] formIds = docFormService.find(new DocFormQuery().templateId(ids[i]), context).stream().map(DocFormEntity::getId).toArray(Long[]::new);
            docFormService.remove(formIds, context);
        }
        super.removeAfter(ids, context, result);
    }

    @Override
    public void parseDocXml(DocTemplateEntity docTemplateVo, Context context) {
        //读文件
        String filepath = filePath + docTemplateVo.getTemplatePath();
        //正则找到所有el表达式
        List<NodeEntity> list = new ArrayList<>();
        Document document = ExportDocUtil.parseXMLFile(list, filepath);
        //校验与更新非标准el表达式
        ExportDocUtil.checkAndUpdateExpressionByDocument(document, list);
        //正在匹配所有图片，如果有，替换模板文件  图片标签暂定为 w:binData
        List<String> ids = ExportDocUtil.getIdsByTagName("w:binData", list);
        if (ids.size() > 0) {
            log.info("需要替换图片");
            for (int i = 0; i < ids.size(); i++) {
                List<String> paths = new ArrayList<>();
                NodeEntity nodeEntity = ExportDocUtil.getElementMapById(ids.get(i), list);
                if (!ObjectUtils.isEmpty(nodeEntity)) {
                    //判断内容如果是${} 这不在解析
                    paths.add(nodeEntity.getTagName());
                    ExportDocUtil.getPath(paths, list, nodeEntity.getParentId());
                    String el = String.format("${image_%s_图片%s}", i, i);
                    ExportDocUtil.parseTemplateImage(paths, el, document);
                    nodeEntity.setContent(el);
                }
            }
        }

        //重新更新list
        list = new ArrayList<>();
        ExportDocUtil.parseDocument(list, document);
        //解析替换多选框值
        //获取所有存在el表达式节点值 并去重复
        List<NodeEntity> elList = list.stream().map(item -> {
            if (!"".equals(item.getContent())) {
                return item;
            }
            return null;
        }).filter(f -> f != null).collect(Collectors.toList());
        List<NodeEntity> newList = new ArrayList<>();

        for (NodeEntity nodeEntity : elList) {
            String content = nodeEntity.getContent();
            boolean bool = false;
            for (NodeEntity nodeEntity1 : newList) {
                if (!ObjectUtils.isEmpty(content) && content.equals(nodeEntity1.getContent())) {
                    bool = true;
                    break;
                }
            }
            if (!bool) {
                newList.add(nodeEntity);
            }
        }
        //根据el表达式 动态创建表单组件
        GenRoot root = new GenRoot();
        root.initAttribute();
        for (int i = 0; i < newList.size(); i++) {
            NodeEntity item = newList.get(i);
            //判断是否有多个el表达式
            List<String> elGroups = StrSplitter.split(item.getContent(), ";", true, true);
            for (int j = 0; j < elGroups.size(); j++) {
                String el = elGroups.get(j);
                String val = StrUtil.strip(el, "${", "}");
                List<String> keys = StrSplitter.split(val, "_", true, true);
                //切分分隔符后动态 创建组件  i_1_姓名（第一个代表类型，第二个如果是多个累加，第三个显示label）
                if (keys.size() > 2) {
                    String label = keys.get(2);
                    String type = keys.get(0);
                    // FieldsItem fieldItem = null;
                    //todo
                    ComponentCons cons = new ComponentCons();
                    cons.setLabel(label);
                    cons.setVal(val);
                    cons.setEl(el);
                    cons.setNodeEntity(item);
                    cons.setList(list);
                    cons.setDocument(document);
                    Component component = Component.createType(type);
                    FieldsItem fieldItem = component.buildDefaultComponent(cons);
                    //显示的label
                    fieldItem.getConfig().setLabel(cons.getLabel());
                    Integer formId = 100 + i + j;
                    fieldItem.getConfig().setFormId(formId);
                    fieldItem.getConfig().setRenderKey(formId + RandomUtil.randomNumbers(13));
                    //设定输入框绑定的key
                    fieldItem.setVModel(cons.getVal());
                    root.getFields().add(fieldItem);
                }
            }
        }
        //判断如果有按钮 添加方法名
        root.getFields().stream().peek(item -> {
            if (item.getOn() != null) {
                if (ObjectUtils.isEmpty(root.getMethods())) {
                    Methods methods = new Methods();
                    methods.getMethods().add(item.getOn().getClick());
                    root.setMethods(methods);
                } else {
                    root.getMethods().getMethods().add(item.getOn().getClick());
                }
            }
        }).count();

        XmlUtil.toFile(document, filepath);
        DocFormEntity docFormEntity = docFormService.selectOne(new DocFormQuery().templateId(docTemplateVo.getId()));
        if (ObjectUtils.isEmpty(docFormEntity)) {
            docFormEntity = new DocFormEntity();
            docFormEntity.setFormContent(JSON.toJSONString(root));
            docFormEntity.setFormName(docTemplateVo.getName() + "表单");
            docFormEntity.setTemplateId(docTemplateVo.getId());
            docFormEntity.setCreateTime(new Date());
            docFormEntity.setCreateUser(context.getUser().getLoginName());
            docFormService.save(docFormEntity, context);
        } else {
            //todo 解析转换 计算交集，id用modelkey
//            GenRoot genRoot = JSON.parseObject(docFormEntity.getFormContent(), new TypeReference<GenRoot>() {
//            });
            docFormEntity.setFormContent(JSON.toJSONString(root));
            docFormEntity.setUpdateTime(new Date());
            docFormEntity.setUpdateUser(context.getUser().getLoginName());
            docFormService.update(docFormEntity, context);
        }
    }

    @Override
    public void parseDocxToJson(DocTemplateEntity docTemplateEntity, Context context) {
        //读文件
        String filepath = filePath + docTemplateEntity.getTemplatePath();
        ConfigureBuilder builder = Configure.builder();

        builder.setValidErrorHandler(new Configure.DiscardHandler());
        builder.useDefaultEL(false);
        //builder.buildGramer("[","]");
        XWPFTemplate template = XWPFTemplate.compile(filepath, builder.build());
        FormDesignRoot root = new FormDesignRoot();
        FormDesignConfig config = new FormDesignConfig();
        config.initAttribute();
        root.setConfig(config);
        List<ListItem> collect = new ArrayList<>();
        for (MetaTemplate item : template.getElementTemplates()) {
            System.out.println(item.variable());
            //识别简单输入
            String val = StrUtil.strip(item.variable(), "{{", "}}");
            List<String> keys = StrSplitter.split(val, "_", true, true);
            //切分分隔符后动态 创建组件  i_1_姓名（第一个代表类型，第二个如果是多个累加，第三个显示label）
            if (keys.size() > 2) {
                String label = keys.get(2);
                String type = keys.get(0);
                ComponentCons cons = new ComponentCons();
                cons.setLabel(label);
                cons.setVal(val);
                cons.setEl(item.variable());

                if (type.equalsIgnoreCase(ComponentEnum.DYNAMIC_TABLE.getValue())) {
                    List<TableColItem> colList = new ArrayList<>();
                    //表格 结构化绑定数据
                    ConfigureBuilder builderTable = Configure.builder();
                    builderTable.setValidErrorHandler(new Configure.DiscardHandler());
                    builderTable.useDefaultEL(false);
                    builderTable.buildGramer("[", "]");
                    XWPFTemplate templateTable = XWPFTemplate.compile(filepath, builderTable.build());
                    templateTable.getElementTemplates().forEach(col -> {
                        String colVal = StrUtil.strip(col.variable(), "[", "]");
                        List<String> colKeys = StrSplitter.split(colVal, "_", true, true);
                        if (colKeys.size() > 2) {
                            String colLabel = colKeys.get(2);
                            String colType = colKeys.get(0);
                            TableColItem tableColItem = new TableColItem();
                            tableColItem.setLabel(colLabel);
                            tableColItem.setColType(colType);
                            tableColItem.setVal(colVal);
                            colList.add(tableColItem);
                            System.out.println("列元素" + col.variable());
                        }
                    });
                    cons.setColList(colList);
                    DesignComponent designComponent = DesignComponent.createType(type);
                    ListItem listItem = designComponent.buildDefaultComponent(cons);
                    collect.add(listItem);
                    continue;
                }
                DesignComponent designComponent = DesignComponent.createType(type);
                ListItem listItem = designComponent.buildDefaultComponent(cons);
                collect.add(listItem);
            }
        }
        root.setList(collect);
        DocFormEntity docFormEntity = docFormService.selectOne(new DocFormQuery().templateId(docTemplateEntity.getId()));
        if (ObjectUtils.isEmpty(docFormEntity)) {
            docFormEntity = new DocFormEntity();
            docFormEntity.setFormContent(JSON.toJSONString(root));
            docFormEntity.setFormName(docTemplateEntity.getName() + "表单");
            docFormEntity.setTemplateId(docTemplateEntity.getId());
            docFormEntity.setCreateTime(new Date());
            docFormEntity.setCreateUser(context.getUser().getLoginName());
            docFormService.save(docFormEntity, context);
        } else {
            //todo 解析转换 计算交集，id用modelkey
            docFormEntity.setFormContent(JSON.toJSONString(root));
            docFormEntity.setUpdateTime(new Date());
            docFormEntity.setUpdateUser(context.getUser().getLoginName());
            docFormService.update(docFormEntity, context);
        }
    }


}