package org.xyzh.system.menu.service.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.dto.menu.TbSysMenu;
import org.xyzh.common.dto.menu.TbSysMenuPermission;
import org.xyzh.common.utils.IDUtils;
import org.xyzh.system.mapper.MenuMapper;
import org.xyzh.system.mapper.MenuPermissionMapper;
import org.xyzh.system.menu.service.SysMenuService;

import java.util.Date;
import java.util.List;

/**
 * @description SysMenuServiceImpl.java文件描述 系统菜单服务实现类
 * @filename SysMenuServiceImpl.java
 * @author yslg
 * @copyright xyzh
 * @since 2025-09-28
 */
@Service
public class SysMenuServiceImpl implements SysMenuService {

    private static final Logger logger = LoggerFactory.getLogger(SysMenuServiceImpl.class);

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private MenuPermissionMapper menuPermissionMapper;

    @Override
    public ResultDomain<TbSysMenu> getAllMenus() {
        ResultDomain<TbSysMenu> resultDomain = new ResultDomain<>();

        try {
            logger.info("开始查询所有菜单");
            
            List<TbSysMenu> menus = menuMapper.selectAllMenus();
            
            logger.info("查询所有菜单完成，共找到{}个菜单", menus.size());
            resultDomain.success("查询成功", menus);
            return resultDomain;
            
        } catch (Exception e) {
            logger.error("查询所有菜单失败", e);
            resultDomain.fail("查询菜单失败：" + e.getMessage());
            return resultDomain;
        }
    }

    @Override
    public ResultDomain<TbSysMenu> getMenuList(TbSysMenu filter) {
        ResultDomain<TbSysMenu> resultDomain = new ResultDomain<>();
        try {
            logger.info("开始查询菜单列表：{}", filter);
            
            List<TbSysMenu> menus = menuMapper.selectMenuList(filter);
            
            logger.info("查询菜单列表完成，共找到{}个菜单", menus.size());
            resultDomain.success("查询成功", menus);
            return resultDomain;
            
        } catch (Exception e) {
            logger.error("查询菜单列表失败：{}", filter, e);
            resultDomain.fail("查询菜单失败：" + e.getMessage());
            return resultDomain;
        }
        
    }

    @Override
    public ResultDomain<TbSysMenu> getMenuById(String menuId) {
        ResultDomain<TbSysMenu> resultDomain = new ResultDomain<>();
        try {
            logger.info("开始根据ID查询菜单：{}", menuId);
            
            if (!StringUtils.hasText(menuId)) {
                resultDomain.fail("菜单ID不能为空");
                return resultDomain;
            }
            
            TbSysMenu menu = menuMapper.selectMenuById(menuId);
            
            if (menu == null) {
                logger.warn("未找到菜单：{}", menuId);
                resultDomain.fail("未找到指定菜单");
                return resultDomain;
            }
            
            logger.info("根据ID查询菜单完成：{}", menuId);
            resultDomain.success("查询成功", menu);
            return resultDomain;
            
        } catch (Exception e) {
            logger.error("根据ID查询菜单失败：{}", menuId, e);
            resultDomain.fail("查询菜单失败：" + e.getMessage());
            return resultDomain;
        }
    }

    @Override
    public ResultDomain<TbSysMenu> getMenusByUserId(String userId) {
        ResultDomain<TbSysMenu> resultDomain = new ResultDomain<>();
        try {
            logger.info("开始根据用户ID查询菜单列表：{}", userId);
            
            if (!StringUtils.hasText(userId)) {
                resultDomain.fail("用户ID不能为空");
                return resultDomain;
            }
            
            List<TbSysMenu> menus = menuMapper.selectMenusByUserId(userId);
            
            logger.info("根据用户ID查询菜单列表完成，共找到{}个菜单", menus.size());
            resultDomain.success("查询成功", menus);
            return resultDomain;
            
        } catch (Exception e) {
            logger.error("根据用户ID查询菜单列表失败：{}", userId, e);
            resultDomain.fail("查询菜单失败：" + e.getMessage());
            return resultDomain;
        }
    }

