package com.storlead.system.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.storlead.framework.common.result.Result;
import com.storlead.framework.common.util.PingyinUtil;
import com.storlead.framework.common.vo.menu.TreeVo;
import com.storlead.framework.util.LoginUserUtil;
import com.storlead.system.entity.UserWebH5MenuShowConfigEntity;
import com.storlead.system.pojo.dto.MenuParamDTO;
import com.storlead.system.pojo.entity.MenuEntity;
import com.storlead.system.pojo.vo.CustomMenuDTO;
import com.storlead.system.pojo.vo.RouterVo;
import com.storlead.system.pojo.vo.UserMenuVO;
import com.storlead.system.service.IMenuService;
import com.storlead.system.service.SysResourceMenuService;
import com.storlead.system.service.UserWebH5MenuShowConfigService;
import com.storlead.user.pojo.dto.MenuParam;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: sp-cloud
 * @description:
 * @author: chenkq
 * @create: 2022-05-20 10:37
 */
@Api(tags = "平台中心 - 系统: 菜单管理")
@Log4j2
@RestController
@RequestMapping("sys/menu")
public class MenuApiController {

    @Resource
    private IMenuService menuService;

    @Resource
    private UserWebH5MenuShowConfigService webH5MenuShowConfigService;

    @Resource
    private SysResourceMenuService resourceMenuService;

    public static Integer FIRST_CODE = 100;

    @ApiOperation("查询菜单Tree")
    @PostMapping("listTree")
    public Result listTree(@RequestBody(required = false) MenuParamDTO dto) {
        try {
            LambdaQueryWrapper<MenuEntity> queryWrapper = new LambdaQueryWrapper();
            queryWrapper.eq(MenuEntity::getIsDelete,0);
            queryWrapper.eq(MenuEntity::getEnabled,1);
            applyMenuScopeFilter(queryWrapper, dto);
            if (Objects.nonNull(dto.getAppId())) {
                queryWrapper.eq(MenuEntity::getAppId,dto.getAppId());
            }
            queryWrapper.orderByAsc(MenuEntity::getSort);
            List<MenuEntity> menus = menuService.list(queryWrapper);
            if(CollectionUtils.isEmpty(menus)) {
                return Result.result(Collections.EMPTY_LIST);
            }
            List<UserMenuVO> res = createTreeMenus(Long.valueOf(0), UserMenuVO.menuListToTargetMenuTreeVoList(menus));
            //res.stream().sorted(Comparator.comparing(UserMenuVO::getSort).reversed());
            return Result.result(res);
        }catch (Exception e) {
            e.printStackTrace();
            return Result.error("获取菜单信息错误:"+e.getMessage());
        }
    }

    @ApiOperation("查询菜单所有菜单")
    @PostMapping("listAllTree")
    public Result listAllTree(@RequestBody(required = false) MenuParamDTO dto) {
        try {
            LambdaQueryWrapper<MenuEntity> queryWrapper = new LambdaQueryWrapper();
            queryWrapper.eq(MenuEntity::getIsDelete,0);
            queryWrapper.eq(MenuEntity::getEnabled,1);
            if (Objects.nonNull(dto.getAppId())) {
                queryWrapper.eq(MenuEntity::getAppId,dto.getAppId());
            }
            queryWrapper.orderByAsc(MenuEntity::getSort);
            applyMenuScopeFilter(queryWrapper, dto);
            List<MenuEntity> menus = menuService.list(queryWrapper);
            List<RouterVo> routerVos = menuToRouter(menus);
            return Result.result(routerVos);
        }catch (Exception e) {
            e.printStackTrace();
            return Result.error("获取菜单信息错误:"+e.getMessage());
        }
    }

    private List<RouterVo> menuToRouter(List<MenuEntity> menus){
        List<RouterVo> routerVos = new ArrayList<>();
        for (MenuEntity menu : menus) {
            RouterVo routerVo = new RouterVo() ;
            routerVo.setMenuType(menu.getMenuType()+"");
            routerVo.setName(menu.getMenuName());
            routerVo.setParentId(menu.getPid());
            routerVo.setId(menu.getId());
            routerVos.add(routerVo);
        }
        return routerVos;
    }


