package ${basePackage};

import ${basePackage}.frame.auth.Token;
import ${basePackage}.frame.base.BaseResponse;
import ${basePackage}.frame.utils.MapperUtil;
import ${basePackage}.frame.utils.Message;
import ${basePackage}.module.system.ent.Res;
import ${basePackage}.module.system.mgr.DictItemManager;
import ${basePackage}.module.system.mgr.DictManager;
import ${basePackage}.module.system.mgr.ResManager;
import ${basePackage}.module.system.mgr.RoleManager;
import ${basePackage}.module.system.mgr.RoleResManager;
import ${basePackage}.module.system.req.DictCreateRequest;
import ${basePackage}.module.system.req.DictItemCreateRequest;
import ${basePackage}.module.system.req.ResCreateRequest;
import ${basePackage}.module.system.req.ResFindRequest;
import ${basePackage}.module.system.req.RoleCreateRequest;
import ${basePackage}.module.system.req.RoleResCheckRequest;
import ${basePackage}.module.system.rsp.DictCreateResponse;
import ${basePackage}.module.system.rsp.DictItemCreateResponse;
import ${basePackage}.module.system.rsp.ResCreateResponse;
import ${basePackage}.module.system.rsp.ResFindResponse;
import ${basePackage}.module.system.rsp.RoleCreateResponse;
import ${basePackage}.module.system.rsp.RoleResCheckResponse;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static org.junit.Assert.assertTrue;

