package cn.api.system;

import cn.facade.abs.IService;
import cn.common.annotation.Log;
import cn.common.enums.BizOpType;
import cn.common.enums.ResultCode;
import cn.common.page.response.Result;
import cn.constant.HttpConst;
import cn.constant.CommonConst;
import cn.pojo.entity.TSysDept;
import cn.pojo.entity.TSysMenu;
import cn.pojo.vo.TreeSelectVo;
import cn.service.system.IDeptService;
import cn.service.system.IMenuService;
import cn.util.core.IsKit;
import cn.util.core.TypeKit;
import cn.util.string.StringKit;
import java.util.*;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/** 树形结构*/
@RestController
@RequestMapping("/api/tree")
public class TreeCtrl extends IService
{
	/***如下代码为菜单特有代码**/
	@Resource
	private IMenuService menuService;

	/**删除菜单。限定：一次只能删除一条菜单记录*/
	@DeleteMapping("/delMenu/{menuId}")
	@Log(title = "菜单管理-删除菜单-deleteMenu", businessType = BizOpType.DELETE)
	public Result<?> deleteMenu(@PathVariable("menuId") Long menuId) 
	{
		//是否存在子菜单节点
		if (menuService.hasChildByMenuId(menuId)) {
			return Result.warnMsg("存在子菜单,不允许删除");
		}
		//菜单是否已分配t_sys_role_menu 是否需要?
		if (menuService.checkMenuExistRole(menuId)) {
			return Result.warnMsg( "菜单已分配,不允许删除");
		}
		return menuService.deleteMenu(menuId)? Result.ok("删除成功")
				:Result.warnMsg(ResultCode.SQL_DELETE.getMsg());
	}
	
	/**新增菜单*/
	@PostMapping("/insertMenu")
	@Log(title = "菜单管理-新增菜单-insertMenu", businessType = BizOpType.INSERT)
	public Result<?> insertMenu( @RequestBody TSysMenu menu)
	{
		if (!menuService.checkMenuNameUnique(menu)){
			return Result.warnMsg("新增菜单'" + menu.getMetaTitle() + "'失败，菜单名称已存在");
		} 
		if (CommonConst.INT_NUM_0.equals(menu.getMetaIsFrame())
				&& !StringKit.startsWithAny(menu.getPath(),HttpConst.HTTP,HttpConst.HTTPS))
		{
			return Result.warnMsg( "新增菜单'" + menu.getMetaTitle() + "'失败，地址必须以http(s)://开头");
		}
		return Result.ok(daoService.save(menu));
	}

	/**修改菜单*/
	@PutMapping("/updateMenu")
	@Log(title = "菜单管理-修改菜单-updateMenu", businessType = BizOpType.UPDATE)
	public Result<?> updateMenu(@Validated @RequestBody TSysMenu menu)
	{
		//	如果修的不是菜单名？
		if (!menuService.checkMenuNameUnique(menu)){
			return Result.warnMsg("修改菜单'" + menu.getMetaTitle() + "'失败，菜单名称已存在");
		} 
		if (CommonConst.INT_NUM_0.equals(menu.getMetaIsFrame())
				&& !StringKit.startsWithAny(menu.getPath(),HttpConst.HTTP,HttpConst.HTTPS)){
			return Result.warnMsg( "修改菜单'" + menu.getMetaTitle() + "'失败，地址必须以http(s)://开头");
		} 
		if (menu.getMenuId().equals(menu.getParentId())) {
			return Result.warnMsg("修改菜单'" + menu.getMetaTitle() + "'失败，上级菜单不能选择自己");
		}
		return daoService.update(menu) > 0 ? 
				Result.ok(daoService.update(menu)) :Result.warnMsg(ResultCode.SQL_UPDATE.getMsg());
	}
	
	/**依据登录者的角色，获取菜单下拉树列表 全部 */
	@GetMapping("/getMenuTree/{roleId}")
	@Log(title = "菜单管理-获取全部菜单列表-getMenuTree", businessType = BizOpType.SELECT)
	public Result<?> getMenuTree(@PathVariable String roleId) 
	{
		//获取当前用户的菜单
		List<TSysMenu> menus = menuService.selectMenuList(roleId);
		//组装成页面el-tree所需的格式
		return Result.ok(menuService.buildMenuTreeSelect(menus));
	}
	/**获取满足查询条件的菜单.查询条件为TSysMenu中非空字段@RequestBody TSysMenu menu*/
	@GetMapping("/getMenuList/{roleId}")
	@Log(title = "菜单管理-加载对应角色菜单列表树-getMenuList", businessType = BizOpType.SELECT)
	public Result<?> getMenuList(@PathVariable("roleId") String roleId,
			@RequestParam Map<String,Object> whereMap) 
	{
		return Result.ok(menuService.selectMenuList(roleId,whereMap));
	}
	
