package com.hertz.modules.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hertz.common.exception.BusinessException;
import com.hertz.modules.system.entity.SysRole;
import com.hertz.modules.system.entity.SysRoleMenu;
import com.hertz.modules.system.mapper.SysRoleMapper;
import com.hertz.modules.system.mapper.SysRoleMenuMapper;
import com.hertz.modules.system.service.RoleService;
import java.util.List;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class RoleServiceImpl implements RoleService {
  private final SysRoleMapper roleMapper;
  private final SysRoleMenuMapper roleMenuMapper;

  public RoleServiceImpl(SysRoleMapper roleMapper, SysRoleMenuMapper roleMenuMapper) {
    this.roleMapper = roleMapper;
    this.roleMenuMapper = roleMenuMapper;
  }

  @Override
  public List<SysRole> listEnabledRoles() {
    return roleMapper.selectList(new LambdaQueryWrapper<SysRole>()
        .eq(SysRole::getStatus, 1)
        .orderByAsc(SysRole::getId));
  }

  @Override
  public IPage<SysRole> pageRoles(int page, int size, String keyword) {
    var wrapper = new LambdaQueryWrapper<SysRole>().orderByDesc(SysRole::getId);
    if (keyword != null && !keyword.isBlank()) {
      wrapper.and(w -> w.like(SysRole::getRoleName, keyword).or().like(SysRole::getRoleKey, keyword));
    }
    return roleMapper.selectPage(Page.of(page, size), wrapper);
  }

  @Override
  @Transactional
  public void saveRole(SysRole role) {
    if (roleMapper.selectCount(new LambdaQueryWrapper<SysRole>().eq(SysRole::getRoleKey, role.getRoleKey())) > 0) {
      throw new BusinessException(400, "Role key already exists");
    }
    role.setCreatedAt(java.time.LocalDateTime.now());
    role.setUpdatedAt(java.time.LocalDateTime.now());
    roleMapper.insert(role);
  }

  @Override
  @Transactional
  public void updateRole(SysRole role) {
    var existing = roleMapper.selectById(role.getId());
    if (existing == null) {
      throw new BusinessException(404, "Role not found");
    }
    existing.setRoleName(role.getRoleName());
    existing.setRoleKey(role.getRoleKey());
    existing.setStatus(role.getStatus());
    existing.setUpdatedAt(java.time.LocalDateTime.now());
    roleMapper.updateById(existing);
  }

  @Override
  @Transactional
  public void deleteRole(Long id) {
    roleMapper.deleteById(id);
    roleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, id));
  }

  @Override
  @Transactional
  public void updateRolePermissions(Long roleId, List<Long> menuIds) {
    roleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleId));
    if (menuIds != null) {
      menuIds.stream().distinct().forEach(menuId -> {
        SysRoleMenu rm = new SysRoleMenu();
        rm.setRoleId(roleId);
        rm.setMenuId(menuId);
        roleMenuMapper.insert(rm);
      });
    }
  }

  @Override
  public List<Long> getRoleMenuIds(Long roleId) {
    return roleMenuMapper.selectList(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleId))
        .stream().map(SysRoleMenu::getMenuId).toList();
  }
}