@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class DataInit {

    @Autowired
    private DictManager dictManager;
    @Autowired
    private DictItemManager dictItemManager;
    @Autowired
    private ResManager resManager;
    @Autowired
    private RoleManager roleManager;
    @Autowired
    private RoleResManager roleCreateRequest;
    @Autowired
    private Token token;

    /**
     * 字典数据初始化
     */
    @Test
    @Rollback(false)
    public void init() {
        //region 字典初始化
        {
            {// 终端类型
                createDict("TERMINAL_TYPE", "终端类型", new String[][]{
                        {"WEB", "游览器端"},
                        {"API", "接口端"},
                        {"PHONE", "手机端"},
                });
            }

            {// 错误日志结果
                createDict("LOG_ERR_RESULT", "错误日志结果", new String[][]{
                        {"未处理", "未处理"},
                        {"已处理", "已处理"},
                        {"搁置", "搁置"},
                });
            }

            {// 资源类型
                createDict("RES_TYPE", "资源类型", new String[][]{
                        {"菜单", "菜单"},
                        {"网页", "网页"},
                        {"请求", "请求"},
                });
            }
            {// 用户状态
                createDict("USER_STATUS", "用户状态", new String[][]{
                        {"正常", "正常"},
                        {"初始密码", "初始密码"},
                        {"锁定/注销", "锁定/注销"},
                });
            }
            {// 日志错误类型
                createDict("LOG_ERR_TYPE", "日志错误类型", new String[][]{
                        {"系统错误", "系统错误"},
                        {"业务错误", "业务错误"},
                });
            }
            {// 文件类型
                createDict("FILE_TYPE", "文件类型", new String[][]{
                        {"IMG", "图片"},
                });
            }
        }
        //endregion

        //region 管理员初始化
        {
            List<Res> forDev = new ArrayList<>();
            {// 初始化开发角色特有资源
                forDev.add(createRes("DEV", "开发管理", "菜单", "DEV"));
                forDev.add(createRes("DEV_RES", "资源管理", "网页", "/system/res.htm"));
                forDev.add(createRes("DEV_RES_CREATE", "资源新增", "请求", "/ajax/system/res/create"));
                forDev.add(createRes("DEV_RES_DELETE", "资源删除", "请求", "/ajax/system/res/delete"));
                forDev.add(createRes("DEV_RES_UPDATE", "资源编辑", "请求", "/ajax/system/res/update"));
                forDev.add(createRes("DEV_RES_FIND", "资源查询", "请求", "/ajax/system/res/find"));
                forDev.add(createRes("DEV_RES_GET", "资源获取", "请求", "/ajax/system/res/get"));
                forDev.add(createRes("DEV_TASK", "计划调度", "网页", "/system/schedule.htm"));
                forDev.add(createRes("DEV_LOGERR", "错误日志", "网页", "/system/logErr.htm"));
                forDev.add(createRes("DEV_LOGERR_DELETE", "错误日志删除", "请求", "/ajax/system/logErr/delete"));
                forDev.add(createRes("DEV_LOGERR_UPDATE", "错误日志更新", "请求", "/ajax/system/logErr/update"));
                forDev.add(createRes("DEV_LOGERR_FIND", "错误日志查询", "请求", "/ajax/system/logErr/find"));
            }

            List<Res> forMgr = new ArrayList<>();
            {// 初始化管理资源
                forMgr.add(createRes("SYS", "系统管理", "菜单", "SYS"));
                forMgr.add(createRes("SYS_INDEX_ROOT", "根页", "网页", "/"));
                forMgr.add(createRes("SYS_INDEX", "主页", "网页", "/index.htm"));
                forMgr.add(createRes("SYS_INDEX_HOME", "首页", "网页", "/home.htm"));

                forMgr.add(createRes("SYS_DICT", "字典管理", "网页", "/system/dict.htm"));
                forMgr.add(createRes("SYS_DICT_CREATE", "字典新建", "请求", "/ajax/system/dict/create"));
                forMgr.add(createRes("SYS_DICT_DELETE", "字典删除", "请求", "/ajax/system/dict/delete"));
                forMgr.add(createRes("SYS_DICT_UPDATE", "字典更新", "请求", "/ajax/system/dict/update"));
                forMgr.add(createRes("SYS_DICT_FIND", "字典查询", "请求", "/ajax/system/dict/find"));
                forMgr.add(createRes("SYS_DICT_GET", "字典获取", "请求", "/ajax/system/dict/get"));
                forMgr.add(createRes("SYS_DICT_IMPORT", "字典导入", "请求", "/ajax/system/dict/imports"));
                forMgr.add(createRes("SYS_DICT_EXPORT", "字典导出", "请求", "/ajax/system/dict/exports"));
                forMgr.add(createRes("SYS_DICT_ITEM", "字典项管理", "网页", "/system/dictItem.htm"));
                forMgr.add(createRes("SYS_DICT_ITEM_CREATE", "字典项新增", "请求", "/ajax/system/dictItem/create"));
                forMgr.add(createRes("SYS_DICT_ITEM_DELETE", "字典项删除", "请求", "/ajax/system/dictItem/delete"));
                forMgr.add(createRes("SYS_DICT_ITEM_UPDATE", "字典项更新", "请求", "/ajax/system/dictItem/update"));
                forMgr.add(createRes("SYS_DICT_ITEM_FIND", "字典项查找", "请求", "/ajax/system/dictItem/find"));
                forMgr.add(createRes("SYS_DICT_ITEM_GET", "字典项获取", "请求", "/ajax/system/dictItem/get"));
                forMgr.add(createRes("SYS_DICT_LOAD", "字典详情", "请求", "/ajax/system/dict/load"));

                forMgr.add(createRes("SYS_RES_TREE", "资源树查询", "请求", "/ajax/system/res/tree"));

                forMgr.add(createRes("SYS_USER", "用户管理", "网页", "/system/user.htm"));
                forMgr.add(createRes("SYS_USER_CREATE", "用户新增", "请求", "/ajax/system/user/create"));
                forMgr.add(createRes("SYS_USER_DELETE", "用户删除", "请求", "/ajax/system/user/delete"));
                forMgr.add(createRes("SYS_USER_UPDATE", "用户更新", "请求", "/ajax/system/user/update"));
                forMgr.add(createRes("SYS_USER_FIND", "用户查询", "请求", "/ajax/system/user/find"));
                forMgr.add(createRes("SYS_USER_GET", "用户获取", "请求", "/ajax/system/user/get"));
                forMgr.add(createRes("SYS_USER_IMPORT", "用户导入", "请求", "/ajax/system/user/imports"));
                forMgr.add(createRes("SYS_USER_EXPORT", "用户导出", "请求", "/ajax/system/user/exports"));

                forMgr.add(createRes("SYS_DEPT", "机构管理", "网页", "/system/dept.htm"));
                forMgr.add(createRes("SYS_DEPT_CREATE", "机构新增", "请求", "/ajax/system/dept/create"));
                forMgr.add(createRes("SYS_DEPT_DELETE", "机构删除", "请求", "/ajax/system/dept/delete"));
                forMgr.add(createRes("SYS_DEPT_UPDATE", "机构更新", "请求", "/ajax/system/dept/update"));
                forMgr.add(createRes("SYS_DEPT_FIND", "机构查询", "请求", "/ajax/system/dept/find"));
                forMgr.add(createRes("SYS_DEPT_GET", "机构获取", "请求", "/ajax/system/dept/get"));
                forMgr.add(createRes("SYS_DEPT_TREE", "机构树查询", "请求", "/ajax/system/dept/tree"));
                forMgr.add(createRes("SYS_DEPT_IMPORT", "机构导入", "请求", "/ajax/system/dept/imports"));
                forMgr.add(createRes("SYS_DEPT_EXPORT", "机构导出", "请求", "/ajax/system/dept/exports"));

                forMgr.add(createRes("SYS_FILE", "文件管理", "网页", "/system/file.htm"));
                forMgr.add(createRes("SYS_FILE_DELETE", "文件删除", "请求", "/ajax/system/file/delete"));
                forMgr.add(createRes("SYS_FILE_FIND", "文件查询", "请求", "/ajax/system/file/find"));

                forMgr.add(createRes("SYS_ROLE", "角色管理", "网页", "/system/role.htm"));
                forMgr.add(createRes("SYS_ROLE_CREATE", "角色新增", "请求", "/ajax/system/role/create"));
                forMgr.add(createRes("SYS_ROLE_DELETE", "角色删除", "请求", "/ajax/system/role/delete"));
                forMgr.add(createRes("SYS_ROLE_UPDATE", "角色更新", "请求", "/ajax/system/role/update"));
                forMgr.add(createRes("SYS_ROLE_FIND", "角色查询", "请求", "/ajax/system/role/find"));
                forMgr.add(createRes("SYS_ROLE_GET", "角色获取", "请求", "/ajax/system/role/get"));
                forMgr.add(createRes("SYS_ROLE_RESCHECK", "角色资源分配", "请求", "/ajax/system/roleRes/check"));
                forMgr.add(createRes("SYS_ROLE_ROLERES", "角色资源关系查询", "请求", "/ajax/system/roleRes/find"));

                forMgr.add(createRes("SYS_TOKENS", "登录凭证管理", "网页", "/system/tokens.htm"));
                forMgr.add(createRes("SYS_TOKENS_FIND", "登录凭证查询", "请求", "/ajax/system/tokens/find"));
                forMgr.add(createRes("SYS_TOKENS_EXPORT", "凭证导出", "请求", "/ajax/system/tokens/exports"));
                forMgr.add(createRes("SYS_TOKENS_LOGOUT", "凭证注销", "请求", "/ajax/system/tokens/logout"));

<#list project.modules as module>
    <#list module.tables as table>
        <#if table.html>
                forMgr.add(createRes("WEB_${table.tableName}", "${table.tableComment}管理", "网页", "/${module.moduleName}/${table.getFName()}.htm"));
        </#if>
        <#if table.create>
                forMgr.add(createRes("WEB_${table.tableName}_CREATE", "${table.tableComment}新增", "请求", "/ajax/${module.moduleName}/${table.getFName()}/create"));
        </#if>
        <#if table.delete>
                forMgr.add(createRes("WEB_${table.tableName}_DELETE", "${table.tableComment}删除", "请求", "/ajax/${module.moduleName}/${table.getFName()}/delete"));
        </#if>
        <#if table.update>
                forMgr.add(createRes("WEB_${table.tableName}_UPDATE", "${table.tableComment}更新", "请求", "/ajax/${module.moduleName}/${table.getFName()}/update"));
        </#if>
        <#if table.find>
                forMgr.add(createRes("WEB_${table.tableName}_FIND", "${table.tableComment}查询", "请求", "/ajax/${module.moduleName}/${table.getFName()}/find"));
        </#if>
        <#if table.get>
                forMgr.add(createRes("WEB_${table.tableName}_GET", "${table.tableComment}获取", "请求", "/ajax/${module.moduleName}/${table.getFName()}/get"));
        </#if>
        <#if table.search>
                forMgr.add(createRes("WEB_${table.tableName}_SEARCH", "${table.tableComment}搜索", "请求", "/ajax/${module.moduleName}/${table.getFName()}/search"));
        </#if>

    </#list>
</#list>
            }

            {//初始化开发角色
                Long roleId = createRole("developer", "开发", "开发");
                for (Res res : forDev) {
                    allocateRes(roleId, "developer", res.getId(), res.getResCode());
                }
                for (Res res : forMgr) {
                    allocateRes(roleId, "developer", res.getId(), res.getResCode());
                }
            }
            {//初始化管理角色
                Long roleId = createRole("management", "管理员", "管理员");
                for (Res res : forMgr) {
                    allocateRes(roleId, "management", res.getId(), res.getResCode());
                }
            }
        }
        //endregion
    }

    private void createDict(String name, String comment, String[][] items) {
        DictCreateRequest dictCreateRequest = new DictCreateRequest();
        dictCreateRequest.setDictName(name);
        dictCreateRequest.setDictComment(comment);
        dictCreateRequest.setVersion(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        dictCreateRequest.setValid(true);
        DictCreateResponse dictCreateResponse = dictManager.create(dictCreateRequest, token);
        printError(dictCreateResponse);
        assertTrue(!dictCreateResponse.hasError());

        for (int i = 0; i < items.length; i++) {
            String[] item = items[i];
            DictItemCreateRequest dictItemCreateRequest = new DictItemCreateRequest();
            dictItemCreateRequest.setDictName(name);
            dictItemCreateRequest.setKey(item[0]);
            dictItemCreateRequest.setValue(item[1]);
            dictItemCreateRequest.setSort(i);
            dictItemCreateRequest.setValid(true);
            DictItemCreateResponse dictItemCreateResponse = dictItemManager.create(dictItemCreateRequest, token);
            printError(dictItemCreateResponse);
            assertTrue(!dictItemCreateResponse.hasError());
        }
    }

    private Res createRes(String code, String name, String resType, String value) {
        ResCreateRequest resCreateRequest = new ResCreateRequest();
        resCreateRequest.setResName(name);
        resCreateRequest.setResCode(code);
        resCreateRequest.setResType(resType);
        resCreateRequest.setResValue(value);
        resCreateRequest.setValid(true);
        ResCreateResponse resCreateResponse = resManager.create(resCreateRequest, token);
        printError(resCreateResponse);
        if (resCreateResponse.hasError() && resCreateResponse.getErrors().get(0).getMessage().equals(Message.INSERT_DUPLICATE)) {
            ResFindRequest resFindRequest = new ResFindRequest();
            resFindRequest.setResCode(code);
            ResFindResponse resFindResponse = resManager.find(resFindRequest, token);
            return resFindResponse.getResult().get(0);
        } else if (resCreateResponse.hasError()) {
            assertTrue(!resCreateResponse.hasError());
            return null;
        } else {
            Res res = new Res();
            res.setResCode(code);
            res.setResName(name);
            res.setResType(resType);
            res.setId(resCreateResponse.getId());
            return res;
        }
    }

    private Long createRole(String roleCode, String roleName, String roleComment) {
        RoleCreateRequest roleCreateRequest = new RoleCreateRequest();
        roleCreateRequest.setCode(roleCode);
        roleCreateRequest.setName(roleName);
        roleCreateRequest.setComment(roleComment);
        RoleCreateResponse roleCreateResponse = roleManager.create(roleCreateRequest, token);
        printError(roleCreateResponse);
        assertTrue(!roleCreateResponse.hasError());
        return roleCreateResponse.getId();
    }

    private void allocateRes(Long roleId, String roleCode, Long resId, String resCode) {
        RoleResCheckRequest roleResCheckRequest = new RoleResCheckRequest();
        roleResCheckRequest.setRoleId(roleId);
        roleResCheckRequest.setRoleCode(roleCode);
        roleResCheckRequest.setResId(resId);
        roleResCheckRequest.setResCode(resCode);
        roleResCheckRequest.setChecked(true);

        RoleResCheckResponse roleResCheckResponse = roleCreateRequest.check(roleResCheckRequest, token);
        printError(roleResCheckResponse);
        assertTrue(!roleResCheckResponse.hasError());
    }

    private void printError(BaseResponse response) {
        if (response.hasError()) {
            System.err.println("==========>" + MapperUtil.toJson(response));
        }
    }
}