    @Override
    public ResultDomain<TbSysMenu> getMenusByRoleId(String roleId) {
        ResultDomain<TbSysMenu> resultDomain = new ResultDomain<>();
        try {
            logger.info("开始根据角色ID查询菜单列表：{}", roleId);
            
            if (!StringUtils.hasText(roleId)) {
                resultDomain.fail("角色ID不能为空");
                return resultDomain;
            }
            
            List<TbSysMenu> menus = menuMapper.selectMenusByRoleId(roleId);
            
            logger.info("根据角色ID查询菜单列表完成，共找到{}个菜单", menus.size());
            resultDomain.success("查询成功", menus);
            return resultDomain;
            
        } catch (Exception e) {
            logger.error("根据角色ID查询菜单列表失败：{}", roleId, e);
            resultDomain.fail("查询菜单失败：" + e.getMessage());
            return resultDomain;
        }
    }

    @Override
    public ResultDomain<TbSysMenu> getMenusByParentId(String parentId) {
        ResultDomain<TbSysMenu> resultDomain = new ResultDomain<>();
        try {
            logger.info("开始根据父菜单ID查询子菜单：{}", parentId);
            
            List<TbSysMenu> menus = menuMapper.selectByParentId(parentId);
            
            logger.info("根据父菜单ID查询子菜单完成，共找到{}个子菜单", menus.size());
            resultDomain.success("查询成功", menus);
            return resultDomain;
            
        } catch (Exception e) {
            logger.error("根据父菜单ID查询子菜单失败：{}", parentId, e);
            resultDomain.fail("查询子菜单失败：" + e.getMessage());
            return resultDomain;
        }
    }

    @Override
    public ResultDomain<TbSysMenu> getMenuTree() {
        ResultDomain<TbSysMenu> resultDomain = new ResultDomain<>();
        try {
            logger.info("开始查询菜单树结构");
            
            List<TbSysMenu> menus = menuMapper.selectMenuTree();
            
            logger.info("查询菜单树结构完成，共找到{}个菜单", menus.size());
            resultDomain.success("查询成功", menus);
            return resultDomain;
            
        } catch (Exception e) {
            logger.error("查询菜单树结构失败", e);
            resultDomain.fail("查询菜单树失败：" + e.getMessage());
            return resultDomain;
        }
    }

    @Override
    public ResultDomain<TbSysMenu> createMenu(TbSysMenu menu) {
        ResultDomain<TbSysMenu> resultDomain = new ResultDomain<>();
        try {
            logger.info("开始创建菜单：{}", menu.getName());
            
            // 参数校验
            if (!StringUtils.hasText(menu.getName())) {
                resultDomain.fail("菜单名称不能为空");
                return resultDomain;
            }
            
            // 检查菜单名称是否已存在
            ResultDomain<Boolean> checkResult = checkMenuNameExists(menu.getName(), null);
            if (!checkResult.isSuccess()) {
                resultDomain.fail(checkResult.getMessage());
                return resultDomain;
            }
            if (checkResult.getData()) {
                resultDomain.fail("菜单名称已存在");
                return resultDomain;
            }
            
            // 设置基础信息
            menu.setID(IDUtils.generateID());
            menu.setMenuID(IDUtils.generateID());
            menu.setCreateTime(new Date());
            menu.setDeleted(false);

            
            // 插入数据库
            int result = menuMapper.insert(menu);
            
            if (result > 0) {
                logger.info("创建菜单成功：{}", menu.getName());
                resultDomain.success("创建菜单成功", menu);
                return resultDomain;
            } else {
                logger.warn("创建菜单失败：{}", menu.getName());
                resultDomain.fail("创建菜单失败");
            }
            
            return resultDomain;
        } catch (Exception e) {
            logger.error("创建菜单异常：{}", menu.getName(), e);
            resultDomain.fail("创建菜单失败：" + e.getMessage());
            return resultDomain;
        }
    }

