package com.zhentao.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zhentao.entity.AdminUser;
import com.zhentao.entity.AdminUserRole;
import com.zhentao.entity.Role;
import com.zhentao.mapper.AdminUserMapper;
import com.zhentao.mapper.AdminUserRoleMapper;
import com.zhentao.mapper.RoleMapper;
import com.zhentao.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 用户服务实现
 */
@Service
public class UserServiceImpl implements UserService {
    
    @Autowired
    private AdminUserMapper adminUserMapper;
    
    @Autowired
    private RoleMapper roleMapper;
    
    @Autowired
    private AdminUserRoleMapper adminUserRoleMapper;
    
    @Override
    @Transactional
    public AdminUser register(AdminUser user, Integer roleId) {
        // 检查用户名是否已存在
        QueryWrapper<AdminUser> wrapper = new QueryWrapper<>();
        wrapper.eq("username", user.getUsername());
        AdminUser existUser = adminUserMapper.selectOne(wrapper);
        if (existUser != null) {
            throw new RuntimeException("用户名已存在");
        }
        
        // 生成盐并加密密码：MD5(密码+盐)
        String salt = generateSalt();
        String encryptedPassword = encryptPassword(user.getPassword(), salt);
        
        // 设置用户信息
        user.setPassword(encryptedPassword);
        user.setSalt(salt);
        user.setStatus(1); // 默认启用
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        
        // 保存用户
        adminUserMapper.insert(user);
        
        // 分配角色：如果未指定角色，则分配默认的普通管理员角色
        if (roleId == null) {
            // 查询普通管理员角色ID（role_code = 'ADMIN'）
            QueryWrapper<Role> roleWrapper = new QueryWrapper<>();
            roleWrapper.eq("role_code", "ADMIN");
            Role defaultRole = roleMapper.selectOne(roleWrapper);
            if (defaultRole != null) {
                roleId = defaultRole.getId();
            }
        }
        
        // 创建用户角色关联
        if (roleId != null) {
            AdminUserRole adminUserRole = new AdminUserRole();
            adminUserRole.setUserId(user.getId());
            adminUserRole.setRoleId(roleId);
            adminUserRole.setCreateTime(new Date());
            adminUserRoleMapper.insert(adminUserRole);
        }
        
        // 清除密码和盐
        user.setPassword(null);
        user.setSalt(null);
        
        return user;
    }
    
    @Override
    public Page<AdminUser> getUserList(Integer pageNum, Integer pageSize, String keyword) {
        Page<AdminUser> page = new Page<>(pageNum, pageSize);
        QueryWrapper<AdminUser> wrapper = new QueryWrapper<>();
        
        if (StringUtils.hasText(keyword)) {
            wrapper.and(w -> w.like("username", keyword)
                    .or().like("real_name", keyword)
                    .or().like("phone", keyword));
        }
        
        wrapper.orderByDesc("create_time");
        
        // 查询时排除密码和盐
        Page<AdminUser> result = adminUserMapper.selectPage(page, wrapper);
        result.getRecords().forEach(u -> {
            u.setPassword(null);
            u.setSalt(null);
        });
        
        return result;
    }
    
    @Override
    public AdminUser getUserById(Integer userId) {
        AdminUser user = adminUserMapper.selectById(userId);
        if (user != null) {
            user.setPassword(null);
            user.setSalt(null);
        }
        return user;
    }
    
    @Override
    public boolean updateUser(AdminUser user) {
        user.setUpdateTime(new Date());
        // 如果更新了密码，需要重新加密：MD5(密码+盐)
        if (StringUtils.hasText(user.getPassword())) {
            String salt = generateSalt();
            String encryptedPassword = encryptPassword(user.getPassword(), salt);
            user.setPassword(encryptedPassword);
            user.setSalt(salt);
        } else {
            // 不更新密码时，清除密码字段
            user.setPassword(null);
            user.setSalt(null);
        }
        return adminUserMapper.updateById(user) > 0;
    }
    
    @Override
    @Transactional
    public boolean deleteUser(Integer userId) {
        // 删除用户角色关联
        adminUserRoleMapper.deleteByUserId(userId);
        // 删除用户
        return adminUserMapper.deleteById(userId) > 0;
    }
    
    @Override
    public List<Role> getUserRoles(Integer userId) {
        List<Integer> roleIds = adminUserRoleMapper.selectRoleIdsByUserId(userId);
        if (roleIds.isEmpty()) {
            return Collections.emptyList();
        }
        return roleMapper.selectBatchIds(roleIds);
    }
    
    @Override
    @Transactional
    public boolean assignRoles(Integer userId, List<Integer> roleIds) {
        // 删除原有角色
        adminUserRoleMapper.deleteByUserId(userId);
        
        // 分配新角色
        if (roleIds != null && !roleIds.isEmpty()) {
            Date now = new Date();
            for (Integer roleId : roleIds) {
                AdminUserRole adminUserRole = new AdminUserRole();
                adminUserRole.setUserId(userId);
                adminUserRole.setRoleId(roleId);
                adminUserRole.setCreateTime(now);
                adminUserRoleMapper.insert(adminUserRole);
            }
        }
        
        return true;
    }
    
    @Override
    public boolean hasRole(Integer userId, String roleCode) {
        List<Role> roles = getUserRoles(userId);
        return roles.stream().anyMatch(r -> roleCode.equals(r.getRoleCode()));
    }
    
    @Override
    public boolean isSuperAdmin(Integer userId) {
        return hasRole(userId, "SUPER_ADMIN");
    }
    
    /**
     * 生成随机盐
     */
    private String generateSalt() {
        return UUID.randomUUID().toString().replace("-", "").substring(0, 16);
    }
    
    /**
     * 密码加密：MD5(密码+盐)
     */
    private String encryptPassword(String password, String salt) {
        String passwordWithSalt = password + salt;
        return DigestUtils.md5DigestAsHex(passwordWithSalt.getBytes(StandardCharsets.UTF_8));
    }
}

