package cc.smtweb.system.bpm.web.design.form;

import cc.smtweb.framework.core.common.R;
import cc.smtweb.framework.core.common.SwEnum;
import cc.smtweb.framework.core.common.SwMap;
import cc.smtweb.framework.core.db.cache.ModelTableCache;
import cc.smtweb.framework.core.db.vo.ModelCache;
import cc.smtweb.framework.core.db.vo.ModelField;
import cc.smtweb.framework.core.db.vo.ModelTable;
import cc.smtweb.framework.core.exception.BizException;
import cc.smtweb.framework.core.mvc.service.AbstractHandler;
import cc.smtweb.framework.core.util.DateUtil;
import cc.smtweb.framework.core.util.MapUtil;
import cc.smtweb.framework.core.util.SpringUtil;
import cc.smtweb.system.bpm.spring.BpmConfigBean;
import cc.smtweb.system.bpm.util.CodeGenUtil;
import cc.smtweb.system.bpm.util.CodeGenerator;
import cc.smtweb.system.bpm.util.IdeaUtil;
import cc.smtweb.system.bpm.web.design.db.ModelCatalogCache;
import cc.smtweb.system.bpm.web.design.db.ModelProjectCache;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by Akmm at 2022/6/14 20:11
 * 生成代码
 */
public class CodeBuildHandler extends AbstractHandler {
    private static final String SRC_MAIN_JAVA = "/src/main/java/";
    private static final String SRC_MAIN_RES = "/src/main/resources";

    private String userName;
    //java文件所在路径
    private String codePath;
    private String packageName;
    private BpmConfigBean bpmConfigBean;

    public R buildJavaCode() {
        userName = String.valueOf(us.getUserId());

        //页面id
        long pageId = params.readLong("pageId");

        //是否需要创建服务
        boolean needBuildService = params.readBool("service");
        //实体相关
        List<Map<String, Object>> tables = params.readListMap("table");

        buildCodeJavaPath(pageId);
        for (Map<String, Object> map : tables) {
            final boolean needBean = MapUtil.readBool(map, "bean");
            final boolean needCache = MapUtil.readBool(map, "cache");
            if (!needBean && !needCache) continue;
            long tableId = MapUtil.readLong(map, "tableId");
            buildJavaTable(tableId, needBean, needCache);
        }
        if (needBuildService) buildJavaService(pageId);
        System.out.println("JAVA代码路径：" + codePath);
        return R.success();
    }

    public R buildBeanByTable() {
        userName = String.valueOf(us.getUserId());

        //页面id
        long tableId = params.readLong("tableId");
        ModelTable table = ModelTableCache.getInstance().get(tableId);
        if (table == null) throw new BizException("未找到指定的表定义(" + table + ")！");

        String moduleName = ModelProjectCache.getInstance().getModule(table.getPrjId());
        if (StringUtils.isEmpty(moduleName)) throw new BizException("此项目未定义Module！");
        if (moduleName.equals("bpm")) {
            packageName = "cc.smtweb.system.bpm.web";
        } else {
            packageName = "cc.smtweb.biz." + moduleName + ".web";
        }
        BpmConfigBean bpmConfigBean = SpringUtil.getBean(BpmConfigBean.class);
        Map<String, String> mapIdeaModules = IdeaUtil.getModules(bpmConfigBean.getCodeJavaPath(), bpmConfigBean.getMode());
        if (mapIdeaModules == null || mapIdeaModules.isEmpty())
            throw new BizException("没有定义idea项目的路径(smtweb.bpm.codeJavaPath)！");
        codePath = mapIdeaModules.get(moduleName);
        if (StringUtils.isEmpty(codePath)) {
            throw new BizException("没有找到对应项目在idea中Module的路径(" + moduleName + ")！");
        }
        codePath += "/src/main/java/";
        //加上目录
        String cn = ModelCatalogCache.getInstance().getFullName(table.getMcId());
        if (StringUtils.isNotEmpty(cn)) {
            packageName += "." + cn;
        }

        codePath += packageName.replaceAll("\\.", "/");
        new File(codePath).mkdirs();

        buildJavaTable(tableId, true, table.isNeedCache());
        System.out.println("JAVA代码路径：" + codePath);
        return R.success();
    }

    public R buildJsCode() {
        userName = String.valueOf(us.getUserId());
        //页面id
        String pageId = params.readString("pageId");
        ModelForm form = ModelFormHelper.getFromCache(pageId);
        if (form == null) throw new BizException("未找到指定的页面定义(" + pageId + ")！");
        String moduleName = ModelProjectCache.getInstance().getModule(form.getPrjId());
        if (StringUtils.isEmpty(moduleName)) throw new BizException("此项目未定义Module！");

        final String eventPath = ModelFormHelper.getEventPath(form);
        codePath = ModelFormHelper.getCodePath(form) + "/src/main/resources/static/event/" + eventPath.replaceAll("\\.", "/");
        new File(codePath).mkdirs();

        SwMap model = new SwMap();
        model.put("user", userName);
        model.put("sysTime", DateUtil.nowDateTime());
        model.put("title", form.getTitle());
        model.put("eventPath", eventPath + "." + form.getName());
        CodeGenerator.getInstance().generateJsEvent(model, codePath + "/" + form.getName() + ".js");
        System.out.println("JS代码路径：" + codePath);
        return R.success();
    }

