package com.erp.permission.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.erp.permission.dto.*;
import com.erp.permission.entity.Permission;
import com.erp.permission.entity.Role;
import com.erp.permission.exception.BusinessException;
import com.erp.permission.repository.PermissionRepository;
import com.erp.permission.repository.RoleRepository;
import com.erp.permission.service.PermissionService;
import com.erp.permission.service.RoleService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 角色服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RoleServiceImpl implements RoleService {
    
    private static final String SUPER_ADMIN_SLUG = "super_admin";
    
    private final RoleRepository roleRepository;
    private final PermissionRepository permissionRepository;
    private final PermissionService permissionService;
    
    @Override
    public RoleListResponse listRoles(String keyword) {
        LambdaQueryWrapper<Role> wrapper = new LambdaQueryWrapper<>();
        
        if (keyword != null && !keyword.isBlank()) {
            wrapper.like(Role::getName, keyword);
        }
        
        wrapper.orderByDesc(Role::getLevel);
        
        List<Role> roles = roleRepository.selectList(wrapper);
        
        // 填充用户数量
        List<RoleDTO> list = roles.stream()
                .map(role -> {
                    Long userCount = roleRepository.countUsersByRoleId(role.getId());
                    List<String> permissionSlugs = permissionService.getPermissionSlugsByRoleId(role.getId());
                    
                    return toDTO(role, userCount, permissionSlugs);
                })
                .collect(Collectors.toList());
        
        return RoleListResponse.builder()
                .list(list)
                .build();
    }
    
    @Override
    public RoleDTO getRole(Long id) {
        Role role = roleRepository.findById(id);
        if (role == null) {
            throw new BusinessException(404, "角色不存在");
        }
        
        Long userCount = roleRepository.countUsersByRoleId(id);
        List<String> permissionSlugs = permissionService.getPermissionSlugsByRoleId(id);
        
        return toDTO(role, userCount, permissionSlugs);
    }
    
    @Override
    @Transactional
    public RoleDTO createRole(CreateRoleRequest request) {
        // 检查slug是否已存在
        if (roleRepository.existsBySlug(request.getCode())) {
            throw new BusinessException(400, "角色标识已存在");
        }
        
        Role role = Role.builder()
                .name(request.getName())
                .slug(request.getCode())
                .level(request.getLevel())
                .description(request.getDescription())
                .guardName("web")
                .build();
        
        roleRepository.insert(role);
        
        // 分配权限
        if (request.getPermissions() != null && !request.getPermissions().isEmpty()) {
            assignPermissionsInternal(role.getId(), request.getPermissions());
        }
        
        log.info("创建角色成功: {}", role.getSlug());
        
        List<String> permissionSlugs = permissionService.getPermissionSlugsByRoleId(role.getId());
        return toDTO(role, 0L, permissionSlugs);
    }
    
    @Override
    @Transactional
    public RoleDTO updateRole(Long id, UpdateRoleRequest request) {
        Role role = roleRepository.findById(id);
        if (role == null) {
            throw new BusinessException(404, "角色不存在");
        }
        
        if (request.getName() != null) {
            role.setName(request.getName());
        }
        if (request.getLevel() != null) {
            role.setLevel(request.getLevel());
        }
        if (request.getDescription() != null) {
            role.setDescription(request.getDescription());
        }
        
        roleRepository.updateById(role);
        
        // 更新权限
        if (request.getPermissions() != null) {
            assignPermissionsInternal(id, request.getPermissions());
        }
        
        log.info("更新角色成功: {}", role.getSlug());
        
        Long userCount = roleRepository.countUsersByRoleId(id);
        List<String> permissionSlugs = permissionService.getPermissionSlugsByRoleId(id);
        
        return toDTO(role, userCount, permissionSlugs);
    }
    
    @Override
    @Transactional
    public void deleteRole(Long id) {
        Role role = roleRepository.findById(id);
        if (role == null) {
            throw new BusinessException(404, "角色不存在");
        }
        
        // 不能删除超级管理员角色
        if (SUPER_ADMIN_SLUG.equals(role.getSlug())) {
            throw new BusinessException(403, "不能删除超级管理员角色");
        }
        
        // 检查是否有用户
        if (roleRepository.hasUsers(id)) {
            throw new BusinessException(400, "该角色下有用户，无法删除");
        }
        
        // 删除角色权限关联（通过MyBatis-Plus的级联删除应该会自动处理）
        roleRepository.deleteById(id);
        
        log.info("删除角色成功: {}", role.getSlug());
    }
    
    @Override
    public List<String> getRolePermissions(Long id) {
        Role role = roleRepository.findById(id);
        if (role == null) {
            throw new BusinessException(404, "角色不存在");
        }
        
        return permissionService.getPermissionSlugsByRoleId(id);
    }
    
    @Override
    @Transactional
    public void assignPermissions(Long roleId, AssignPermissionsRequest request) {
        Role role = roleRepository.findById(roleId);
        if (role == null) {
            throw new BusinessException(404, "角色不存在");
        }
        
        assignPermissionsInternal(roleId, request.getPermissions());
        log.info("分配权限成功: role={}, permissions={}", role.getSlug(), request.getPermissions());
    }
    
    @Override
    public boolean existsBySlug(String slug) {
        return roleRepository.existsBySlug(slug);
    }
    
    @Override
    public boolean existsBySlugAndIdNot(String slug, Long excludeId) {
        return roleRepository.existsBySlugAndIdNot(slug, excludeId);
    }
    
    @Override
    public RoleDTO getRoleBySlug(String slug) {
        Role role = roleRepository.findBySlug(slug);
        if (role == null) {
            throw new BusinessException(404, "角色不存在");
        }
        
        Long userCount = roleRepository.countUsersByRoleId(role.getId());
        List<String> permissionSlugs = permissionService.getPermissionSlugsByRoleId(role.getId());
        
        return toDTO(role, userCount, permissionSlugs);
    }
    
    /**
     * 内部方法：分配权限
     */
    private void assignPermissionsInternal(Long roleId, List<String> permissionSlugs) {
        // 获取权限ID列表
        Set<Long> permissionIds = permissionService.getPermissionIdsBySlugs(permissionSlugs);
        
        // 删除旧关联
        // 注意：需要通过中间表删除，这里使用原生SQL
        // INSERT INTO role_permissions (role_id, permission_id) VALUES ... ON DUPLICATE KEY UPDATE ...
        
        // 先删除旧关联
        // INSERT INTO role_permissions (role_id, permission_id) SELECT ... WHERE NOT EXISTS
        
        // 使用MyBatis-Plus的关联操作
        // 这里需要直接操作中间表，使用Repository的原生SQL
        
        // 清空角色的权限
        // 然后重新插入
        roleRepository.clearRolePermissions(roleId);
        
        // 插入新关联
        if (!permissionIds.isEmpty()) {
            roleRepository.insertRolePermissions(roleId, new ArrayList<>(permissionIds));
        }
    }
    
    /**
     * 转换为DTO
     */
    private RoleDTO toDTO(Role role, Long userCount, List<String> permissionSlugs) {
        return RoleDTO.builder()
                .id(role.getId())
                .name(role.getName())
                .code(role.getSlug())
                .level(role.getLevel())
                .description(role.getDescription())
                .userCount(userCount)
                .createTime(role.getCreatedAt())
                .permissions(permissionSlugs)
                .build();
    }
}
