package io.gisbi.application.system.service.impl;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.gisbi.application.system.domain.Menu;
import io.gisbi.application.system.mapper.MenuMapper;
import io.gisbi.application.system.mapper.RoleMapper;
import io.gisbi.application.system.service.IMenuService;
import io.gisbi.utils.AuthUtils;
import io.micrometer.common.util.StringUtils;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 菜单及按钮 服务实现类
 * </p>
 *
 * @author lilin
 * @since 2025-05-08
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

    @Resource
    private MenuMapper menuMapper;

    @Resource
    private RoleMapper roleMapper;

    @Override
    public List<Map<String, Object>> getMenuTree(String appId, String name, String isdisplay) {
        List<Map<String, Object>> listMap = null;
        //不带名称查询，返回树结构
        if (StringUtils.isEmpty(name)) {
            QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("parentid", "0").eq("app_id", appId).orderByAsc("orderno");
            listMap = this.listMaps(queryWrapper);

            for (int i = 0; i < listMap.size(); i++) {
                //查询下一子集
                List<Map<String, Object>> childList = child(listMap.get(i).get(
                        "id").toString(), appId, name, null, null);
                listMap.get(i).put("children", childList);   //添加新列 子集
            }
        } else {  //根据菜单名称查询，直接返回类别
            QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
            queryWrapper.like("name", name).eq("app_id", appId).orderByAsc("name");
            listMap = this.listMaps(queryWrapper);
        }
        return listMap;
    }

    /***********************************
     * 用途说明：新增菜单及按钮
     * 参数说明
     * sysMenu        菜单或按钮表对象
     * 返回值说明:   是否添加成功提示
     ***********************************/
    @Override
    public boolean addMenu(Menu menu) {
        String parentId = menu.getParentid();
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        //根据上级id 查询到总数 并累加
        int orderno = (int) (this.count(queryWrapper.eq("parentid", parentId)) + 1);
        // 生成排序号
        // 生成编号
        QueryWrapper<Menu> queryMaxCode = new QueryWrapper<>();
        queryMaxCode.eq("parentid", parentId);
        // 查询最大的编号
        List<Object> maxList = this.listObjs(queryMaxCode.select("max(code) " +
                "code").eq("app_id", menu.getAppId()));
        Menu parentMenu = menuMapper.selectById(parentId);
        // 最大编号转换成int类型
        String maxCode = maxList.isEmpty() ? "0" : (maxList.get(0) != null ? maxList.get(0).toString() : "0");
        int max = ObjectUtil.isEmpty(maxList) ? 0 : Integer.parseInt(maxCode);
        DecimalFormat df;
        if ("0".equals(menu.getParentid())) {
            df = new DecimalFormat("00");
        } else if (parentMenu.getCode().length() == 2) {
            df = new DecimalFormat("0000");
        } else {
            df = new DecimalFormat("000000");
        }
        //DecimalFormat df = new DecimalFormat("00");
        //int parentCode = Integer.parseInt(parentMenu.getCode());
        String parentCode = "";
        if (parentMenu != null) {
            parentCode = parentMenu.getCode();
        }
        // 生成的新编号 年月日+4位编号
        String code;
        if (max > 0) {
            code = df.format(max + 1);
        } else {
            max = max + 1;
            if (StringUtils.isBlank(parentCode)) {
                parentCode = "0" + max;
            } else {
                int i = Integer.parseInt(parentCode);
                parentCode = i + "0" + max;
            }

            int format = Integer.parseInt(parentCode);
            code = df.format(format);
        }

        // 判断是否显示字段 是否填写 为空
        if (StringUtils.isEmpty(menu.getIsdisplay())) {
            // 默认设置成 1 显示
            menu.setIsdisplay("1");
        }
        // 判断是否填写父级id 为空 默认设置成 0
        if (StringUtils.isEmpty(menu.getParentid())) {
            menu.setParentid("0");
        }
        // 添加编号
        menu.setCode(code);
        // 添加排序号
        menu.setOrderno(orderno);
        //填写 当前用户名称
        menu.setLastmodifier(AuthUtils.getUser().getUserId().toString());
        //填写 当前日期
        menu.setLastmodifydate(LocalDateTime.now());
        return this.save(menu);
    }

    /***********************************
     * 用途说明：根据id删除菜单或按钮
     * 参数说明
     * id        删除列的id
     * 返回值说明:   是否删除成功
     ***********************************/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteMenuById(String id) {
        //根据id查询
        Menu menu = this.getById(id);

        // 根据id删除主菜单
        boolean isOk = this.removeById(id);
        if (!isOk) {
            return false;
        }
        // 通过ID 删除角色菜单关联信息
        roleMapper.deleteRoleMenusByMenuId(id);

        //1 创建list集合，用于封装所有删除目录或菜单id值  如果下面有子项 都删除
        List<String> idList = new ArrayList<>();
        this.selectPermissionChildById(id, idList);

        if (!idList.isEmpty()) {
            menuMapper.deleteBatchIds(idList);
            //通过ID集合 删除角色菜单关联信息
            for (String menuId : idList) {
                roleMapper.deleteRoleMenusByMenuId(menuId);
            }
        }
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        //根据上级id 查询 根据 orderno 正序排序
        queryWrapper.eq("parentid", menu.getParentid()).orderByAsc(
                "orderno");
        List<Menu> list = this.list(queryWrapper);
        for (int i = 0; i < list.size(); i++) {
            Menu menuData = list.get(i);
            //更新序列号
            menuData.setOrderno(i + 1);
        }
        //更新表数据
        this.updateBatchById(list);

        return isOk;
    }

    /***********************************
     * 用途说明：获取分配权限
     * 参数说明
     *  appId      系统id
     *  roleId     角色ID
     * 返回值说明:  菜单结构树集合
     ***********************************/
    @Override
    public List<Map<String, Object>> permissionAssignment(String appId ,String roleId) {


        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Menu::getAppId, appId).select(Menu::getId,Menu::getAppId,Menu::getType,Menu::getCode,
                Menu::getParentid, Menu::getName).orderByAsc
                (Menu::getOrderno);
        List<Map<String, Object>> listAll =
                menuMapper.selectMaps(queryWrapper);
        List<String> listRole =
                menuMapper.selectMenuByRoleId(appId,roleId);
        for (Map<String, Object> map : listAll) {
            String id = (String) map.get("id");
            if (listRole.contains(id)) {
                map.put("checkinfo", true);
            } else {
                map.put("checkinfo", false);
            }

        }
        List<Map<String, Object>> listTree = buildTrees(listAll);
        return listTree;
    }

    @Override
    public boolean changeOrder(String menuId, String direction) {
        Menu currentMenu = menuMapper.selectById(menuId);
        if (currentMenu == null) {
            return false;
        }

        String parentId = currentMenu.getParentid();

        QueryWrapper<Menu> wrapper = new QueryWrapper<>();
        wrapper.eq("parentid", parentId);
        wrapper.orderByAsc("orderno");

        List<Menu> siblings = menuMapper.selectList(wrapper);

        int index = -1;
        for (int i = 0; i < siblings.size(); i++) {
            if (siblings.get(i).getId().equals(menuId)) {
                index = i;
                break;
            }
        }

        if ("up".equals(direction)) {
            if (index > 0) {
                swapOrder(siblings.get(index), siblings.get(index - 1));
            } else {
                return false; // 已是第一个，无法上移
            }
        } else if ("down".equals(direction)) {
            if (index < siblings.size() - 1) {
                swapOrder(siblings.get(index), siblings.get(index + 1));
            } else {
                return false; // 已是最后一个，无法下移
            }
        } else {
            return false; // 方向错误
        }
        return true;
    }

    @Override
    public boolean moveMenu(String menuId, String targetParentId) {
        Menu menu = menuMapper.selectById(menuId);
        if (menu == null) {
            return false;
        }
        // 更新父级ID
        menu.setParentid(targetParentId);

        // 获取新父级下的最大序号
        QueryWrapper<Menu> wrapper = new QueryWrapper<>();
        wrapper.eq("parentid", targetParentId);
        wrapper.select("orderno","code");
        wrapper.orderByDesc("orderno");
        List<Menu> list = menuMapper.selectList(wrapper);
        if (list.isEmpty()) {
            return false;
        }
        Integer maxOrderNo = list.getFirst().getOrderno();
        // 设置新的序号为最大值+1
        menu.setOrderno(maxOrderNo == null ? 1 : maxOrderNo + 1);
        // 设置移动过后的菜单code


        // 更新菜单信息
        return menuMapper.updateById(menu) > 0;
    }



    private void swapOrder(Menu m1, Menu m2) {
        Integer temp = m1.getOrderno();
        m1.setOrderno(m2.getOrderno());
        m2.setOrderno(temp);

        menuMapper.updateById(m1);
        menuMapper.updateById(m2);
    }

    /**********************************
     * 用途说明: 生成权菜单权限树
     * 参数说明 sysMenus
     * 返回值说明: java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
     ***********************************/
    public List<Map<String, Object>> buildTrees(List<Map<String, Object>> Menus) {
        List<Map<String, Object>> resultMenuList = new ArrayList<>();
        for (Map<String, Object> sysMenu : Menus) {
            if ("0".equals(sysMenu.get("parentid"))) {
                resultMenuList.add(sysMenu);
            }
        }
        for (Map<String, Object> sysMenu : resultMenuList) {
            List<Map<String, Object>> menus = iterateMenus(Menus,
                    (String) sysMenu.get("id"));
            for (Map<String, Object> menu : menus) {
                if (!(boolean) menu.get("checkinfo")) {
                    sysMenu.put("checkinfo", false);
                    break;
                }
            }
            sysMenu.put("children", menus);
        }
        return resultMenuList;
    }

    /**
     * 多级菜单查询方法
     *
     * @param menuVoList 不包含最高层次菜单的菜单集合
     * @param pid        父类id
     * @return
     */
    public List<Map<String, Object>> iterateMenus(List<Map<String, Object>> menuVoList, String pid) {
        List<Map<String, Object>> result = new ArrayList<>();
        for (Map<String, Object> menu : menuVoList) {
            //获取菜单的id
            String menuid = (String) menu.get("id");
            //获取菜单的父id
            String parentid = (String) menu.get("parentid");
            if (StrUtil.isNotBlank(parentid)) {
                if (parentid.equals(pid)) {
                    //递归查询当前子菜单的子菜单
                    List<Map<String, Object>> iterateMenu =
                            iterateMenus(menuVoList, menuid);
                    for (Map<String, Object> map : iterateMenu) {
                        boolean checkinfo = (boolean) map.get("checkinfo");
                        if (!checkinfo) {
                            menu.put("checkinfo", false);
                        }
                    }
                    menu.put("children", iterateMenu);
                    result.add(menu);
                }
            }
        }
        return result;
    }


    //2 根据当前菜单id，查询菜单里面子菜单id，封装到list集合
    private void selectPermissionChildById(String id, List<String> idList) {
        //查询菜单里面子菜单id
        QueryWrapper<Menu> wrapper = new QueryWrapper<>();
        wrapper.eq("parentid", id);
        wrapper.select("id");
        List<Menu> childIdList = baseMapper.selectList(wrapper);
        //把childIdList里面菜单id值获取出来，封装idList里面，做递归查询
        childIdList.stream().forEach(item -> {
            //封装idList里面
            idList.add(item.getId());
            //递归查询
            this.selectPermissionChildById(item.getId(), idList);
        });
    }


    /***********************************
     * 用途说明：查询菜单
     * 参数说明
     * parentid     上级id
     *systemcode    系统
     * isdisplay    是否显示
     * type         菜单类型
     * 返回值说明:  菜单结构树集合
     ***********************************/
    private List<Map<String, Object>> child(String parentid,
                                            String appId, String name,
                                            String isdisplay, String type) {
        List<Map<String, Object>> listMap = new ArrayList<>();
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parentid", parentid).eq("app_id", appId);
        //根据上级id 系统 查询
        if (StringUtils.isNotEmpty(type)) {
            queryWrapper.ne("type", type);
        }
        //根据菜单名称查询
        if (StringUtils.isNotEmpty(name)) {
            queryWrapper.like("name", name);
        }
        listMap = this.listMaps(queryWrapper.orderByAsc("orderno"));
        if (listMap.size() > 0) {              //判断是否存在子集
            for (int i = 0; i < listMap.size(); i++) {             //遍历表数据
                List<Map<String, Object>> childList =
                        child(listMap.get(i).get("id").toString(), appId
                                , name, isdisplay, type); //循环获取下一子集
                listMap.get(i).put("children", childList); //添加新列 子集
            }
        }
        return listMap;
    }


}