    @ApiOperation("查询菜单Tree")
    @PostMapping("sort")
    public Result sort(Long [] ids) {
        if (ids == null || ids.length == 0) {
            return Result.error("参数错误");
        }
        Integer i = 0;
        for (Long id : ids) {
            LambdaUpdateWrapper<MenuEntity> update = new LambdaUpdateWrapper();
            update.eq(MenuEntity::getId,id);
            update.set(MenuEntity::getSort,i);
            menuService.update(update);
            i++;
        }

        return Result.ok();
    }

    /**
     * 资源树（权限配置等）：返回 {@link TreeVo}，type=20 表示菜单节点。
     * PC / H5 原各有一套接口，逻辑相同，已合并；旧路径 list_web_h5_res_tree 仍可用。
     */
    @ApiOperation("查询菜单资源树（PC/H5 共用）")
    @PostMapping(value = {"listResTree", "list_web_h5_res_tree"})
    public Result listResTree(@RequestBody(required = false) MenuParamDTO dto) {
        try {
            return Result.result(buildResTree(dto));
        } catch (Exception e) {
            log.error("listResTree error", e);
            return Result.error("获取菜单信息错误:" + e.getMessage());
        }
    }

    private List<TreeVo> buildResTree(MenuParamDTO dto) {
        LambdaQueryWrapper<MenuEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MenuEntity::getIsDelete, 0);
        queryWrapper.eq(MenuEntity::getEnabled, 1);
        if (Objects.nonNull(dto.getAppId())) {
            queryWrapper.eq(MenuEntity::getAppId,dto.getAppId());
        }
        queryWrapper.orderByAsc(MenuEntity::getSort);
        applyMenuScopeFilter(queryWrapper, dto);
        List<MenuEntity> menus = menuService.list(queryWrapper);
        if (CollectionUtils.isEmpty(menus)) {
            return Collections.emptyList();
        }
        List<TreeVo> menuResls = new ArrayList<>();
        for (MenuEntity res : menus) {
            TreeVo treeVo = new TreeVo();
            treeVo.setId(res.getId());
            treeVo.setMenuId(res.getId());
            treeVo.setParentId(res.getPid());
            treeVo.setTitle(res.getMenuName());
            treeVo.setType(20);
            treeVo.setArg(res);
            treeVo.setExpand(false);
            treeVo.setDisabled(false);
            treeVo.setDisableCheckbox(false);
            menuResls.add(treeVo);
        }
        return createResTrees(0L, menuResls);
    }


    @ApiOperation("查询菜单列表")
    @PostMapping("pagelist")
    public Result pagelist(@RequestBody MenuParam dto) {
        try {
            IPage<MenuEntity> page = new Page<>(dto.getPageIndex(), dto.getPageSize());
            LambdaQueryWrapper<MenuEntity> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(MenuEntity::getIsDelete, 0);
            if (dto.getServiceModeType() != null) {
                queryWrapper.eq(MenuEntity::getServiceModeType, dto.getServiceModeType());
            }
            applyAppIdFilter(queryWrapper, dto.getAppId());
            queryWrapper.orderByAsc(MenuEntity::getSort).orderByAsc(MenuEntity::getId);
            IPage<MenuEntity> menus = menuService.page(page, queryWrapper);
            return Result.result(menus);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("获取菜单信息错误:" + e.getMessage());
        }
    }

    @ApiOperation("菜单详情")
    @PostMapping("detail")
    public Result detail(@RequestBody MenuParamDTO dto) {
        if (dto == null || dto.getId() == null) {
            return Result.error("参数错误");
        }
        LambdaQueryWrapper<MenuEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MenuEntity::getId, dto.getId());
        queryWrapper.eq(MenuEntity::getIsDelete, 0);
        applyAppIdFilter(queryWrapper, dto.getAppId());
        MenuEntity menu = menuService.getOne(queryWrapper);
        if (menu == null) {
            return Result.error("菜单不存在或不在当前应用范围内");
        }
        return Result.result(menu);
    }

    @ApiOperation("保存菜单")
    @PostMapping("save")
    public Result save(@RequestBody MenuEntity menu) {
        if (Objects.isNull(menu.getPid())) {
            menu.setPid(0L);
        }
        resolveMenuAppId(menu);
        if (Long.valueOf(0L).equals(menu.getPid()) && menu.getAppId() == null) {
            return Result.error("顶级菜单(pid=0)必须指定 appId");
        }
        convertMenuCode(menu);
        return Result.result(menuService.saveOrUpdate(menu));
    }

    @ApiOperation("删除菜单")
    @PostMapping("delete")
    public Result remove(@NotNull @NotEmpty Long[] ids, Long appId) {
        List<MenuEntity> toDelete = menuService.list(new LambdaQueryWrapper<MenuEntity>()
                .in(MenuEntity::getId, Arrays.asList(ids))
                .eq(MenuEntity::getIsDelete, 0));
        if (CollectionUtils.isEmpty(toDelete)) {
            return Result.error("菜单不存在或已删除");
        }
        if (appId != null) {
            boolean outOfApp = toDelete.stream().anyMatch(m -> !appId.equals(m.getAppId()));
            if (outOfApp) {
                return Result.error("存在不属于当前应用的菜单，无法删除");
            }
        }
        List<MenuEntity> menus = menuService.list(new LambdaQueryWrapper<MenuEntity>().in(MenuEntity::getPid, ids));
        if (!CollectionUtils.isEmpty(menus)) {
            List<Long> idls = Arrays.asList(ids);
            for (MenuEntity menu : menus) {
                if (!idls.contains(menu.getId())) {
                    return Result.error("请先删除子节点");
                }
            }
        }
        menuService.removeByIds(Arrays.asList(ids));
        return Result.ok();
    }




    /**
     * 递归生成菜单树
     */
    private List<TreeVo> createResTrees(Long pid, List<TreeVo> menus) {
        List<TreeVo> treeMenu = new ArrayList<>();
        for (TreeVo menu : menus) {
            if (pid.equals(menu.getParentId())) {
                treeMenu.add(menu);
                List<TreeVo> childs =  createResTrees(menu.getId(), menus);
                if (childs != null && childs.size() > 0) {
                    menu.setChildren(childs);
                }
            }
        }
        return treeMenu;
    }

    private void convertMenuCode(MenuEntity info) {

        if (StrUtil.isBlank(info.getMenuCode())) {
            String routeCode = getInitials(info.getMenuName());
            MenuEntity menu = menuService.getRootLastNodeInfo(info.getPid(), info.getAppId());
            String lastCode;
            if (menu == null) {
                info.setPid(Long.valueOf(0));
                info.setMenuCode(routeCode);
            } else {
                lastCode = getInitials(menu.getMenuName());
                info.setMenuCode(lastCode+"_"+routeCode);
            }
        }
    }

    @ApiOperation("处理历史数据code")
    @PostMapping("batch_generate_code")
    public Result initializeCode(@RequestBody(required = false) MenuParamDTO dto) {
        LambdaQueryWrapper<MenuEntity> wrapper = new LambdaQueryWrapper<MenuEntity>()
                .in(MenuEntity::getMenuType, Arrays.asList(1, 2))
                .eq(MenuEntity::getIsDelete, 0);
        applyAppIdFilter(wrapper, dto != null ? dto.getAppId() : null);
        List<MenuEntity> menuList = menuService.list(wrapper);
        Map<Long,MenuEntity> mapMenu = menuList.stream().collect(Collectors.toMap(MenuEntity::getId, a ->a));
        for (MenuEntity info : menuList) {
            String routeCode = getInitials(info.getMenuName());
            String code = recursionMenu(mapMenu,info,routeCode);
            LambdaUpdateWrapper<MenuEntity> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(MenuEntity::getId,info.getId());
            updateWrapper.set(MenuEntity::getMenuCode,code);
            menuService.update(updateWrapper);
        }
        return Result.ok();
    }

    @ApiOperation("处理历史数据code")
    @PostMapping("update_menu_icon")
    public Result updateMenuIcon(@RequestBody(required = false) MenuParamDTO dto) {
        LambdaQueryWrapper<MenuEntity> wrapper = new LambdaQueryWrapper<MenuEntity>()
                .eq(MenuEntity::getMenuType, 2)
                .eq(MenuEntity::getIsDelete, 0);
        applyAppIdFilter(wrapper, dto != null ? dto.getAppId() : null);
        List<MenuEntity> menuList = menuService.list(wrapper);
        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        for (MenuEntity info : menuList) {
            try {
                String iconName = PinyinHelper.toHanyuPinyinString(info.getMenuName(), format, "");
                LambdaUpdateWrapper<MenuEntity> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(MenuEntity::getId,info.getId());
                updateWrapper.set(MenuEntity::getIcon,iconName);
                menuService.update(updateWrapper);
            }catch (Exception e) {
                log.error("---updateMenuIcon",e);
            }
        }
        return Result.ok();
    }
    public String recursionMenu(Map<Long,MenuEntity> mapMenu,MenuEntity info,String routeCode) {

        if (Integer.valueOf(0).equals(info.getPid())) {
            return routeCode;
        }
        MenuEntity pMenu = mapMenu.get(info.getPid());
        if (Objects.isNull(pMenu)) {
            return routeCode;
        }
        String pCode = getInitials(pMenu.getMenuName());
        if (StrUtil.isNotBlank(pCode)) {
            routeCode = pCode+"_"+routeCode;
           return recursionMenu(mapMenu,pMenu,routeCode);
        }
        return routeCode;
    }

    public static String getInitials(String chinese) {
        StringBuilder initials = new StringBuilder();
        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);

        for (char ch : chinese.toCharArray()) {
            if (Character.toString(ch).matches("[\u4E00-\u9FA5]")) { // 判断是否为汉字
                try {
                    String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(ch, format);
                    if (pinyinArray != null && pinyinArray.length > 0) {
                        initials.append(pinyinArray[0].charAt(0));
                    }
                } catch (BadHanyuPinyinOutputFormatCombination e) {
                   log.error("hanyuPinyinOutputFormatCombination---error-----",e);
                }
            } else {
                initials.append(ch); // 非汉字直接附加
            }
        }

        return initials.toString();
    }

    public static void main(String[] args) {
        // 创建输出格式对象
        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        // 设置拼音为全小写
        format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        // 设置拼音不带音调
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);

        // 你可以使用 PinyinHelper 来转换汉字为拼音
        try {
            String pinyin = PinyinHelper.toHanyuPinyinString("汉字", format, "");
            System.out.println(pinyin);  // 输出：han zi
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 递归生成菜单树
     */
    private List<UserMenuVO> createTreeMenus(Long pid, List<UserMenuVO> menus) {
        List<UserMenuVO> treeMenu = new ArrayList<>();
        for (UserMenuVO menu : menus) {
            if (pid.equals(menu.getPid())) {
                treeMenu.add(menu);
                List<UserMenuVO> childs =  createTreeMenus(menu.getId(), menus);
                if (childs != null && childs.size() > 0) {
                    menu.setChildren(childs);
                }
            }
        }
        return treeMenu;
    }

    @ApiOperation("获取自定义菜单")
    @PostMapping("get_custom_menu_list")
    public Result getCustomMenuList(Integer position) {

        LambdaQueryWrapper<UserWebH5MenuShowConfigEntity> queryH5Config = new LambdaQueryWrapper();
        queryH5Config.eq(UserWebH5MenuShowConfigEntity::getOwnerBy, LoginUserUtil.getCurrentUserId());
        queryH5Config.eq(UserWebH5MenuShowConfigEntity::getMenuShowPosition,position);
        queryH5Config.last("limit 1");
        UserWebH5MenuShowConfigEntity webH5MenuShowConfig =  webH5MenuShowConfigService.getOne(queryH5Config);
        if (Objects.nonNull(webH5MenuShowConfig)) {
            String menuJson = webH5MenuShowConfig.getMenuJson();
            return Result.result(menuJson);
        }
//        LambdaQueryWrapper<MenuEntity> queryWrapper = new LambdaQueryWrapper();
//        queryWrapper.eq(MenuEntity::getIsDelete,0);
//        queryWrapper.eq(MenuEntity::getEnabled,1);
//        queryWrapper.eq(MenuEntity::getServiceModeType, 1);
//        queryWrapper.eq(MenuEntity::getMenuShowPosition, position);
//        queryWrapper.orderByAsc(MenuEntity::getSort);
//        List<MenuEntity> menus = menuService.list(queryWrapper);
//        if (!CollectionUtils.isEmpty(menus)) {
//            String menuJson = JSON.toJSONString(menus);
//            return Result.result(JSONArray.parseArray(menuJson, UserH5MenuVO.class));
//        }
        return Result.ok();
    }

    @ApiOperation("自定义菜单设置")
    @PostMapping("set_custom_menu")
    public Result customMenuSet(@RequestBody CustomMenuDTO dto) {

        LambdaQueryWrapper<UserWebH5MenuShowConfigEntity> queryH5Config = new LambdaQueryWrapper();
        queryH5Config.eq(UserWebH5MenuShowConfigEntity::getOwnerBy, LoginUserUtil.getCurrentUserId());
        queryH5Config.eq(UserWebH5MenuShowConfigEntity::getMenuShowPosition,dto.getPosition());
        queryH5Config.last("limit 1");
        UserWebH5MenuShowConfigEntity webH5MenuShowConfig =  webH5MenuShowConfigService.getOne(queryH5Config);
        if (Objects.isNull(webH5MenuShowConfig)) {
            webH5MenuShowConfig = new UserWebH5MenuShowConfigEntity();
            webH5MenuShowConfig.setMenuJson(dto.getJsonMenu());
            webH5MenuShowConfig.setMenuShowPosition(dto.getPosition());
            webH5MenuShowConfig.setOwnerBy(LoginUserUtil.getCurrentUserId());
        } else {
            webH5MenuShowConfig.setMenuJson(dto.getJsonMenu());
            webH5MenuShowConfig.setMenuShowPosition(dto.getPosition());
        }
        webH5MenuShowConfigService.saveOrUpdate(webH5MenuShowConfig);
        return Result.ok();
    }


    @ApiOperation("查询菜单所有菜单")
    @PostMapping("allMenulist")
    public Result allMenulist(@RequestBody(required = false) MenuParamDTO dto) {
        if (dto == null) {
            dto = new MenuParamDTO();
        }
        Integer[] types = dto.getMenuTypes();
        if (types == null || types.length == 0) {
            types = new Integer[]{1, 2};
        }
        try {
            LambdaQueryWrapper<MenuEntity> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(MenuEntity::getIsDelete, 0);
            queryWrapper.eq(MenuEntity::getEnabled, 1);
            queryWrapper.in(MenuEntity::getMenuType, Arrays.asList(types));
            applyAppIdFilter(queryWrapper, dto.getAppId());
            if (StringUtils.isNotEmpty(dto.getMenuName())) {
                queryWrapper.like(MenuEntity::getMenuName, dto.getMenuName());
            }
            queryWrapper.orderByAsc(MenuEntity::getSort);
            List<MenuEntity> menus = menuService.list(queryWrapper);
            if (!CollectionUtils.isEmpty(menus)) {
                menus.forEach(e -> {
                    if (StrUtil.isNotBlank(e.getMenuName())) {
                        String pyIcon = PingyinUtil.getLowFullSpell(e.getMenuName());
                        e.setIcon(pyIcon);
                    }
                });
            }
//            List<RouterVo> routerVos = menuToRouter(menus);
            return Result.result(menus);
        }catch (Exception e) {
            e.printStackTrace();
            return Result.error("获取菜单信息错误:"+e.getMessage());
        }
    }

    /**
     * 菜单列表通用范围：终端类型 + 应用 ID（appId 有值时按 menu.app_id 过滤）。
     */
    private void applyMenuScopeFilter(LambdaQueryWrapper<MenuEntity> queryWrapper, MenuParamDTO dto) {
        if (dto == null || dto.getServiceModeType() == null) {
            queryWrapper.eq(MenuEntity::getServiceModeType, 0);
        } else {
            queryWrapper.eq(MenuEntity::getServiceModeType, dto.getServiceModeType());
        }
        applyAppIdFilter(queryWrapper, dto != null ? dto.getAppId() : null);
    }

    /**
     * 按应用过滤：appId 非空时追加 menu.app_id = appId。
     */
    private void applyAppIdFilter(LambdaQueryWrapper<MenuEntity> queryWrapper, Long appId) {
        if (appId != null) {
            queryWrapper.eq(MenuEntity::getAppId, appId);
        }
    }

    /**
     * 子菜单未传 appId 时继承父级应用。
     */
    private void resolveMenuAppId(MenuEntity menu) {
        if (menu.getAppId() != null || menu.getPid() == null || menu.getPid() <= 0) {
            return;
        }
        MenuEntity parent = menuService.getById(menu.getPid());
        if (parent != null && parent.getAppId() != null) {
            menu.setAppId(parent.getAppId());
        }
    }
}
