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.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 com.mortals.xhx.module.app.model.AppEntity;
import com.mortals.xhx.module.app.service.AppService;
import freemarker.template.Template;
import lombok.SneakyThrows;
import org.apache.commons.io.IOUtils;
import org.apiguardian.api.API;
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.*;
import java.util.*;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import static com.mortals.xhx.common.utils.GenUtils.getBusinessNameExt;

/**
 * <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;
    @Autowired
    private AppService appService;


    @Override
    public List<GentableEntity> selectDbTableList(GentableQuery query) {
        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();
        String operName = "admin";
        try {
            for (GentableEntity table : tableList) {
                String tableName = table.getTableName();
                GenUtils.initTable(table, operName);
                table.setGenType(0);
                table.setIsGenExport(0);
                table.setGenFeign(0);
                table.setIsShowControl(2);
                table.setDetailShow(2);
                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) {
            log.error(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);
        String requestMapping = Arrays.stream(getBusinessNameExt(gentableEntity.getTableName()).split("\\.")).collect(Collectors.joining("/"));
        gentableEntity.setRequestMapping(requestMapping);
        buildAppInfo(gentableEntity);
        //生成模板基础数据
        Map data = FreeMarkerUtils.prepareSetFreeMarkerData(gentableEntity);
        //输出合成模板
        List<String> templates = FreeMarkerUtils.getTemplateList(gentableEntity.getTplCategory());
        for (String temp : templates) {
            if (temp.equals("enum.java.ftl")) {
                continue;
            }
            //如果开启feign生成模式，加载feign生成模板
            if (gentableEntity.getGenFeign() != null && gentableEntity.getGenFeign() == 0) {
                if (temp.contains("feign.java.ftl") || temp.contains("pdu.java.ftl")) {
                    continue;
                }
            }
            if (gentableEntity.getIsShowControl() != null) {
                if (gentableEntity.getIsShowControl() == 2) {
                    if (temp.contains("webForm.java.ftl") || temp.contains("web.java.ftl")) {
                        continue;
                    }
//                if (temp.contains("entity.java.ftl")||temp.contains("entityQuery.java.ftl")) {
//                    continue;
//                }
                } else if (gentableEntity.getIsShowControl() == 0) {
                    if (temp.contains("webBody.java.ftl")) {
                        continue;
                    }
                }
            } else {
                if (temp.contains("webForm.java.ftl") || temp.contains("web.java.ftl")) {
                    continue;
                }
            }


            if (gentableEntity.getDetailShow() != null) {
                if (gentableEntity.getDetailShow() == 0) {
                    if (temp.contains("VueDialogShow.vue.ftl") || temp.contains("VueDrawerShow.vue.ftl")) {
                        continue;
                    }
                } else if (gentableEntity.getDetailShow() == 1) {
                    if (temp.contains("webVueShow.vue.ftl") || temp.contains("VueDrawerShow.vue.ftl")) {
                        continue;
                    }
                } else if (gentableEntity.getDetailShow() == 2) {
                    if (temp.contains("webVueShow.vue.ftl") || temp.contains("VueDialogShow.vue.ftl")) {
                        continue;
                    }
                } else {
                    if (temp.contains("webVueShow.vue.ftl") || temp.contains("VueDrawerShow.vue.ftl")) {
                        continue;
                    }
                }
            } else {
                if (temp.contains("webVueShow.vue.ftl") || temp.contains("VueDrawerShow.vue.ftl")) {
                    continue;
                }
            }


            if (temp.equals("menu.sql.ftl") || temp.equals("db.sql.ftl") || temp.equals("dm_db.sql.ftl") || temp.equals("api.md.ftl") || temp.equals("apipost.md.ftl")) {
                try {
                    List<GentableEntity> tableList = new ArrayList<>();
                    tableList.add(gentableEntity);
                    data.put("tableList", tableList);
                    //初始化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);
                }
                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) {
        List<GentableEntity> tableList = new ArrayList<>();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        GentableEntity gentableEntity = generatorCode(tableId, genTypes, zip);
        tableList.add(gentableEntity);

        Map data = new HashMap();
        data.put("tableList", tableList);
        FreeMarkerUtils.initFreeMarker(genFreePath("menu.sql.ftl"));
        zipTemplate("menu.sql.ftl", "db/menu.sql", data, zip);
        zipTemplate("db.sql.ftl", "db/db.sql", data, zip);
        zipTemplate("dm_db.sql.ftl", "db/dm_db.sql", data, zip);
        FreeMarkerUtils.initFreeMarker(genFreePath("api.md.ftl"));
        zipTemplate("api.md.ftl", "doc/api.md", data, zip);
        FreeMarkerUtils.initFreeMarker(genFreePath("apipost.md.ftl"));
        zipTemplate("apipost.ftl", String.format("doc/%s.json", gentableEntity.getName()), data, zip);

        IOUtils.closeQuietly(zip);
        return outputStream.toByteArray();
    }

    @SneakyThrows
    @Override
    public byte[] downloadCode(Long[] tableIds, String genTypes) {
        List<GentableEntity> tableList = new ArrayList<>();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        for (Long tableId : tableIds) {
            GentableEntity gentableEntity = generatorCode(tableId, genTypes, zip);
            tableList.add(gentableEntity);
        }
        AppEntity appEntity = new AppEntity();
        appEntity.setName(tableList.get(0).getName());
        appEntity.setCode(tableList.get(0).getCode());
        appEntity.setPath(tableList.get(0).getPath());

        Map data = new HashMap();
        data.put("tableList", tableList);
        data.put("appInfo", appEntity);

        FreeMarkerUtils.initFreeMarker(genFreePath("menu.sql.ftl"));
        zipTemplate("menu.sql.ftl", "db/menu.sql", data, zip);
        zipTemplate("db.sql.ftl", "db/db.sql", data, zip);
        zipTemplate("dm_db.sql.ftl", "db/dm_db.sql", data, zip);
        FreeMarkerUtils.initFreeMarker(genFreePath("api.md.ftl"));
        zipTemplate("api.md.ftl", "doc/api.md", data, zip);
        zipTemplate("apipost.md.ftl", String.format("doc/%s.json", appEntity.getName()), data, zip);
        IOUtils.closeQuietly(zip);
        return outputStream.toByteArray();
    }

    private void zipTemplate(String temp, String zipPath, Map data, ZipOutputStream zip) {
        try {
            StringWriter sw = new StringWriter();
            Template template = FreeMarkerUtils.getTemplate(temp);
            template.process(data, sw);
            zip.putNextEntry(new ZipEntry(zipPath));

            IOUtils.write(sw.toString(), zip, Constant.UTF8);
        } catch (Exception e) {
            log.error("异常", e);
        }
    }

    @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) {
        try {
            List<GentableEntity> tableList = ReadDoc.readWord(file);
            //String operName = context.getUser().getLoginName();
            String operName = "admin";
            for (GentableEntity table : tableList) {
                GenUtils.initTable(table, operName);
                table.setAppId(appId);
                table.setGenType(0);
                table.setGenFeign(0);
                table.setIsGenExport(0);
                table.setIsShowControl(2);
                table.setDetailShow(2);
                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());
                } 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 GentableEntity 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 -> {
                //字典类型1  （1.xxxx,2.xxxxx）
                //字典类型2  （xxxx.xxxx,xxxx.xxxxx）
                //字典类型3  （xxxx,xxxxx）
                String temp1 = StringUtils.substringBetween(column.getColumnComment(), "(", ")");
                String temp2 = StringUtils.substringBetween(column.getColumnComment(), "（", "）");
                GenUtils.checkDict(column, temp1);
                GenUtils.checkDict(column, temp2);
                column.setColumnComment(StrUtil.removeAllLineBreaks(column.getColumnComment().replaceAll("\"","“")));
                return column;
            }).collect(Collectors.toList());

            gentableEntity.setColumns(columnEntities);
            // 设置主子表信息
            setSubTable(gentableEntity);
            // 设置主键列信息
            setPkColumn(gentableEntity);
            String requestMapping = Arrays.stream(getBusinessNameExt(gentableEntity.getTableName()).split("\\.")).collect(Collectors.joining("/"));
            gentableEntity.setRequestMapping(requestMapping);

            buildAppInfo(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")) {
                    //单独生成枚举类
                    gentableEntity.getColumns().stream()
                            .filter(f -> f.getDict() != null)
                            .map(item -> {
                                Map enumData = FreeMarkerUtils.prepareSetFreeMarkerDataByEnum(item.getDict(), item.getColumnComment(), item.getJavaField(), 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.getJavaField());
                                    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;

                }
                if (gentableEntity.getIsShowControl() != null) {
                    if (gentableEntity.getIsShowControl() == 2) {
                        if (temp.contains("webForm.java.ftl") || temp.contains("web.java.ftl")) {
                            continue;
                        }
                    } else if (gentableEntity.getIsShowControl() == 0) {
                        if (temp.contains("webBody.java.ftl")) {
                            continue;
                        }
                    }
                } else {
                    if (temp.contains("webForm.java.ftl") || temp.contains("web.java.ftl")) {
                        continue;
                    }
                }


                if (gentableEntity.getDetailShow() != null) {
                    if (gentableEntity.getDetailShow() == 0) {
                        if (temp.contains("VueDialogShow.vue.ftl") || temp.contains("VueDrawerShow.vue.ftl")) {
                            continue;
                        }
                    } else if (gentableEntity.getDetailShow() == 1) {
                        if (temp.contains("webVueShow.vue.ftl") || temp.contains("VueDrawerShow.vue.ftl")) {
                            continue;
                        }
                    } else if (gentableEntity.getDetailShow() == 2) {
                        if (temp.contains("webVueShow.vue.ftl") || temp.contains("VueDialogShow.vue.ftl")) {
                            continue;
                        }
                    } else {
                        if (temp.contains("webVueShow.vue.ftl") || temp.contains("VueDrawerShow.vue.ftl")) {
                            continue;
                        }
                    }
                } else {
                    if (temp.contains("webVueShow.vue.ftl") || temp.contains("VueDrawerShow.vue.ftl")) {
                        continue;
                    }
                }

                if (temp.equals("menu.sql.ftl")) {
                    continue;
                }
                if (temp.equals("db.sql.ftl")) {
                    continue;
                }
                if (temp.equals("dm_db.sql.ftl")) {
                    continue;
                }
                if (temp.equals("api.md.ftl")) {
                    continue;
                }
                if (temp.equals("apipost.md.ftl")) {
                    continue;
                }
                try {
                    FreeMarkerUtils.initFreeMarker(genFreePath(temp));
                    StringWriter sw = new StringWriter();
                    Template template = FreeMarkerUtils.getTemplate(temp);
                    template.process(data, sw);
                    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);
                }
            }
        }
        return gentableEntity;
    }

    private void buildAppInfo(GentableEntity gentableEntity) {
        AppEntity appEntity = appService.get(gentableEntity.getAppId());
        gentableEntity.setCode(appEntity.getCode() == null ? "" : appEntity.getCode());
        gentableEntity.setPath(appEntity.getPath() == null ? "" : appEntity.getPath());
        gentableEntity.setName(appEntity.getName() == null ? "" : appEntity.getName());
        gentableEntity.setDesc(appEntity.getRemark() == null ? "" : appEntity.getRemark());
    }


    /**
     * 生成文档
     */
    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)) {
                buildAppInfo(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 {

            InputStream in = this.getClass().getResourceAsStream("/template/doc/base.docx");
           // ClassPathResource classPathResource = new ClassPathResource("template/doc/base.docx");
            template = XWPFTemplate.compile(in, 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);
            }
        }
    }

    /**
     * 设置主键列信息
     *
     * @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 {
        super.removeAfter(ids, context, result);

//        GentableColumnQuery condition = new GentableColumnQuery();
//        condition.setTableIdList(Arrays.asList(ids));
//
//        gentableColumnService.getDao().delete(condition);

        Long[] colIds = gentableColumnService.find(new GentableColumnQuery().tableIdList(Arrays.asList(ids))).stream().map(GentableColumnEntity::getId).toArray(Long[]::new);
        gentableColumnService.remove(colIds, context);

    }

    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;
    }
}