	/**依据登录者的角色，获取已经选中的菜单列表项。主要用于页面设置：角色-菜单权限t_sys_role_menu*/
	@GetMapping(value = "/getCheckedMenuByRole/{roleId}")
	@Log(title = "菜单管理-加载对应角色菜单列表树-getCheckedMenuByRole", businessType = BizOpType.SELECT)
	public Result<?> getCheckedMenuByRole(@PathVariable("roleId") String roleId) 
	{
		Map<String, Object> data = new HashMap<>();
		//获取指定用户的菜单项 
		List<TSysMenu> menus = menuService.selectMenuList(roleId);
		//构建菜单
		data.put("menus", menuService.buildMenuTreeSelect(menus));
		//获取已选菜单项
		data.put("checkedKeys",menuService.selectMenuListByRoleId(roleId));
		return Result.ok(data);
	}
	/**依据登录者的角色，获取已经选中的菜单列表项。主要用于页面设置：角色-按钮操作 权限*/
	@GetMapping(value = "/getCheckedRoleMenu/{roleId}")
	@Log(title = "菜单管理-加载对应角色菜单列表树-getCheckedRoleMenu", businessType = BizOpType.SELECT)
	public Result<?> getCheckedRoleMenu(@PathVariable("roleId") String roleId) 
	{
		Map<String, Object> data = new HashMap<>();
		//获取指定用户的菜单项 
		List<TSysMenu> menus = menuService.selectMenuList4Perm(roleId);
		//构建菜单
		data.put("menus", menuService.buildMenuTreeSelect(menus));
		//获取已选菜单项 有问题？
		data.put("checkedKeys", menuService.selectRoleMenuListByRoleId(roleId));
		return Result.ok(data);
	}	
	
	/**依据登录者的角色，获取菜单下拉树列表 非隐藏的 */
	@GetMapping("/getPermMenuTree/{roleId}")
	@Log(title = "菜单管理-获取非隐藏菜单列表-getPermMenuTree", businessType = BizOpType.SELECT)
	public Result<?> getPermMenuTree(@PathVariable String roleId) 
	{
		//获取当前用户的菜单
		List<TSysMenu> menus = menuService.selectPermMenuList(roleId);
		//组装成页面el-tree所需的格式
		return Result.ok(menuService.buildMenuTreeSelect(menus));
	}

	/**保留：根据菜单编号获取详细信息*/
	@GetMapping(value = "/getMenuById/{menuId}")
	@Log(title = "菜单管理-根据菜单编号获取详细信息-getMenuInfoById", businessType = BizOpType.SELECT)
	public Result<?> getMenuById(@PathVariable Long menuId) {
		return Result.ok(menuService.getMenuById(menuId));
	}

	/**
	 * 获取路由信息（页面左边的菜单树），即菜单跳转 
	 * @return 路由信息
	 */
	@GetMapping("/getRouters/{roleId}")
	@Log(title = "菜单管理-获取路由信息-getRouters", businessType = BizOpType.SELECT)
	public Result<?> getRouters(@PathVariable String roleId)
	{ 	 
		List<TSysMenu> resultList = menuService.selectMenuTreeByRoleId(roleId);
		if(IsKit.isNullOrEmpty(resultList)) {
			return Result.warnMsg(ResultCode.SQL_RUN.getMsg());
		}
		else {
			return Result.ok(menuService.buildMenus(resultList));
		}
	}

	//************************************************************************************//
	//************************************************************************************//

	@Resource
	private IDeptService deptService;
	private final String deptTable = "t_sys_dept";

	/** 获取部门下拉树列表**/
	@GetMapping("/getDeptTree/{roleId}")
	@Log(title = "部门管理-获取部门下拉树列表-getDeptTree", businessType = BizOpType.SELECT)
	public Result<?> getDeptTree(@PathVariable String roleId) 
	{
		return Result.ok(deptService.buildDeptTreeSelect(roleId));
	} 

