package cn.van.business.controller.login;

import cn.van.business.model.ApiResponse;
import cn.van.business.model.user.LoginRequest;
import cn.van.business.model.user.LoginResponse;
import cn.van.business.service.CaptchaService;
import cn.van.business.util.JwtUtils;
import cn.van.business.util.WXUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.web.bind.annotation.*;

import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/auth")
public class AuthController {

    private static final Logger logger = LoggerFactory.getLogger(AuthController.class);


    private final CaptchaService captchaService;
    private final JwtUtils jwtUtils;
    private final AuthenticationManager authenticationManager;
    private final StringRedisTemplate redisTemplate;

    public AuthController(CaptchaService captchaService, JwtUtils jwtUtils, AuthenticationManager authenticationManager, StringRedisTemplate redisTemplate) {
        this.captchaService = captchaService;
        this.jwtUtils = jwtUtils;
        this.authenticationManager = authenticationManager;
        this.redisTemplate = redisTemplate;
    }

    private static final String USER_TOKEN_PREFIX = "user:token:";

    @PostMapping("/login")
    public ApiResponse login(@RequestBody LoginRequest request) {
        logger.info("用户登录");
        logger.info("用户名：{}", request.getUsername());
        logger.info("密码：{}", request.getPassword());
        logger.info("验证码：{}", request.getCaptcha());
        logger.info("生成的验证码：{}", request.getGeneratedCaptcha());
        // 1. 基础校验
        if (StringUtils.isBlank(request.getUsername()) || StringUtils.isBlank(request.getPassword())) {
            logger.error("用户名或密码不能为空");
            return ApiResponse.badRequest();
        }

        // 2. 验证码校验
        if (!captchaService.validateCaptcha(request.getCaptcha(), request.getGeneratedCaptcha())) {
            logger.error("验证码错误");
            return ApiResponse.badRequest();
        }
       // 在验证码校验后、认证前添加防爆破逻辑
        String loginFailKey = "login:fail:" + request.getUsername();
        Long failCount = redisTemplate.opsForValue().increment(loginFailKey);
        if (failCount != null && failCount > 5) {
            logger.error("尝试次数过多，请稍后再试");
            return ApiResponse.badRequest();
        }else {
            redisTemplate.expire(loginFailKey, 5, TimeUnit.MINUTES);
        }

        // 3. 用户认证（Spring Security 标准流程）
        logger.info("3. 用户认证（Spring Security 标准流程）");
        try {
            Authentication authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()));
        } catch (Exception e) {
            logger.error("用户认证失败：{}", e.getMessage());
        }

        // 4. 生成 JWT Token
        logger.info("用户认证成功");
        String token = jwtUtils.generateToken(request.getUsername());
        String refreshToken = generateRefreshToken(request.getUsername());
        logger.info("生成 JWT Token：{}", token);

        // 5. 存入 Redis
        saveUserToken(request.getUsername(), token, jwtUtils.getExpiration(token));

        // 6. 构造响应
        LoginResponse response = new LoginResponse();
        response.setToken(token);
        response.setRefreshToken(refreshToken);
        response.setUsername(request.getUsername());

        return ApiResponse.success(response);
    }


    @PostMapping("/logout")
    public ApiResponse logout(@RequestHeader("Authorization") String token) {
        String actualToken = token.startsWith("Bearer ") ? token.substring(7) : token;
        String username = jwtUtils.extractUsername(actualToken);
        String userKey = USER_TOKEN_PREFIX + username;

        // 从 Redis 删除用户 Token
        redisTemplate.delete(userKey);

        // 添加 Token 到黑名单
        addToBlacklist(actualToken, jwtUtils.getRemainingExpirationTime(actualToken));

        return ApiResponse.success();
    }


    @GetMapping("/captcha")
    public ApiResponse<String> getCaptcha() throws Exception {
        logger.info("获取验证码");
        String captchaImage = captchaService.generateCaptchaImage();
        return ApiResponse.success(captchaImage);
    }

    /**
     * 将用户 Token 存入 Redis，并设置相同有效期
     */
    private void saveUserToken(String username, String token, long expiration) {
        String key = USER_TOKEN_PREFIX + username;
        redisTemplate.opsForValue().set(key, token, expiration, TimeUnit.MILLISECONDS);
    }

    /**
     * 将 Token 加入黑名单
     */
    private void addToBlacklist(String token, long remainingTime) {
        String blacklistKey = "blacklist:token:" + token;
        redisTemplate.opsForValue().set(blacklistKey, "invalid", remainingTime, TimeUnit.MILLISECONDS);
    }

    /**
     * 生成刷新 Token（Refresh Token）
     */
    private String generateRefreshToken(String username) {
        return jwtUtils.generateToken(username);
    }

}
