package com.mortals.xhx.base.system.gentable.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.plugin.table.MultipleRowTableRenderPolicy;
import com.mortals.framework.common.code.YesNo;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.model.ParamDto;
import com.mortals.framework.service.impl.AbstractCRUDServiceImpl;
import com.mortals.framework.util.DateUtils;
import com.mortals.framework.util.EntityUtil;
import com.mortals.xhx.base.system.gentable.dao.GentableDao;
import com.mortals.xhx.base.system.gentable.model.*;
import com.mortals.xhx.base.system.gentable.service.GentableColumnService;
import com.mortals.xhx.base.system.gentable.service.GentableService;
import com.mortals.xhx.common.code.CacheServiceTypeEnum;
import com.mortals.xhx.common.code.DividedTableTypeEnum;
import com.mortals.xhx.common.key.Constant;
import com.mortals.xhx.common.key.GenConstants;
import com.mortals.xhx.common.model.UserInfo;
import com.mortals.xhx.common.utils.FreeMarkerUtils;
import com.mortals.xhx.common.utils.GenUtils;
import com.mortals.xhx.common.utils.ReadDoc;
import com.mortals.xhx.common.utils.StringUtils;
import freemarker.template.Template;
import lombok.SneakyThrows;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * <p>Title: 代码生成业务表</p>
 * <p>Description: GentableService service接口 </p>
 * <p>Copyright: Copyright &reg;  </p>
 *
 * @version 1.0.0
 */
@Service("gentableService")
public class GentableServiceImpl extends AbstractCRUDServiceImpl<GentableDao, GentableEntity, Long> implements GentableService {

    @Autowired
    private GentableColumnService gentableColumnService;

    String headStr = "版本 |  创建时间   | 作者 |  备注信息\n" +
            "---|---|---|---\n" +
            "v1.0|" + DateUtils.getCurrStrDate() + "|zxfei| 接口文档\n\n" +
            "## 数据类型\n" +
            "类型名称|类型描述|参考样例\n" +
            "---|---|---\n" +
            "String |字符串|A、a、ab\n" +
            "Integer|数字类型|1、12、-1\n" +
            "Long|长整型数字|1、12、-1\n" +
            "date|时间类型,单位纳秒数字|167988745573\n" +
            "BigDecimal|小数类型|545.256\n" +
            "object|对象类型|{\"name\":\"zhang3\"}\n" +
            "arrays|数组类型|[{\"name\":\"zhang3\"},{\"name\":\"zhang2\"}]\n";

    @Override
    public List<GentableEntity> selectDbTableList(GentableQuery query) {
        //query to  dao
        ParamDto paramDto = new ParamDto();
        Map map = new HashMap();
        EntityUtil.entityToMap(query, map);
        paramDto.setCondition(map);
        return this.dao.selectDbTableList(paramDto);
    }

    @Override
    public List<GentableEntity> selectDbTableListByNames(String[] tableNames) {
        return this.getDao().selectDbTableListByNames(tableNames);
    }

    @Override
    public List<GentableEntity> selectGenTableAll(Long appId) {
        return this.getDao().selectGenTableAll(appId);
    }

    @Override
    public void importGenTable(List<GentableEntity> tableList, Long appId, Context context) {
        String operName = context.getUser().getLoginName();
        try {
            for (GentableEntity table : tableList) {
                String tableName = table.getTableName();
                GenUtils.initTable(table, operName);
                table.setGenType(0);
                table.setIsGenExport(0);
                table.setIsShowControl(0);
                table.setGenPath("/");
                table.setTplCategory("crud");
                table.setAppId(appId);
                table.setCacheServiceType(CacheServiceTypeEnum.NORMAL_SERVICE.getValue());
                table.setDividedTableType(DividedTableTypeEnum.DIVIED_NO.getValue());
                //保存表
                this.save(table);
                //保存列
                List<GentableColumnEntity> genTableColumns = gentableColumnService.selectDbTableColumnsByName(tableName);
                for (GentableColumnEntity column : genTableColumns) {
                    GenUtils.initColumnField(column, table);
                    gentableColumnService.save(column);
                }
            }
        } catch (Exception e) {
            throw new AppException("导入失败：" + e.getMessage());
        }
    }