    @Override
    public ResultDomain<TbSysMenu> updateMenu(TbSysMenu menu) {
        ResultDomain<TbSysMenu> resultDomain = new ResultDomain<>();
        try {
            logger.info("开始更新菜单：{}", menu.getMenuID());
            
            // 参数校验
            if (!StringUtils.hasText(menu.getMenuID())) {
                resultDomain.fail("菜单ID不能为空");
                return resultDomain;
            }
            if (!StringUtils.hasText(menu.getName())) {
                resultDomain.fail("菜单名称不能为空");
                return resultDomain;
            }
            
            // 检查菜单是否存在
            ResultDomain<TbSysMenu> existResult = getMenuById(menu.getMenuID());
            if (!existResult.isSuccess()) {
                resultDomain.fail(existResult.getMessage());
                return resultDomain;
            }
            
            // 检查菜单名称是否已存在（排除自身）
            ResultDomain<Boolean> checkResult = checkMenuNameExists(menu.getName(), menu.getID());
            if (!checkResult.isSuccess()) {
                resultDomain.fail(checkResult.getMessage());
                return resultDomain;
            }
            if (checkResult.getData()) {
                resultDomain.fail("菜单名称已存在");
                return resultDomain;
            }
            
            // 设置更新时间
            menu.setUpdateTime(new Date());
            
            // 更新数据库
            int result = menuMapper.updateById(menu);
            
            if (result > 0) {
                logger.info("更新菜单成功：{}", menu.getMenuID());
                resultDomain.success("更新菜单成功", menu);
                return resultDomain;
            } else {
                logger.warn("更新菜单失败：{}", menu.getMenuID());
                resultDomain.fail("更新菜单失败");
                return resultDomain;
            }
            
        } catch (Exception e) {
            logger.error("更新菜单异常：{}", menu.getMenuID(), e);
            resultDomain.fail("更新菜单失败：" + e.getMessage());
            return resultDomain;
        }
    }

    @Override
    public ResultDomain<TbSysMenu> deleteMenu(String menuId) {
        ResultDomain<TbSysMenu> resultDomain = new ResultDomain<>();
        try {
            logger.info("开始删除菜单：{}", menuId);
            
            if (!StringUtils.hasText(menuId)) {
                resultDomain.fail("菜单ID不能为空");
                return resultDomain;
            }
            
            // 检查菜单是否存在
            ResultDomain<TbSysMenu> existResult = getMenuById(menuId);
            if (!existResult.isSuccess()) {
                resultDomain.fail(existResult.getMessage());
                return resultDomain;
            }
            
            // 检查是否有子菜单
            ResultDomain<TbSysMenu> childrenResult = getMenusByParentId(menuId);
            if (childrenResult.isSuccess() && childrenResult.getData() != null) {
                resultDomain.fail("该菜单下有子菜单，无法删除");
                return resultDomain;
            }
            
            // 逻辑删除
            TbSysMenu menu = existResult.getData();
            menu.setDeleted(true);
            menu.setDeleteTime(new Date());
            
            int result = menuMapper.updateById(menu);
            
            if (result > 0) {
                logger.info("删除菜单成功：{}", menuId);
                resultDomain.success("删除菜单成功", menu);
                return resultDomain;
            } else {
                logger.warn("删除菜单失败：{}", menuId);
                resultDomain.fail("删除菜单失败");
                return resultDomain;
            }
            
        } catch (Exception e) {
            logger.error("删除菜单异常：{}", menuId, e);
            resultDomain.fail("删除菜单失败：" + e.getMessage());
            return resultDomain;
        }
    }

    @Override
    public ResultDomain<Boolean> checkMenuNameExists(String menuName, String excludeId) {
        ResultDomain<Boolean> resultDomain = new ResultDomain<>();
        try {
            logger.info("检查菜单名称是否存在：{}", menuName);
            
            if (!StringUtils.hasText(menuName)) {
                resultDomain.fail("菜单名称不能为空");
                return resultDomain;
            }
            
            int count = menuMapper.countByMenuName(menuName, excludeId);
            boolean exists = count > 0;
            
            logger.info("菜单名称存在性检查完成：{}，存在：{}", menuName, exists);
            resultDomain.success("检查完成", exists);
            return resultDomain;
            
        } catch (Exception e) {
            logger.error("检查菜单名称存在性失败：{}", menuName, e);
            resultDomain.fail("检查失败：" + e.getMessage());
            return resultDomain;
        }
    }

