package com.platform.controller;

import com.alibaba.fastjson.JSON;
import com.platform.annotation.SysLog;
import com.platform.entity.Result;
import com.platform.entity.SysDeptEntity;
import com.platform.entity.SysUserEntity;
import com.platform.service.SysDeptService;
import com.platform.service.impl.SysUserServiceImpl;
import com.platform.utils.*;
import com.platform.vos.SysDeptEntityVo;
import com.platform.vos.SysDeptVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 部门管理Controller
 *
 * @author liepngjun
 * @email 939961241@qq.com
 * @gitee https://gitee.com/fuyang_lipengjun/platform
 * @date 2017-09-17 23:58:47
 */
@Api(tags = "管理后台部门操作相关接口")
@RestController
@RequestMapping("/sys/dept")
@Slf4j
public class SysDeptController extends AbstractController {
    @Autowired
    private SysDeptService sysDeptService;

    @Autowired
    private SysUserServiceImpl sysUserService;

    @ApiOperation(value = "获取公司可新增员工的数量")
    @GetMapping("/getLessNum")
    @RequiresPermissions("sys:user:list")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "deptId", value = "部门ID", dataType = "long"),
    })
    public Result userBindList(@RequestParam(name = "deptId") long deptId) {
        Map<String , Object> mp = new HashMap<>();
        SysDeptEntity sysDeptEntity = sysDeptService.queryObject(deptId);
        if(null == sysDeptEntity){
            return  Result.failure("公司不存在");
        }
        long curStaffNum = sysUserService.getUserNumOfDept(deptId);
        long maxStaffNum = null !=  sysDeptEntity.getStaffNum() ? sysDeptEntity.getStaffNum() : 0;
        long less = maxStaffNum - curStaffNum;
        mp.put("less" , less);
        return Result.success(mp);
    }


    /**
     * 部门列表
     *
     * @return R
     */
    @RequestMapping("/list")
    @RequiresPermissions("sys:dept:list")
    public Result list(@RequestParam(name = "name") String name) {
        List<SysDeptEntity> deptList;
        if(StringUtils.isBlank(name)){
            Map<String, Object> map = new HashMap<>();
            //如果不是超级管理员，则只能查询本部门及子部门数据
            if (getUserId() != Constant.SUPER_ADMIN) {
                map.put("deptFilter", sysDeptService.getSubDeptIdList(getDeptId()));
            }
            if(map.containsKey("sidx")){
                map.remove("sidx");
            }
            deptList = sysDeptService.queryList(map);
        }else{
            //如果不是超级管理员，则只能查询本部门及子部门数据
            if (getUserId() != Constant.SUPER_ADMIN) {
                deptList = sysDeptService.queryListByName(name , getAllSubDeptIds(getDeptId()));
            }else{
                deptList = sysDeptService.queryListByName(name , null);
            }
        }
        // 获取管理员手机号
        if(ObjectUtils.isEmpty(deptList)) {
            return Result.success( deptList);
        }
        Map<Long, SysDeptEntity> entityMap = deptList.stream()
                .collect(Collectors.toMap(SysDeptEntity::getDeptId, deptEntity -> deptEntity));
        Map<String,Object> params = new HashMap<>();
        params.put("deptIdList",entityMap.keySet());
        List<SysUserEntity> users = sysUserService.queryList(params);
        users.parallelStream().filter(user -> !ObjectUtils.isEmpty(user.getRoleId()))
                .filter(user -> user.getRoleId() == 6 && entityMap.containsKey(user.getDeptId()))
                .forEach(user -> {
                    SysDeptEntity deptEntity = entityMap.get(user.getDeptId());
                    String mobile = user.getMobile();
                    if (ObjectUtils.isEmpty(deptEntity.getManagerPhoneNum())) {
                        deptEntity.setManagerPhoneNum(mobile);
                    } else {
                        deptEntity.setManagerPhoneNum(deptEntity.getManagerPhoneNum().concat(";").concat(mobile));
                    }
                });
        return Result.success(deptList);
    }
    @ApiOperation(value = "拉取所有部门列表，具有树状结构")
    @PostMapping("/anonList")
    public Result anonList() {
        Map<String, Object> map = new HashMap<>();
        //从总部开始去获取所有的子部门
        map.put("deptFilter", sysDeptService.getSubDeptIdList(1L));
        List<SysDeptEntity> deptList = sysDeptService.queryList(map);
        return Result.success(deptList);
    }

    /**
     * 选择部门(添加、修改菜单)
     *
     * @return R
     */
    @RequestMapping("/select")
    @RequiresPermissions("sys:dept:select")
    public Result select() {
        Map<String, Object> map = new HashMap<>();
        //如果不是超级管理员，则只能查询本部门及子部门数据
        if (getUserId() != Constant.SUPER_ADMIN) {
            map.put("deptFilter", sysDeptService.getSubDeptIdList(getDeptId()));
        }
        List<SysDeptEntity> deptList = sysDeptService.queryList(map);

        //添加一级部门
        if (getUserId() == Constant.SUPER_ADMIN) {
            SysDeptEntity root = new SysDeptEntity();
            root.setDeptId(0L);
            root.setName("一级部门");
            root.setParentId(-1L);
            root.setOpen(true);
            deptList.add(root);
        }

        return Result.success( deptList);
    }

    /**
     * 获取用户部门Id(管理员则为0)
     *
     * @return
     */
    @RequestMapping("/info")
    @RequiresPermissions("sys:dept:list")
    public Result info() {
        long deptId = 0;
        if (getUserId() != Constant.SUPER_ADMIN) {
            SysDeptEntity dept = sysDeptService.queryObject(getDeptId());
            deptId = dept.getParentId();
        }

        return Result.success(deptId);
    }

    /**
     * 根据主键获取部门信息
     *
     * @param deptId 主键
     * @return R
     */
    @RequestMapping("/info/{deptId}")
    @RequiresPermissions("sys:dept:info")
    public Result info(@PathVariable("deptId") Long deptId) {
        SysDeptEntity dept = sysDeptService.queryObject(deptId);

        return Result.success( dept);
    }

    /**
     * 新增部门
     *
     * @param dept 部门
     * @return R
     */
    @ApiOperation(value = "新增部门")
    @SysLog("新增部门")
    @PostMapping("/save")
    @RequiresPermissions("sys:dept:save")
    public Result save(@RequestBody SysDeptEntityVo dept) {
        try {
            if(ObjectUtils.isEmpty(dept.getManagerPhoneNum())){
                return Result.failure("手机号为空，请输入公司管理员手机号！");
            }
            SysUserEntity manager = sysUserService.queryByUserMobile(dept.getManagerPhoneNum());
            if(!ObjectUtils.isEmpty(manager) && manager.getDeptId() != -1L){
                return Result.failure("操作失败，当前账号已被绑定");
            }
            if (ObjectUtils.isEmpty(dept.getParentId())) {
                dept.setParentId(1L);
            }else{
                Integer count = 0;
                int parentLevel = countParentDeptLevel(dept.getParentId(), count);
                log.info("当前部门的父类部门深度为:{}", parentLevel);
                if (parentLevel > 4) {
                    return Result.failure("部门层级已经达到5层了，无法再创建子部门");
                }
            }
            if (ObjectUtils.isEmpty(dept.getDeptId())) {
                dept.setCurStaffNum(1);
            } else {
                SysDeptEntity deptEntity = sysDeptService.queryObject(dept.getDeptId());
                if (ObjectUtils.isEmpty(deptEntity.getCurStaffNum())) {
                    deptEntity.setCurStaffNum(0);
                }
                deptEntity.setCurStaffNum(deptEntity.getCurStaffNum() + 1);
            }
            sysDeptService.save(dept);
            //需要更新公司管理员的部门id
            manager.setDeptId(dept.getDeptId());
            manager.setRoleIdList(Arrays.asList(6L));
            sysUserService.update(manager);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.failure(e.getMessage());
        }
        return Result.success();
    }

    @SysLog("计算当前部门的深度")
    @ApiOperation(value = "计算当前部门的深度")
    @GetMapping("/countDeptLevel")
    @RequiresPermissions("sys:dept:save")
    public Result countDeptLevel(Long deptId) {
        if(null == deptId){
            return Result.failure("部门Id缺失");
        }
        int count = 0;
        Map<String , Object> result  = new HashMap<>();
        result.put("num" , countParentDeptLevel(deptId , count));
        return  Result.success(result);

    }

    public int countParentDeptLevel(long parentId , Integer count){

        SysDeptEntity sysDeptEntity = sysDeptService.queryObject(parentId);
        if(null == sysDeptEntity){
            return 0;
        }
        if(count > 10){
            log.warn("递归嵌套超过了10，保护资源，停止递归");
            return 0;
        }
        count += 1;
        if(null != sysDeptEntity.getParentId()){
           return  1 + countParentDeptLevel(sysDeptEntity.getParentId() , count);
        }

        return 1;
    }


    @SysLog("校验父部门的管理员的短信验证码")
    @PostMapping("/validParentAdmin")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    public Result validParentAdmin(@RequestBody SysDeptVo sysDeptVo) {
        if(null == sysDeptVo){
            return Result.failure("缺失参数");
        }
        if(null == sysDeptVo.getParentId()){
            return Result.failure("缺失父部门的id");
        }

        if(StringUtils.isBlank(sysDeptVo.getParentAdminPhoneNum())){
            return Result.failure("缺失父部门管理员的手机号");
        }

        if(StringUtils.isBlank(sysDeptVo.getParentSmsCode())){
            return Result.failure("缺失父部门管理员的短信验证码");
        }
        SysUserEntity parentAdmin = sysUserService.queryByMobileAndDeptId(sysDeptVo.getParentAdminPhoneNum() , sysDeptVo.getParentId());
        if(null == parentAdmin){
            return Result.failure("父部门的管理员信息不正确");
        }

        //校验管理员的短信验证码
        String parentSmsCode = (String) LettuceRedisClientUtils.getValueByKey("login_sms_code:" + sysDeptVo.getParentAdminPhoneNum() + sysDeptVo.getParentSmsCode());
        logger.info("上级部门管理员的上送验证码为:{},缓存中的为:{}" , sysDeptVo.getParentSmsCode() , parentSmsCode);
        if(StringUtils.isBlank(parentSmsCode)){
            return Result.failure("上级部门管理员的验证码过期或者不正确");
        }
        return Result.success();

    }


    @SysLog("新增部门同时更新管理员数据")
    @PostMapping("/createDept")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    public Result saveDept(@RequestBody SysDeptVo sysDeptVo) {

        if(null == sysDeptVo){
            return Result.failure("缺失参数");
        }

        if(StringUtils.isBlank(sysDeptVo.getSmsCode()) || StringUtils.isBlank(sysDeptVo.getAdminPhoneNum())){
            return Result.failure("管理员的手机号或者验证码缺失");
        }
        //校验当前管理员的手机验证码
        String smsCode = (String) LettuceRedisClientUtils.getValueByKey("login_sms_code:" + sysDeptVo.getAdminPhoneNum() + sysDeptVo.getSmsCode());
        logger.info("上级部门管理员的上送验证码为:{},缓存中的为:{}" , sysDeptVo.getSmsCode() , smsCode);
        if(StringUtils.isBlank(smsCode)){
            return Result.failure("管理员的短信验证码过期或者无效");
        }

        SysUserEntity userEntity = getUser();
        if(null == userEntity){
            return Result.failure("用户未登录");
        }
        if(null != userEntity.getDeptId()){
            return Result.failure("一个用户只能归属一个部门");
        }

        //新增部门数据
        SysDeptEntity sysDeptEntity = new SysDeptEntity();
        sysDeptEntity.setName(sysDeptVo.getDeptName());
        if(null == sysDeptVo.getParentId()){
            //不传，默认认为是新建，新建的，统一设置为1l总部
            sysDeptEntity.setParentId(1L);
        }else{
            sysDeptEntity.setParentId(sysDeptVo.getParentId());
        }

        //TODO:事务管控
        sysDeptService.save(sysDeptEntity);

        log.info("新增的部门id={}" , sysDeptEntity.getDeptId());

        //更新部门数据到管理员
        SysUserEntity admin = sysUserService.queryByUserMobile(sysDeptVo.getAdminPhoneNum());
        if(null == admin){
            log.warn("管理员用户:{}不存在" , sysDeptVo.getAdminPhoneNum());
        }else{
            admin.setDeptId(sysDeptEntity.getDeptId());
            sysUserService.updateUserAndAddDeptAdminRolls(admin);
        }
        return Result.success();
    }


    /**
     * 修改部门
     *
     * @param dept 部门
     * @return R
     */
    @SysLog("修改部门")
    @RequestMapping("/update")
    @RequiresPermissions("sys:dept:update")
    public Result update(@RequestBody SysDeptEntityVo dept) {
        sysDeptService.update(dept);

        return Result.success();
    }

    /**
     * 删除部门
     *
     * @param deptId 主键
     * @return R
     */
    @SysLog("删除部门")
    @RequestMapping("/delete")
    @RequiresPermissions("sys:dept:delete")
    public Result delete(long deptId) {
        //判断是否有子部门
        List<Long> deptList = getAllSubDeptIds(deptId);
        if (deptList.size() > 1) {
            return Result.failure("请先删除子部门");
        }
        // 判断 该部门(子部门)下有没有账号
        List<SysUserEntity> users = sysUserService.getSysUserListByDeptIds(deptList);
        if(!CollectionUtils.isEmpty(users)){
            return Result.failure("删除失败，请先将公司以及下级公司所绑定的账号都解绑后，再进行删除!");
        }
        sysDeptService.delete(deptId);
        return Result.success();
    }

    public List<Long> getAllSubDeptIds(Long deptId) {
        if (null == deptId) {
            log.info("部门ID为空");
            return new ArrayList<>();
        }
        List<Long> allDeptIdList = new ArrayList<>();
        int leve = 0;
        leve = findDeptIdByParent(deptId, 0, allDeptIdList);
        log.info("获取到当前部门以及所有子部门(10层嵌套以内)的id为:{}，部门层级为:{}",
                JSON.toJSONString(allDeptIdList) , leve);
        return allDeptIdList;
    }

    private int findDeptIdByParent(long deptId, int level, List<Long> deptIdList) {

        if (level > 10) {
            log.info("嵌套层数超过了10层");
            return level;
        }
        deptIdList.add(deptId);
        //获取所有子部门的id
        List<Long> subDeptIdList = sysDeptService.queryDetpIdList(deptId);
        if (CollectionUtils.isEmpty(subDeptIdList)) {
            //自己算一层，没有子部门，要先加上自己这一层
            return level + 1;
        }
        int maxLevel = 0;
        for(Long id : subDeptIdList){
            //遍历所有子部门的子部门，并记下子部门中嵌套最深的层数
            int tmpLevel = findDeptIdByParent(id, level, deptIdList);
            if(tmpLevel > maxLevel){
                maxLevel = tmpLevel;
            }
        }
        //添加子部门的id
        deptIdList.addAll(subDeptIdList);
        //叠加子部门的最大层级
        level += maxLevel;
        //加上自己这一层
        level += 1;
        return level;
    }

}