    @Override
    public void validData(GentableEntity genTable, Context context) throws AppException {
        if (GenConstants.TPL_TREE.equals(genTable.getTplCategory())) {
            //if(genTabl)
            JSONObject paramsObj = JSONObject.parseObject(genTable.getOptions());
            if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_CODE))) {
                throw new AppException("树编码字段不能为空");
            } else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_PARENT_CODE))) {
                throw new AppException("树父编码字段不能为空");
            } else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_NAME))) {
                throw new AppException("树名称字段不能为空");
            }
        }
        super.validData(genTable, context);
    }

    @Override
    public Map<String, String> previewCode(Long id) {

        Map<String, String> dataMap = new LinkedHashMap<>();
        // 查询表信息
        GentableEntity gentableEntity = this.get(id);
        List<GentableColumnEntity> columnEntities = this.gentableColumnService.find(new GentableColumnQuery().tableId(gentableEntity.getId())).stream().map(column -> {
            //拆解枚举类，格式必须为（1.啊啊啊，2.不不不）
            String temp1 = StringUtils.substringBetween(column.getColumnComment(), "(", ")");
            String temp2 = StringUtils.substringBetween(column.getColumnComment(), "（", "）");
            GenUtils.checkDict(column, temp1);
            GenUtils.checkDict(column, temp2);
            return column;
        }).collect(Collectors.toList());
        gentableEntity.setColumns(columnEntities);
        // 设置主子表信息
        setSubTable(gentableEntity);
        // 设置主键列信息
        setPkColumn(gentableEntity);

        //生成模板基础数据
        Map data = FreeMarkerUtils.prepareSetFreeMarkerData(gentableEntity);
        //输出合成模板
        List<String> templates = FreeMarkerUtils.getTemplateList(gentableEntity.getTplCategory());
        for (String temp : templates) {
            if (temp.equals("enum.java.ftl")) {
                continue;
            }

            if (temp.equals("api.md.ftl")) {
                continue;
            }

            if (temp.equals("api-two.md.ftl")) {
                continue;
            }
            if (temp.equals("apidict.md.ftl")) {
                continue;
            }
            try {
                //初始化freeMarkers
                FreeMarkerUtils.initFreeMarker(genFreePath(temp));
                // 渲染模板
                StringWriter sw = new StringWriter();
                Template template = FreeMarkerUtils.getTemplate(temp);
                template.process(data, sw);
                dataMap.put(temp, sw.toString());
            } catch (Exception e) {
                log.error("异常", e);
            }
        }
        return dataMap;

    }


    @Override
    protected void updateAfter(GentableEntity entity, Context context) throws AppException {
        if (!ObjectUtils.isEmpty(entity.getColumns())) {
            gentableColumnService.update(entity.getColumns());
        }
        super.updateAfter(entity, context);
    }


    @SneakyThrows
    @Override
    public byte[] downloadCode(Long tableId, String genTypes) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        FreeMarkerUtils.menuSql = new StringBuilder();
        FreeMarkerUtils.paramsSql = new StringBuilder();
        FreeMarkerUtils.dbSql = new StringBuilder();
        FreeMarkerUtils.apimd = new StringBuilder();
        FreeMarkerUtils.apitwomd = new StringBuilder();
        FreeMarkerUtils.apidict = new StringBuilder();
        FreeMarkerUtils.apidict.append("## 字典附录\n");
        FreeMarkerUtils.apimd.append(headStr);
        FreeMarkerUtils.apitwomd.append(headStr);
        generatorCode(tableId, genTypes, zip);
        if (StringUtils.isNotEmpty(FreeMarkerUtils.menuSql)) {
            zip.putNextEntry(new ZipEntry("db/menu.sql"));
            IOUtils.write(FreeMarkerUtils.menuSql.toString(), zip, Constant.UTF8);
        }
        if (StringUtils.isNotEmpty(FreeMarkerUtils.dbSql)) {
            zip.putNextEntry(new ZipEntry("db/db.sql"));
            IOUtils.write(FreeMarkerUtils.dbSql.toString(), zip, Constant.UTF8);
        }
        if (StringUtils.isNotEmpty(FreeMarkerUtils.paramsSql)) {
            zip.putNextEntry(new ZipEntry("db/params.sql"));
            IOUtils.write(FreeMarkerUtils.paramsSql.toString(), zip, Constant.UTF8);
        }
        if (StringUtils.isNotEmpty(FreeMarkerUtils.apimd)) {
            zip.putNextEntry(new ZipEntry("doc/api.md"));
            IOUtils.write(FreeMarkerUtils.apimd.toString(), zip, Constant.UTF8);
        }

        if (StringUtils.isNotEmpty(FreeMarkerUtils.apitwomd)) {
            zip.putNextEntry(new ZipEntry("doc/api-two.md"));
            IOUtils.write(FreeMarkerUtils.apitwomd.toString(), zip, Constant.UTF8);
        }

        if (StringUtils.isNotEmpty(FreeMarkerUtils.apidict)) {
            zip.putNextEntry(new ZipEntry("doc/dict.md"));
            IOUtils.write(FreeMarkerUtils.apidict.toString(), zip, Constant.UTF8);
        }
        IOUtils.closeQuietly(zip);
        return outputStream.toByteArray();
    }

    @SneakyThrows
    @Override
    public byte[] downloadCode(Long[] tableIds, String genTypes) {
        FreeMarkerUtils.menuSql = new StringBuilder();
        FreeMarkerUtils.dbSql = new StringBuilder();
        FreeMarkerUtils.paramsSql = new StringBuilder();
        FreeMarkerUtils.apimd = new StringBuilder();
        FreeMarkerUtils.apitwomd = new StringBuilder();
        FreeMarkerUtils.apidict = new StringBuilder();
        FreeMarkerUtils.apidict.append("## 字典附录\n");
        FreeMarkerUtils.apimd.append(headStr);
        FreeMarkerUtils.apitwomd.append(headStr);

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        for (Long tableId : tableIds) {
            generatorCode(tableId, genTypes, zip);
        }
        if (StringUtils.isNotEmpty(FreeMarkerUtils.menuSql)) {
            zip.putNextEntry(new ZipEntry("db/menu.sql"));
            IOUtils.write(FreeMarkerUtils.menuSql.toString(), zip, Constant.UTF8);
        }
        if (StringUtils.isNotEmpty(FreeMarkerUtils.dbSql)) {
            zip.putNextEntry(new ZipEntry("db/db.sql"));
            IOUtils.write(FreeMarkerUtils.dbSql.toString(), zip, Constant.UTF8);
        }
        if (StringUtils.isNotEmpty(FreeMarkerUtils.paramsSql)) {
            zip.putNextEntry(new ZipEntry("db/params.sql"));
            IOUtils.write(FreeMarkerUtils.paramsSql.toString(), zip, Constant.UTF8);
        }
        if (StringUtils.isNotEmpty(FreeMarkerUtils.apimd)) {
            FreeMarkerUtils.apimd.append(FreeMarkerUtils.apidict);

            zip.putNextEntry(new ZipEntry("doc/api.md"));
            IOUtils.write(FreeMarkerUtils.apimd.toString(), zip, Constant.UTF8);
        }

        if (StringUtils.isNotEmpty(FreeMarkerUtils.apitwomd)) {
            FreeMarkerUtils.apitwomd.append(FreeMarkerUtils.apidict);

            zip.putNextEntry(new ZipEntry("doc/api-two.md"));
            IOUtils.write(FreeMarkerUtils.apitwomd.toString(), zip, Constant.UTF8);
        }


//        if (StringUtils.isNotEmpty(FreeMarkerUtils.apidict)) {
//            zip.putNextEntry(new ZipEntry("doc/dict.md"));
//            IOUtils.write(FreeMarkerUtils.apidict.toString(), zip, Constant.UTF8);
//        }
//
        IOUtils.closeQuietly(zip);
        return outputStream.toByteArray();
    }

    @Override
    public void synchDb(Long tableId) {
        GentableEntity table = this.get(tableId);

        List<GentableColumnEntity> tableColumns = gentableColumnService.find(new GentableColumnQuery().tableId(table.getId()));
        table.setColumns(tableColumns);

        List<String> tableColumnNames = tableColumns.stream().map(GentableColumnEntity::getColumnName).collect(Collectors.toList());

        List<GentableColumnEntity> dbTableColumns = gentableColumnService.selectDbTableColumnsByName(table.getTableName());
        if (StringUtils.isEmpty(dbTableColumns)) {
            throw new AppException("同步数据失败，原表结构不存在");
        }
        List<String> dbTableColumnNames = dbTableColumns.stream().map(GentableColumnEntity::getColumnName).collect(Collectors.toList());

        dbTableColumns.forEach(column -> {
            if (!tableColumnNames.contains(column.getColumnName())) {
                GenUtils.initColumnField(column, table);
                gentableColumnService.save(column);
            }
        });

        List<GentableColumnEntity> delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList());
        if (StringUtils.isNotEmpty(delColumns)) {
            Long[] ids = delColumns.stream().map(GentableColumnEntity::getId).toArray(Long[]::new);
            gentableColumnService.remove(ids, null);
        }
    }


    public void synchDb(Long tableId, List<GentableColumnEntity> dbTableColumns) {
        GentableEntity table = this.get(tableId);

        List<GentableColumnEntity> tableColumns = gentableColumnService.find(new GentableColumnQuery().tableId(table.getId()));
        table.setColumns(tableColumns);

        List<String> tableColumnNames = tableColumns.stream().map(GentableColumnEntity::getColumnName).collect(Collectors.toList());

        List<String> dbTableColumnNames = dbTableColumns.stream().map(GentableColumnEntity::getColumnName).collect(Collectors.toList());


        dbTableColumns.forEach(column -> {
            //新增列
            if (!tableColumnNames.contains(column.getColumnName())) {
                GenUtils.initColumnField(column, table);
                gentableColumnService.save(column);
            } else {
                //todo 更新列
                GentableColumnEntity columnEntity = tableColumns.stream().filter(f -> f.getColumnName().equals(column.getColumnName())).findFirst().orElseGet(() -> null);
                if (!ObjectUtils.isEmpty(columnEntity)) {
                    columnEntity.setColumnComment(column.getColumnComment());
                    columnEntity.setDefaultValue(column.getDefaultValue());
                    columnEntity.setColumnType(column.getColumnType());
                    gentableColumnService.update(columnEntity);
                }

            }
        });

        //删除多于列
        List<GentableColumnEntity> delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList());
        if (StringUtils.isNotEmpty(delColumns)) {
            Long[] ids = delColumns.stream().map(GentableColumnEntity::getId).toArray(Long[]::new);
            gentableColumnService.remove(ids, null);
        }
    }

    @Override
    public void importDoc(MultipartFile file, Long appId, Context context) {

        List<GentableEntity> tableList = ReadDoc.readWord(file);
        String operName = context.getUser().getLoginName();
        try {
            for (GentableEntity table : tableList) {
                GenUtils.initTable(table, operName);
                table.setAppId(appId);
                table.setGenType(0);
                table.setIsGenExport(0);
                table.setIsShowControl(0);
                table.setGenPath("/");
                table.setTplCategory("crud");
                table.setCacheServiceType(CacheServiceTypeEnum.NORMAL_SERVICE.getValue());

                //查询如果存在相同表名，先删除后再添加
                GentableEntity gentableEntity = this.selectOne(new GentableQuery().tableName(table.getTableName()).appId(appId));
                if (!ObjectUtils.isEmpty(gentableEntity)) {
                    synchDb(gentableEntity.getId(), table.getColumns());
//                    //删除表
//                    this.remove(gentableEntity.getId(), context);
//                    //删除列
//                    List<GentableColumnEntity> gentableColumnEntities = gentableColumnService.find(new GentableColumnQuery().tableId(gentableEntity.getId()));
//                    if (ObjectUtils.isEmpty(gentableColumnEntities)) {
//                        gentableEntity.setColumns(gentableColumnEntities);
//                        gentableColumnService.remove(gentableEntity.getColumns().stream().map(item -> item.getId()).toArray(Long[]::new), context);
//                    }
                } else {

                    //保存表
                    this.save(table);
                    //保存列
                    List<GentableColumnEntity> genTableColumns = table.getColumns();

                    //校验是否有主键列，如果没有，默认第一列为主键
                    GentableColumnEntity columnEntity = genTableColumns.stream().filter(f -> f.getIsPrimaryKey() != null).filter(f -> f.getIsPrimaryKey() == 1).findFirst().orElseGet(() -> null);
                    if (ObjectUtils.isEmpty(columnEntity)) {
                        if (genTableColumns.size() > 0) {
                            genTableColumns.get(0).setIsPrimaryKey(YesNo.YES.getValue());
                        }
                    }

                    for (GentableColumnEntity column : genTableColumns) {
                        GenUtils.initColumnField(column, table);
                        gentableColumnService.save(column);
                    }

                }
            }
        } catch (Exception e) {
            log.error("异常:", e);
            throw new AppException("导入失败：" + e.getMessage());
        }

    }

    @Override
    public byte[] exportDoc(ProjectInfoEntity projectInfoEntity) {
        return generatorDoc(projectInfoEntity);
    }

    @Override
    public void crateTableBySql(String tableSql, Context context) {

        Pattern p = Pattern.compile("(?ms)('(?:''|[^'])*')|--.*?$|/\\*.*?\\*/");
        tableSql = p.matcher(tableSql).replaceAll("$1");

        log.info("去除注释后的sql:" + tableSql);

        //校验部分命令 禁止使用 比如清库的

//        if(tableSql.indexOf("")!=-1){
//            throw new AppException("禁止使用");
//        }

        List<String> list = StrUtil.splitTrim(tableSql, ";".charAt(0), -1);

        list.stream().filter(f -> !ObjectUtils.isEmpty(f)).peek(item -> {
            log.info("sql:" + item);
            this.getDao().createTable(item);
        }).count();

    }

    /**
     * 查询表信息并生成代码
     */
    private void generatorCode(Long tableId, String genTypes, ZipOutputStream zip) {
        GentableEntity gentableEntity = this.get(tableId);
        Set<String> types = StrUtil.splitTrim(genTypes, ",".charAt(0), -1).stream().collect(Collectors.toSet());
        if (!ObjectUtils.isEmpty(gentableEntity)) {
            List<GentableColumnEntity> columnEntities = this.gentableColumnService.find(new GentableColumnQuery().tableId(gentableEntity.getId())).stream().map(column -> {
                String temp1 = StringUtils.substringBetween(column.getColumnComment(), "(", ")");
                String temp2 = StringUtils.substringBetween(column.getColumnComment(), "（", "）");
                GenUtils.checkDict(column, temp1);
                GenUtils.checkDict(column, temp2);
                return column;
            }).collect(Collectors.toList());

            gentableEntity.setColumns(columnEntities);

            // 设置主子表信息
            setSubTable(gentableEntity);
            // 设置主键列信息
            setPkColumn(gentableEntity);

            //生成模板基础数据
            Map data = FreeMarkerUtils.prepareSetFreeMarkerData(gentableEntity);

            List<String> templates = FreeMarkerUtils.getTemplateList(gentableEntity.getTplCategory());
            for (String temp : templates) {
                if (!types.contains("1") && types.contains("2")) {
                    //只生成model类型
                    Set<String> modelTemplateSet = FreeMarkerUtils.getModelTemplateSet();
                    if (!modelTemplateSet.contains(temp)) {
                        continue;
                    }
                }

                //通过模板生成不同的业务类
                if (temp.equals("enum.java.ftl")) {
                    //单独生成枚举类
                    List<GentableColumnEntity> collect = gentableEntity.getColumns().stream()
                            .filter(f -> f.getDict() != null)
                            .map(item -> {

                                Map enumData = FreeMarkerUtils.prepareSetFreeMarkerDataByEnum(item.getDict(), item.getColumnComment(), item.getColumnName(), item.getJavaType());
                                try {
                                    FreeMarkerUtils.initFreeMarker(genFreePath(temp));
                                    StringWriter sw = new StringWriter();
                                    Template template = FreeMarkerUtils.getTemplate(temp);
                                    template.process(enumData, sw);
                                    String enumFileName = FreeMarkerUtils.getEnumFileName(item.getColumnName());
                                    File file = new File(enumFileName);
                                    if (file.exists()) {
                                        return item;
                                    }
                                    zip.putNextEntry(new ZipEntry(enumFileName));
                                    IOUtils.write(sw.toString(), zip, Constant.UTF8);
                                    IOUtils.closeQuietly(sw);
                                    zip.flush();
                                    zip.closeEntry();
                                } catch (Exception e) {
                                    log.error("渲染模板失败，表名：" + gentableEntity.getTableName(), e);
                                }
                                return item;
                            })
                            .collect(Collectors.toList());
                    continue;

                }

                try {
                    FreeMarkerUtils.initFreeMarker(genFreePath(temp));
                    StringWriter sw = new StringWriter();
                    Template template = FreeMarkerUtils.getTemplate(temp);
                    template.process(data, sw);
                    // 添加到zip
                    if (template.getName().equals("menu.sql.ftl")) {
                        FreeMarkerUtils.menuSql.append(sw.toString());
                    } else if (template.getName().equals("db.sql.ftl")) {
                        FreeMarkerUtils.dbSql.append(sw.toString());
                    } else if (template.getName().equals("params.sql.ftl")) {
                        FreeMarkerUtils.paramsSql.append(sw.toString());
                    } else if (template.getName().equals("api.md.ftl")) {
                        FreeMarkerUtils.apimd.append(sw.toString());
                    } else if (template.getName().equals("api-two.md.ftl")) {
                        FreeMarkerUtils.apitwomd.append(sw.toString());
                    } else if (template.getName().equals("apidict.md.ftl")) {
                        FreeMarkerUtils.apidict.append(sw.toString() + "\n");
                    } else {
                        zip.putNextEntry(new ZipEntry(FreeMarkerUtils.getFileName(template.getName(), gentableEntity)));
                        IOUtils.write(sw.toString(), zip, Constant.UTF8);
                    }

                    IOUtils.closeQuietly(sw);
                    zip.flush();
                    zip.closeEntry();
                } catch (Exception e) {
                    log.error("渲染模板失败，表名：" + gentableEntity.getTableName(), e);
                }
            }

        }
    }

    /**
     * 生成文档
     */
    private byte[] generatorDoc(ProjectInfoEntity projectInfo) {
        //构建列表
        Long[] tableIds = Convert.toLongArray(projectInfo.getTables());
        List<GentableEntity> list = new ArrayList<>();

        for (Long tableId : tableIds) {
            GentableEntity gentableEntity = this.get(tableId);
            if (!ObjectUtils.isEmpty(gentableEntity)) {
                List<GentableColumnEntity> columnEntities = this.gentableColumnService.find(new GentableColumnQuery().tableId(gentableEntity.getId()));
                gentableEntity.setColumns(columnEntities);
                // 设置主子表信息
                setSubTable(gentableEntity);
                // 设置主键列信息
                setPkColumn(gentableEntity);
                list.add(gentableEntity);
            }
        }

        Map data = FreeMarkerUtils.prepareSetFreeMarkerDataByDoc(list, projectInfo);
        ConfigureBuilder builder = Configure.builder();
        builder.bind("columns", new MultipleRowTableRenderPolicy());

        Configure config = Configure.builder().useSpringEL().bind("columns", new MultipleRowTableRenderPolicy()).build();

        XWPFTemplate template = null;
        ByteArrayOutputStream byteArrayOutputStream = null;
        try {
            ClassPathResource classPathResource = new ClassPathResource("template/doc/base.docx");
           // InputStream inputStream = classPathResource.getInputStream();
            template = XWPFTemplate.compile(  classPathResource.getInputStream(), config).render(data);
            byteArrayOutputStream = new ByteArrayOutputStream();
            template.write(byteArrayOutputStream);
            return byteArrayOutputStream.toByteArray();
        } catch (Exception e) {
            log.error("渲染模板失败：", e);
            return null;
        } finally {
            try {
                template.close();
                byteArrayOutputStream.close();
            } catch (IOException e) {
                log.error("ioEx：", e);
            }

        }

        //通过模板生成不同的业务类
/*        String temp = "db.doc.ftl";
        try {
            FreeMarkerUtils.initFreeMarker(genFreePath(temp));
            StringWriter sw = new StringWriter();
            Template template = FreeMarkerUtils.getTemplate(temp);
            template.process(data, sw);
            return sw.toString().getBytes(Constant.UTF8);
        } catch (Exception e) {
            log.error("渲染模板失败：" , e);
            return null;
        }*/

    }

    /**
     * 设置主键列信息
     *
     * @param table 业务表信息
     */
    public void setPkColumn(GentableEntity table) {
        for (GentableColumnEntity column : table.getColumns()) {
            if (column.getIsPrimaryKey() == YesNo.YES.getValue()) {
                //是主键 设置主键列
                table.setPkColumn(column);
                break;
            }
        }
        if (StringUtils.isNull(table.getPkColumn())) {
            table.setPkColumn(table.getColumns().get(0));
        }
        new UserInfo();
        if (GenConstants.TPL_SUB.equals(table.getTplCategory()) && !ObjectUtils.isEmpty(table.getSubTable())) {
            for (GentableColumnEntity column : table.getSubTable().getColumns()) {
                if (column.getIsPrimaryKey() == YesNo.YES.getValue()) {
                    table.getSubTable().setPkColumn(column);
                    break;
                }
            }
            if (StringUtils.isNull(table.getSubTable().getPkColumn())) {
                table.getSubTable().setPkColumn(table.getSubTable().getColumns().get(0));
            }
        }
    }

    /**
     * 设置主子表信息
     *
     * @param table 业务表信息
     */
    public void setSubTable(GentableEntity table) {
        String subTableName = table.getSubTableName();
        if (StringUtils.isNotEmpty(subTableName)) {
            GentableEntity gentableEntity = this.selectOne(new GentableQuery().tableName(subTableName));
            if (!ObjectUtils.isEmpty(gentableEntity)) {
                List<GentableColumnEntity> columnEntities = gentableColumnService.find(new GentableColumnQuery().tableId(gentableEntity.getId()));
                gentableEntity.setColumns(columnEntities);
                setPkColumn(gentableEntity);
                table.setSubTable(gentableEntity);
            }
        }
    }


    @Override
    protected void removeAfter(Long[] ids, Context context, int result) throws AppException {
        Long[] colIds = gentableColumnService.find(new GentableColumnQuery().tableIdList(Arrays.asList(ids))).stream().map(GentableColumnEntity::getId).toArray(Long[]::new);
        gentableColumnService.remove(colIds, context);
        super.removeAfter(ids, context, result);
    }

    private String genFreePath(String temp) {
        String path = "";
        if (temp.indexOf(".java.") != -1) {
            path = "java";
        } else if (temp.indexOf(".sql.") != -1) {
            path = "sql";
        } else if (temp.indexOf(".test.") != -1) {
            path = "java";
        } else if (temp.indexOf(".xml.") != -1) {
            path = "xml";
        } else if (temp.indexOf(".vue.") != -1) {
            path = "vue";
        } else if (temp.indexOf(".doc.") != -1) {
            path = "doc";
        } else if (temp.indexOf(".md.") != -1) {
            path = "doc";
        }
        return path;
    }
}