    @Override
    public ResultDomain<TbSysMenu> changeMenuStatus(String menuId, Integer status) {
        ResultDomain<TbSysMenu> resultDomain = new ResultDomain<>();
        try {
            logger.info("开始修改菜单状态：{}，状态：{}", menuId, status);
            
            if (!StringUtils.hasText(menuId)) {
                resultDomain.fail("菜单ID不能为空");
                return resultDomain;
            }
            
            if (status == null) {
                resultDomain.fail("菜单状态不能为空");
                return resultDomain;
            }
            
            // 检查菜单是否存在
            ResultDomain<TbSysMenu> existResult = getMenuById(menuId);
            if (!existResult.isSuccess()) {
                resultDomain.fail(existResult.getMessage());
                return resultDomain;
            }
            
            TbSysMenu menu = existResult.getData();
        
            menu.setUpdateTime(new Date());
            
            int result = menuMapper.updateById(menu);
            
            if (result > 0) {
                logger.info("修改菜单状态成功：{}", menuId);
                resultDomain.success("修改菜单状态成功", menu);
                return resultDomain;
            } else {
                logger.warn("修改菜单状态失败：{}", menuId);
                resultDomain.fail("修改菜单状态失败");
                return resultDomain;
            }
            
        } catch (Exception e) {
            logger.error("修改菜单状态异常：{}", menuId, e);
            resultDomain.fail("修改菜单状态失败：" + e.getMessage());
            return resultDomain;
        }
    }

    @Override
    public ResultDomain<TbSysMenu> changeMenuVisibility(String menuId, Boolean visible) {
        ResultDomain<TbSysMenu> resultDomain = new ResultDomain<>();
        try {
            logger.info("开始修改菜单可见性：{}，可见性：{}", menuId, visible);
            
            if (!StringUtils.hasText(menuId)) {
                resultDomain.fail("菜单ID不能为空");
                return resultDomain;
            }
            
            if (visible == null) {
                resultDomain.fail("菜单可见性不能为空");
                return resultDomain;
            }
            
            // 检查菜单是否存在
            ResultDomain<TbSysMenu> existResult = getMenuById(menuId);
            if (!existResult.isSuccess()) {
                resultDomain.fail(existResult.getMessage());
                return resultDomain;
            }
            
            TbSysMenu menu = existResult.getData();
            menu.setUpdateTime(new Date());
            
            int result = menuMapper.updateById(menu);
            
            if (result > 0) {
                logger.info("修改菜单可见性成功：{}", menuId);
                resultDomain.success("修改菜单可见性成功", menu);
                return resultDomain;
            } else {
                logger.warn("修改菜单可见性失败：{}", menuId);
                resultDomain.fail("修改菜单可见性失败");
                return resultDomain;
            }
            
        } catch (Exception e) {
            logger.error("修改菜单可见性异常：{}", menuId, e);
            resultDomain.fail("修改菜单可见性失败：" + e.getMessage());
            return resultDomain;
        }
    }
    
    @Override
    public ResultDomain<TbSysMenuPermission> getMenuPermission(String menuId) {
        ResultDomain<TbSysMenuPermission> resultDomain = new ResultDomain<>();
        try {
            logger.info("开始查询菜单权限：{}", menuId);
            List<TbSysMenuPermission> menuPermissions = menuPermissionMapper.selectByMenuId(menuId);
            if (menuPermissions.isEmpty()) {
                resultDomain.fail("未找到菜单权限");
                return resultDomain;
            }
            resultDomain.success("查询菜单权限成功", menuPermissions);
            return resultDomain;
        } catch (Exception e) {
            logger.error("查询菜单权限异常：{}", menuId, e);
            resultDomain.fail("查询菜单权限失败：" + e.getMessage());
            return resultDomain;
        }
    }
}
