package com.czg.service.account.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.czg.account.dto.PageDTO;
import com.czg.account.dto.role.RoleAddDTO;
import com.czg.account.dto.role.RoleEditDTO;
import com.czg.account.entity.SysMenu;
import com.czg.account.entity.SysRole;
import com.czg.account.entity.SysRolesMenus;
import com.czg.account.service.SysMenuService;
import com.czg.account.service.SysRoleService;
import com.czg.account.service.SysRolesMenusService;
import com.czg.exception.ApiNotPrintException;
import com.czg.sa.StpKit;
import com.czg.service.account.mapper.SysRoleMapper;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

import static com.mybatisflex.core.query.QueryMethods.column;

/**
 * 角色表 服务层实现。
 *
 * @author Administrator
 * @since 2025-02-08
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole>  implements SysRoleService {
    @Resource
    private SysMenuService sysMenuService;
    @Resource
    private SysRolesMenusService sysRolesMenusService;

    @Override
    public List<SysRole> getByUserId(Long id) {
        return mapper.selectByUserId(id);
    }

    @Override
    public Page<SysRole> getList(Long shopId, PageDTO pageDTO, String key, String startTime, String endTime) {
        QueryWrapper queryWrapper = new QueryWrapper();
        if (!StpKit.USER.isAdmin()) {
            queryWrapper.eq(SysRole::getCreateUserId, StpKit.USER.getLoginIdAsLong());
        }

        if (StrUtil.isNotBlank(key)) {
            queryWrapper.and(column(SysRole::getName).like(key).or(column(SysRole::getDescription).like(key)));
        }

        if (StrUtil.isNotBlank(startTime)) {
            queryWrapper.ge(SysRole::getCreateTime, DateUtil.parse(startTime));
        }

        if (StrUtil.isNotBlank(endTime)) {
            queryWrapper.le(SysRole::getCreateTime, DateUtil.parse(endTime));
        }

        return page(new Page<>(pageDTO.page(), pageDTO.size()), queryWrapper);
    }

    @Override
    public List<Long> getRoleMenu(long userId, Integer id) {
        SysRole role = queryChain().eq(SysRole::getId, id).eq(SysRole::getCreateUserId, userId).one();
        if (role == null) {
            throw new ApiNotPrintException("角色不存在");
        }
        return sysRolesMenusService.queryChain().eq(SysRolesMenus::getRoleId, id).list().stream().map(SysRolesMenus::getMenuId).toList();
    }

    public boolean addMenu(Long roleId, List<Long> menuIds) {
        long count = sysMenuService.queryChain().in(SysMenu::getMenuId, menuIds).count();
        if (count != menuIds.size()) {
            throw new ApiNotPrintException("菜单id包含错误id");
        }

        ArrayList<SysRolesMenus> rolesMenus = new ArrayList<>();
        for (Long id : menuIds) {
            rolesMenus.add(new SysRolesMenus(id, roleId));
        }
        return sysRolesMenusService.saveBatch(rolesMenus);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(RoleAddDTO roleAddDTO) {
        long roleCount = queryChain().eq(SysRole::getName, roleAddDTO.name())
                .eq(SysRole::getShopId, StpKit.USER.getShopId())
                .count();
        if (roleCount > 0) {
            throw new ApiNotPrintException("此角色名称已存在");
        }

        SysRole sysRole = new SysRole();
        sysRole.setName(roleAddDTO.name());
        sysRole.setLevel(roleAddDTO.level());
        sysRole.setDescription(roleAddDTO.description());
        sysRole.setShopId(StpKit.USER.getLoginIdAsLong());
        sysRole.setCreateUserId(StpKit.USER.getLoginIdAsLong());
        sysRole.setCreateTime(DateUtil.date().toLocalDateTime());
        boolean save = save(sysRole);
        if (save) {
            return addMenu(sysRole.getId(), roleAddDTO.menuIdList());
        }

        throw new ApiNotPrintException("保存失败");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean edit(RoleEditDTO roleEditDTO) {
        SysRole role = queryChain().eq(SysRole::getId, roleEditDTO.getId()).eq(SysRole::getCreateUserId, StpKit.USER.getLoginIdAsLong()).one();
        if (role == null) {
            throw new ApiNotPrintException("角色不存在");
        }

        long roleCount = queryChain().eq(SysRole::getName, roleEditDTO.getName()).ne(SysRole::getId, roleEditDTO.getId())
                .eq(SysRole::getShopId, StpKit.USER.getShopId()).count();
        if (roleCount > 0) {
            throw new ApiNotPrintException("此角色名称已存在");
        }

        BeanUtil.copyProperties(roleEditDTO, role);
        boolean b = updateById(role);
        if (b) {
            sysRolesMenusService.updateChain().eq(SysRolesMenus::getRoleId, role.getId()).remove();
            return addMenu(role.getId(), roleEditDTO.getMenuIdList());
            }
        throw new ApiNotPrintException("保存失败");
    }
}
