package com.stdproject.config;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.stdproject.entity.AppUser;
import com.stdproject.entity.AppRole;
import com.stdproject.entity.AppRoleUser;
import com.stdproject.entity.AppRoleMenu;
import com.stdproject.entity.AppMenu;
import com.stdproject.service.IAppUserService;
import com.stdproject.service.IAppRoleService;
import com.stdproject.service.IAppRoleUserService;
import com.stdproject.service.IAppRoleMenuService;
import com.stdproject.service.IAppMenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
import java.util.stream.Collectors;

/**
 * 自定义用户详情服务
 * 实现Spring Security的UserDetailsService接口
 *
 * @author StdProject
 */
@Slf4j
@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private IAppUserService appUserService;
    
    @Autowired
    private IAppRoleService appRoleService;
    
    @Autowired
    private IAppRoleUserService appRoleUserService;
    
    @Autowired
    private IAppRoleMenuService appRoleMenuService;
    
    @Autowired
    private IAppMenuService appMenuService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        log.debug("加载用户信息: {}", username);
        
        AppUser appUser = appUserService.findByUsername(username);
        if (appUser == null) {
            log.warn("用户不存在: {}", username);
            throw new UsernameNotFoundException("用户不存在: " + username);
        }
        
        // 检查用户状态
        if (!"1".equals(appUser.getStatus())) {
            log.warn("用户已被禁用: {}", username);
            throw new UsernameNotFoundException("用户已被禁用: " + username);
        }
        
        // 构建用户权限
        Collection<GrantedAuthority> authorities = buildUserAuthorities(appUser);
        
        return User.builder()
                .username(appUser.getUsername())
                .password(appUser.getPassword())
                .authorities(authorities)
                .accountExpired(false)
                .accountLocked(isAccountLocked(appUser))
                .credentialsExpired(isCredentialsExpired(appUser))
                .disabled(!"1".equals(appUser.getStatus()))
                .build();
    }

    /**
     * 构建用户权限
     *
     * @param appUser 用户信息
     * @return 权限集合
     */
    private Collection<GrantedAuthority> buildUserAuthorities(AppUser appUser) {
        Set<GrantedAuthority> authorities = new HashSet<>();
        
        try {
            // 根据用户类型添加基本角色权限
            if ("0".equals(appUser.getUsertype())) {
                authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
            } else {
                authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
            }
            
            // 查询用户的角色
            QueryWrapper<AppRoleUser> roleUserQuery = new QueryWrapper<>();
            roleUserQuery.eq("userid", appUser.getId());
            List<AppRoleUser> roleUsers = appRoleUserService.list(roleUserQuery);
            
            if (!roleUsers.isEmpty()) {
                // 获取角色ID列表
                List<String> roleIds = roleUsers.stream()
                    .map(AppRoleUser::getRoleid)
                    .collect(Collectors.toList());
                
                // 查询角色信息并添加角色权限
                List<AppRole> roles = appRoleService.listByIds(roleIds);
                for (AppRole role : roles) {
                    if ("1".equals(role.getIsvaild())) {
                        // 添加角色权限，格式：ROLE_角色编码
                        if (StringUtils.hasText(role.getRolecode())) {
                            authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getRolecode().toUpperCase()));
                        }
                    }
                }
                
                // 查询角色关联的菜单权限
                QueryWrapper<AppRoleMenu> roleMenuQuery = new QueryWrapper<>();
                roleMenuQuery.in("roleid", roleIds);
                List<AppRoleMenu> roleMenus = appRoleMenuService.list(roleMenuQuery);
                
                if (!roleMenus.isEmpty()) {
                    // 获取菜单ID列表
                    List<String> menuIds = roleMenus.stream()
                        .map(AppRoleMenu::getMenuid)
                        .distinct()
                        .collect(Collectors.toList());
                    
                    // 查询菜单信息并添加菜单权限
                    List<AppMenu> menus = appMenuService.listByIds(menuIds);
                    for (AppMenu menu : menus) {
                        if ("1".equals(menu.getIsdisplay()) && StringUtils.hasText(menu.getCode())) {
                            // 添加菜单权限，格式：菜单编码
                            authorities.add(new SimpleGrantedAuthority(menu.getCode()));
                            
                            // 根据菜单类型添加操作权限
                            String menuCode = menu.getCode();
                            if (StringUtils.hasText(menuCode)) {
                                // 为每个菜单添加基本操作权限
                                authorities.add(new SimpleGrantedAuthority(menuCode + ":list"));
                                authorities.add(new SimpleGrantedAuthority(menuCode + ":detail"));
                                
                                // 管理员拥有所有操作权限
                                if ("0".equals(appUser.getUsertype())) {
                                    authorities.add(new SimpleGrantedAuthority(menuCode + ":add"));
                                    authorities.add(new SimpleGrantedAuthority(menuCode + ":edit"));
                                    authorities.add(new SimpleGrantedAuthority(menuCode + ":delete"));
                                    authorities.add(new SimpleGrantedAuthority(menuCode + ":permission"));
                                }
                            }
                        }
                    }
                }
            }
            
            log.debug("用户 {} 的权限列表: {}", appUser.getUsername(), 
                authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()));
                
        } catch (Exception e) {
            log.error("构建用户权限失败: {}", e.getMessage(), e);
            // 发生异常时，至少保证基本角色权限
            authorities.clear();
            if ("0".equals(appUser.getUsertype())) {
                authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
            } else {
                authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
            }
        }
        
        return authorities;
    }

    /**
     * 检查账户是否被锁定
     *
     * @param appUser 用户信息
     * @return 是否被锁定
     */
    private boolean isAccountLocked(AppUser appUser) {
        // 检查登录失败锁定时间
        if (appUser.getFailedlocktime() != null) {
            // 如果锁定时间还未过期，则账户被锁定
            return appUser.getFailedlocktime().isAfter(java.time.LocalDateTime.now());
        }
        return false;
    }

    /**
     * 检查凭证是否过期
     *
     * @param appUser 用户信息
     * @return 是否过期
     */
    private boolean isCredentialsExpired(AppUser appUser) {
        // 检查密码是否过期
        if (appUser.getPwdresettime() != null && appUser.getPwdvalidperiod() != null) {
            java.time.LocalDateTime expireTime = appUser.getPwdresettime().plusDays(appUser.getPwdvalidperiod());
            return expireTime.isBefore(java.time.LocalDateTime.now());
        }
        return false;
    }
}