package com.competition.modules.sys.service;

import com.competition.common.enums.ErrorCode;
import com.competition.common.exception.BusinessException;
import com.competition.modules.sys.entity.SysTenant;
import com.competition.modules.sys.entity.SysUser;
import com.competition.security.util.JwtUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 认证服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AuthService {

    private final ISysUserService userService;
    private final ISysTenantService tenantService;
    private final JwtUtil jwtUtil;
    private final PasswordEncoder passwordEncoder;
    private final StringRedisTemplate redisTemplate;

    /**
     * 登录
     */
    public Map<String, Object> login(String username, String password, Long tenantId, String tenantCode) {
        log.info("开始登录，用户名：{}，租户ID：{}，租户编码：{}", username, tenantId, tenantCode);

        // 如果没有 tenantId 但有 tenantCode，通过编码查找租户
        if (tenantId == null && tenantCode != null && !tenantCode.isBlank()) {
            SysTenant tenantByCode = tenantService.getOne(
                    new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<SysTenant>()
                            .eq(SysTenant::getCode, tenantCode)
                            .eq(SysTenant::getValidState, 1), false);
            if (tenantByCode != null) {
                tenantId = tenantByCode.getId();
            }
        }

        // 查找用户
        SysUser user = userService.findByUsername(username, tenantId);
        if (user == null) {
            throw BusinessException.of(ErrorCode.UNAUTHORIZED, "用户名或密码错误");
        }

        // 验证密码
        if (!passwordEncoder.matches(password, user.getPassword())) {
            throw BusinessException.of(ErrorCode.UNAUTHORIZED, "用户名或密码错误");
        }

        // 验证用户状态
        if ("disabled".equals(user.getStatus())) {
            throw BusinessException.of(ErrorCode.FORBIDDEN, "账号已被禁用");
        }

        Long userTenantId = user.getTenantId();

        // 验证租户有效性
        SysTenant tenant = tenantService.getById(userTenantId);
        if (tenant == null) {
            throw BusinessException.of(ErrorCode.BAD_REQUEST, "租户不存在");
        }
        if (tenant.getValidState() != 1) {
            throw BusinessException.of(ErrorCode.BAD_REQUEST, "租户已失效");
        }

        // 获取角色和权限
        List<String> roles = userService.getRoles(user.getId());
        List<String> permissions = userService.getPermissions(user.getId());

        // 缓存到 Redis
        cacheUserAuth(user.getId(), roles, permissions);

        // 生成 JWT
        String token = jwtUtil.generateToken(user.getId(), user.getUsername(), userTenantId);

        // 构造返回
        Map<String, Object> userInfo = new LinkedHashMap<>();
        userInfo.put("id", user.getId());
        userInfo.put("username", user.getUsername());
        userInfo.put("nickname", user.getNickname());
        userInfo.put("email", user.getEmail());
        userInfo.put("avatar", user.getAvatar());
        userInfo.put("tenantId", userTenantId);
        userInfo.put("tenantCode", tenant.getCode());
        userInfo.put("roles", roles);
        userInfo.put("permissions", permissions);

        Map<String, Object> result = new LinkedHashMap<>();
        result.put("token", token);
        result.put("user", userInfo);

        log.info("登录成功，用户：{}，ID：{}", username, user.getId());
        return result;
    }

    /**
     * 获取当前用户信息
     */
    public Map<String, Object> getUserInfo(Long userId) {
        SysUser user = userService.getById(userId);
        if (user == null) {
            throw BusinessException.of(ErrorCode.UNAUTHORIZED, "用户不存在");
        }

        SysTenant tenant = tenantService.getById(user.getTenantId());

        List<String> roles = userService.getRoles(userId);
        List<String> permissions = userService.getPermissions(userId);

        Map<String, Object> result = new LinkedHashMap<>();
        result.put("id", user.getId());
        result.put("username", user.getUsername());
        result.put("nickname", user.getNickname());
        result.put("email", user.getEmail());
        result.put("avatar", user.getAvatar());
        result.put("tenantId", user.getTenantId());
        result.put("tenantCode", tenant != null ? tenant.getCode() : null);
        result.put("roles", roles);
        result.put("permissions", permissions);

        return result;
    }

    /**
     * 缓存用户角色和权限到 Redis（7天过期，与 JWT 一致）
     */
    private void cacheUserAuth(Long userId, List<String> roles, List<String> permissions) {
        try {
            String rolesKey = "user:roles:" + userId;
            String permsKey = "user:perms:" + userId;

            redisTemplate.delete(rolesKey);
            redisTemplate.delete(permsKey);

            if (!roles.isEmpty()) {
                redisTemplate.opsForSet().add(rolesKey, roles.toArray(new String[0]));
                redisTemplate.expire(rolesKey, 7, TimeUnit.DAYS);
            }
            if (!permissions.isEmpty()) {
                redisTemplate.opsForSet().add(permsKey, permissions.toArray(new String[0]));
                redisTemplate.expire(permsKey, 7, TimeUnit.DAYS);
            }
        } catch (Exception e) {
            log.warn("缓存用户权限到 Redis 失败：{}", e.getMessage());
            // Redis 不可用不阻断登录
        }
    }
}
