package com.aiotagro.cattletrade.business.service.impl;

import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.stp.SaLoginConfig;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.aiotagro.cattletrade.business.dto.LoginDto;
import com.aiotagro.cattletrade.business.entity.SysMenu;
import com.aiotagro.cattletrade.business.entity.SysRole;
import com.aiotagro.cattletrade.business.entity.SysUser;
import com.aiotagro.cattletrade.business.mapper.SysMenuMapper;
import com.aiotagro.cattletrade.business.mapper.SysRoleMapper;
import com.aiotagro.cattletrade.business.mapper.SysUserMapper;
import com.aiotagro.cattletrade.business.mapper.SysUserMenuMapper;
import com.aiotagro.cattletrade.business.service.LoginService;
import com.aiotagro.cattletrade.business.service.TencentSmsCodeService;
import com.aiotagro.common.core.constant.Constants;
import com.aiotagro.common.core.constant.RoleConstants;
import com.aiotagro.common.core.exception.ServiceException;
import com.aiotagro.common.core.utils.SecurityUtil;
import com.aiotagro.common.core.web.domain.AjaxResult;
import com.aiotagro.common.redis.service.RedisService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import com.aiotagro.common.core.utils.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class LoginServiceImpl implements LoginService {

    @Resource
    private RedisService redisService;

    @Resource
    SysUserMapper userMapper;

    @Resource
    TencentSmsCodeService tencentSmsCodeService;

    @Resource
    SysMenuMapper menuMapper;

    @Resource
    SysRoleMapper roleMapper;

    @Resource
    SysUserMenuMapper sysUserMenuMapper;


    @Override
    public AjaxResult sendLoginSmsCode(String mobile) {
        // 临时跳过Redis验证码存储，直接返回成功
        SysUser user = userMapper.selectOne(new QueryWrapper<SysUser>().lambda().eq(SysUser::getMobile, mobile).eq(SysUser::getIsDelete, 0));
        if (null == user || user.getIsDelete() == 1) {
            return AjaxResult.error("手机号不存在!");
        }
        if (user.getStatus() == 0) {
            return AjaxResult.error("手机号已被禁用!");
        }
        
        log.warn("短信验证码发送暂时跳过Redis存储，直接返回成功");
        return AjaxResult.success("验证码发送成功");
    }

    @Override
    public AjaxResult login(LoginDto dto) {
        log.info(dto.toString());
        SysUser user = userMapper.selectOne(new QueryWrapper<SysUser>().lambda().eq(SysUser::getMobile, dto.getMobile()).eq(SysUser::getIsDelete, 0));
        if (dto.getLoginType() == 0) {
            // 判断用户存不存在
            if (null == user || user.getIsDelete() == 1) {
                return AjaxResult.error("员工不存在!");
            }
            if (user.getStatus() == 0) {
                return AjaxResult.error("此账号已禁用!");
            }
            // 密码校验
            String passwordMd5 = DigestUtil.md5Hex(Constants.USER_PASSWORD_PREFIX + dto.getPassword());
            if (!passwordMd5.equals(user.getPassword())) {
                throw new ServiceException("密码错误!");
            }
        } else if (dto.getLoginType() == 1) {
            // 短信验证码校验 - 临时跳过Redis验证
            log.warn("短信验证码登录暂时跳过Redis验证，直接允许登录");
        }

        // 更新登录时间
        user.setLastLoginTime(new Date());
        userMapper.updateById(user);

        log.info(user.toString());
        // 登录成功，写入缓存数据并返回token值
        StpUtil.login(user.getId(), SaLoginConfig
                .setExtra("username", user.getName())
                .setExtra("userId", user.getId())
                .setExtra("mobile", user.getMobile())
                .setExtra("roleId", user.getRoleId())
        );
        
        // 存储角色ID到session
        StpUtil.getTokenSession().set("roleId", user.getRoleId());
        // 存储用户名与手机号到session，便于业务侧读取
        StpUtil.getTokenSession().set("username", user.getName());
        StpUtil.getTokenSession().set("mobile", user.getMobile());
        
        // 调试日志：验证TokenSession写入
        log.info("=== TokenSession 写入调试 ===");
        log.info("写入 username: {}", user.getName());
        log.info("写入 mobile: {}", user.getMobile());
        log.info("写入 roleId: {}", user.getRoleId());
        
        // 立即验证读取
        Object sessionUsername = StpUtil.getTokenSession().get("username");
        Object sessionMobile = StpUtil.getTokenSession().get("mobile");
        Object sessionRoleId = StpUtil.getTokenSession().get("roleId");
        log.info("验证读取 username: {}", sessionUsername);
        log.info("验证读取 mobile: {}", sessionMobile);
        log.info("验证读取 roleId: {}", sessionRoleId);
        
        // 查询用户权限列表（优先使用用户专属权限）
        List<String> permissions = queryUserPermissions(user.getId(), user.getRoleId());
        StpUtil.getTokenSession().set("permissions", permissions);
        
        // 查询用户角色信息
        SysRole role = roleMapper.selectById(user.getRoleId());
        String roleCode = role != null ? role.getName() : "";
        StpUtil.getTokenSession().set("roleCode", roleCode);
        
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("token", SaManager.getConfig().getTokenPrefix() + " " + StpUtil.getTokenValue());
        map.put("username", user.getName());
        map.put("userId", user.getId());
        map.put("mobile", user.getMobile());
        map.put("roleId", user.getRoleId());
        map.put("permissions", permissions);  // 返回权限列表
        return AjaxResult.success("登录成功", map);
    }

    @Override
    public AjaxResult getUserMenus() {
        Integer userId = SecurityUtil.getCurrentUserId();
        
        // 获取当前用户的角色ID
        SysUser user = userMapper.selectById(userId);
        if (user == null) {
            return AjaxResult.error("用户不存在");
        }
        
        // 菜单权限查询：优先使用用户专属菜单权限，否则使用角色菜单权限
        List<SysMenu> menus = queryUserMenus(userId, user.getRoleId());
        
        log.info("=== 用户 {} 菜单查询结果，菜单数量: {}", userId, menus.size());
        return AjaxResult.success("查询成功", menus);
    }

    @Override
    public AjaxResult getUserInfo() {
        SysUser user = userMapper.getUserInfoById(SecurityUtil.getCurrentUserId());
        return AjaxResult.success(user);
    }

    /**
     * 查询用户菜单权限（优先使用用户专属菜单权限）
     * 
     * @param userId 用户ID
     * @param roleId 角色ID
     * @return 菜单列表
     */
    private List<SysMenu> queryUserMenus(Integer userId, Integer roleId) {
        if (userId == null || roleId == null) {
            return Collections.emptyList();
        }
        
        // 1. 先查询用户专属菜单权限（只查询菜单，不查询操作按钮）
        List<SysMenu> userMenus = sysUserMenuMapper.selectMenusByUserId(userId);
        if (userMenus != null && !userMenus.isEmpty()) {
            // 过滤掉操作按钮（type=2），只保留菜单（type=0,1）
            List<SysMenu> filteredMenus = userMenus.stream()
                    .filter(menu -> menu.getType() != 2) // 排除操作按钮
                    .collect(Collectors.toList());
            
            if (!filteredMenus.isEmpty()) {
                log.info("=== 用户 {} 使用专属菜单权限，菜单数量: {}", userId, filteredMenus.size());
                return filteredMenus;
            }
        }
        
        // 2. 如果没有专属菜单权限，使用角色菜单权限
        if (roleId.equals(RoleConstants.SUPER_ADMIN_ROLE_ID)) {
            log.info("=== 超级管理员用户 {} 使用所有菜单权限（无专属菜单权限）", userId);
            return menuMapper.selectList(null);
        }
        
        // 3. 普通角色菜单权限
        log.info("=== 用户 {} 使用角色菜单权限，roleId: {}", userId, roleId);
        return menuMapper.queryMenusByUserId(userId);
    }

    /**
     * 查询用户权限列表（优先使用用户专属权限）
     * 
     * @param userId 用户ID
     * @param roleId 角色ID
     * @return 权限列表
     */
    private List<String> queryUserPermissions(Integer userId, Integer roleId) {
        if (userId == null || roleId == null) {
            return Collections.emptyList();
        }
        
        // 1. 先查询用户专属权限（优先于角色权限）
        List<SysMenu> userMenus = sysUserMenuMapper.selectMenusByUserId(userId);
        if (userMenus != null && !userMenus.isEmpty()) {
            log.info("=== 用户 {} 使用专属权限，权限数量: {}", userId, userMenus.size());
            return userMenus.stream()
                    .filter(menu -> StringUtils.isNotEmpty(menu.getAuthority()))
                    .map(SysMenu::getAuthority)
                    .distinct()
                    .collect(Collectors.toList());
        }
        
        // 2. 如果没有专属权限，使用角色权限
        if (roleId.equals(RoleConstants.SUPER_ADMIN_ROLE_ID)) {
            log.info("=== 超级管理员用户 {} 使用所有权限（无专属权限）", userId);
            return Collections.singletonList(RoleConstants.ALL_PERMISSION);
        }
        
        // 3. 普通角色权限
        log.info("=== 用户 {} 使用角色权限，roleId: {}", userId, roleId);
        List<SysMenu> roleMenus = menuMapper.selectMenusByRoleId(roleId);
        return roleMenus.stream()
                .filter(menu -> StringUtils.isNotEmpty(menu.getAuthority()))
                .map(SysMenu::getAuthority)
                .distinct()
                .collect(Collectors.toList());
    }

}