	/**获取全部部门列表：页面传来的参数有deptName和status两项
	 * 页面组装满足属性结构要求的数据结构*/
	@GetMapping("/getDeptList")
	@Log(title = "部门管理-获取部门列表-getDeptList", businessType = BizOpType.SELECT)
	public Result<?> getDeptList(@RequestParam Map<String,Object> paramMap)
	{	
		//2代表删除 排除已删除记录
		paramMap.put("delFlag","!1");
		List<?> resultList = daoService.getEntityList(deptTable,paramMap,TSysDept.class);
		return Result.ok(resultList);
	}
	/**删除给定部门编码的部门记录*/
	@DeleteMapping("/delDept/{deptId}")
	@Log(title = "部门管理-删除部门-delDeptNode", businessType = BizOpType.DELETE)
	public Result<?> delDeptNode(@PathVariable Integer deptId) 
	{	
		//查询拟删除部门是否存在子节点(下属部门)：存在 > 0
		Map<String,Object> paramMap = new HashMap<>();
		paramMap.put("delFlag","!1");
		paramMap.put("parentId",deptId);
		if (daoService.ifExistRecord(deptTable,paramMap)) {
			return Result.warnMsg("存在下级部门,不允许删除");
		}

		//查询拟删除部门是否存在用户
		paramMap = new HashMap<>();
		paramMap.put("delFlag","!1");
		paramMap.put("deptId",deptId);		
		if (daoService.ifExistRecord("t_sys_user",paramMap)) {
			return Result.warnMsg( "部门存在用户,不允许删除");
		}

		//删除满足条件的部门。即做删除标记即del_flag = '1' status=1
		paramMap = new HashMap<>();
		paramMap.put("deptId=?",deptId);
		Map<String,Object> updateMap = new HashMap<>();
		updateMap.put("delFlag","1");
		updateMap.put("status","1");
		Boolean opFlag = daoService.updateFieldByBean(TSysDept.class,updateMap,paramMap);
		return Result.ok(opFlag);	
	}
	/** 新增部门*/
	@PostMapping("/insertDept")
	@Log(title = "部门管理-新增部门-insertDept", businessType = BizOpType.INSERT)
	public Result<?> insertDept(@Validated @RequestBody TSysDept entity)
	{
		//校验部门名称是否唯一. 唯一返回truenew String[] {"deptName","deptId","parentId"}
		if (!daoService.isUnique(entity, "deptName","deptId","parentId")){
			return Result.warnMsg( "新增部门'" + entity.getDeptName() + "'失败，部门名称已存在");
		}
		Boolean opFlag = deptService.insertDept(entity);
		return Result.ok(opFlag);	
	}

	/** 修改部门 */
	@PutMapping("/updateDept")
	@Log(title = "部门管理-修改部门-updateDept", businessType = BizOpType.UPDATE)
	public Result<?> updateDept(@Validated @RequestBody TSysDept entity) 
	{
		//校验部门名称是否唯一. 唯一返回true new String[] {"deptName","deptId","parentId"}
		if (!daoService.isUnique(entity, "deptName","deptId","parentId")){
			return Result.warnMsg("修改部门'" + entity.getDeptName() + "'失败，部门名称已存在");
		}


		//部门编号与父部门编号是不是相等
		if (entity.getParentId().equals(entity.getDeptId())){
			return Result.warnMsg("修改部门'" + entity.getDeptName() + "'失败，上级部门不能是自己");
		}
		//部门停用状态 
		if (StringKit.isEquals(CommonConst.CHAR_NUM_1, entity.getStatus())){
			Map<String,Object> paramMap = new HashMap<>();
			paramMap.put("delFlag","!1");
			paramMap.put("status",0);//0正常
			paramMap.put("find_in_set","FUN('"+entity.getDeptId()+"','"+ entity.getAncestors()+"')");
			//根据ID查询所有子部门（正常状态）,返回子部门数
			if(daoService.ifExistRecord(deptTable,paramMap)){
				return Result.warnMsg( "该部门包含未停用的子部门！");
			}
		}	
		//修改保存部门信息
		Boolean opFlag = deptService.updateDept(entity);
		return Result.ok(opFlag);	
	}
	
	/** 备用未调试：根据部门编号获取详细信息*/
	@GetMapping(value = "/getDeptById/{deptId}")
	@Log(title = "部门管理-根据部门编号获取详细信息-getDeptById", businessType = BizOpType.SELECT)
	public Result<?> getDeptById(@PathVariable Long deptId) 
	{
		return Result.ok(deptService.getDeptById(deptId));
	}
	
	/**备用未调试： 加载对应角色部门列表树*/
	@GetMapping(value = "/getDeptTreeByRole/{roleId}")
	@Log(title = "部门管理-根据角色获取部门信息-getDeptTreeByRole", businessType = BizOpType.SELECT)
	public Result<?> getDeptTreeByRole(@PathVariable("roleId") String roleId) 
	{
		List<TSysDept> depts = deptService.getDeptListByRole(roleId);

		Map<String, Object> data = new HashMap<>();
		//new BigInteger(roleId.toString())
		List<TSysDept> checkedKeys = deptService.selectDeptListByRoleId(TypeKit.objToInt(data));
		data.put("checkedKeys", checkedKeys);
		List<TreeSelectVo> dept = deptService.buildDeptTreeSelect(depts);
		data.put("depts",dept);
		return Result.ok(data);
	}
	/**备用未调试：查询部门列表（排除节点）*/
	@GetMapping("/getDeptList/exclude/{deptId}")
	@Log(title = "部门管理-查询部门列表（排除节点）-getDeptListExcludeChild", businessType = BizOpType.SELECT)
	public Result<?> getDeptListExcludeChild(@PathVariable(value = "deptId") Integer deptId)
	{
		List<TSysDept> depts = deptService.selectDeptListByRoleId(deptId);
		depts.removeIf(d -> Objects.equals(d.getDeptId(),deptId) ||
				ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
		return Result.ok(depts);
	}
}