    /**
     * 构建java代码路径
     *
     * @param pageId 页面id
     */
    private void buildCodeJavaPath(long pageId) {
        ModelForm form = ModelFormCache.getInstance().get(pageId);
        if (form == null) throw new BizException("未找到指定的页面定义(" + pageId + ")！");
        String moduleName = ModelProjectCache.getInstance().getModule(form.getPrjId());
        if (StringUtils.isEmpty(moduleName)) throw new BizException("此项目未定义Module！");

        if (moduleName.equals("bpm")) {
            packageName = "cc.smtweb.system.bpm.web";
        } else {
            packageName = "cc.smtweb.biz." + moduleName + ".web";
        }
        BpmConfigBean bpmConfigBean = SpringUtil.getBean(BpmConfigBean.class);
        Map<String, String> mapIdeaModules = IdeaUtil.getModules(bpmConfigBean.getCodeJavaPath(), bpmConfigBean.getMode());
        if (mapIdeaModules == null || mapIdeaModules.isEmpty())
            throw new BizException("没有定义idea项目的路径(smtweb.bpm.codeJavaPath)！");
        codePath = mapIdeaModules.get(moduleName);
        if (StringUtils.isEmpty(codePath)) {
            throw new BizException("没有找到对应项目在idea中Module的路径(" + moduleName + ")！");
        }
        codePath += "/src/main/java/";
        //加上目录
        String cn = ModelCatalogCache.getInstance().getFullName(form.getMcId());
        if (StringUtils.isNotEmpty(cn)) {
            packageName += "." + cn;
        }
        String pn = ModelFormHelper.getFormParentName(form);
        if (StringUtils.isNotEmpty(pn)) packageName += "." + pn;

        codePath += packageName.replaceAll("\\.", "/");
        new File(codePath).mkdirs();
    }

    /**
     * 生成bean
     *
     * @param tableId
     */
    private void buildJavaTable(long tableId, boolean needBean, boolean needCache) {
        ModelTable table = ModelTableCache.getInstance().get(tableId);
        if (table == null) throw new BizException("没有找到对应的表定义(" + tableId + ")！");
        SwMap model = new SwMap();
        model.put("user", userName);
        model.put("sysTime", DateUtil.nowDateTime());
        model.put("packageName", packageName);
        model.put("tableName", table.getName());
        model.put("tableTitle", table.getTitle());

        final String beanName = CodeGenUtil.getBeanName(table.getName());
        model.put("beanName", beanName);
        if (needBean) {
            List<SwMap> fields = new ArrayList<>();
            model.put("fields", fields);
            for (ModelField field : table.getFields()) {
                SwMap fn = new SwMap();
                fields.add(fn);
                fn.put("name", field.getName());
                fn.put("title", field.getTitle());
                String javaName = CodeGenUtil.getBeanName(field.getName());
                if (SwEnum.DataType.BOOL.value.equals(field.getDataType()) && javaName.startsWith("Is")) {
                    javaName = javaName.substring(2);
                }
                fn.put("javaName", javaName);
                SwEnum.DataTypeBean dtb = SwEnum.DataType.instance.getByValue(field.getDataType());
                fn.put("javaType", dtb.javaType);
                fn.put("shortJavaType", dtb.shortJavaType);
            }

            CodeGenerator.getInstance().generateBean(model, codePath + "/" + beanName + ".java");
        }

        if (needCache) {
            if (!table.isNeedCache()) throw new BizException("表设置为不需要缓存！" + table.getTitle());
            List<SwMap> caches = new ArrayList<>();
            model.put("caches", caches);
            for (ModelCache cache : table.getCaches()) {
                SwMap fn = new SwMap();
                caches.add(fn);
                final String name = cache.getName();
                fn.put("name", name);
                fn.put("nameUF", CodeGenUtil.toUpperHump(name));
                fn.put("title", cache.getTitle());
                fn.put("fields", cache.getFields());
                fn.put("type", cache.getType());
            }

            CodeGenerator.getInstance().generateCache(model, codePath + "/" + beanName + "Cache.java");
        }
    }

    private void buildJavaService(long pageId) {
        ModelForm form = ModelFormCache.getInstance().get(pageId);
        String sName = form.getService();
        if (StringUtils.isEmpty(sName)) {
            //模块名称
            form = ModelFormCache.getInstance().get(form.getParent());
            if (form == null) {
                throw new BizException("页面设置未定义服务名！" + form.getTitle());
            }
            sName = form.getService();
            if (StringUtils.isEmpty(sName)) {
                throw new BizException("模块设置未定义服务名！" + form.getTitle());
            }
        }
        sName = CodeGenUtil.toUpperHump(sName);

        SwMap model = new SwMap();
        model.put("user", userName);
        model.put("sysTime", DateUtil.nowDateTime());
        model.put("packageName", packageName);
        model.put("formTitle", form.getTitle());
        model.put("service", sName);
        model.put("eventPath", ModelFormHelper.getEventPath(form));

        CodeGenerator.getInstance().generateService(model, codePath + "/" + sName + "Service.java");
    }
}
