package shop.alien.dining.util;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import shop.alien.util.common.JwtUtil;

import javax.servlet.http.HttpServletRequest;

/**
 * Token 工具类
 * 用于统一处理 token 的获取和解析
 *
 * @author ssk
 * @version 1.0
 * @date 2024/12/4
 */
@Slf4j
public class TokenUtil {

    /**
     * 去除 token 中的 "Bearer " 前缀
     *
     * @param token 原始 token 字符串
     * @return 去除前缀后的 token
     */
    private static String removeBearerPrefix(String token) {
        if (StringUtils.isBlank(token)) {
            return token;
        }
        // 去除首尾空格
        token = token.trim();
        
        // 去除 "Bearer " 前缀（不区分大小写）
        if (token.length() > 7 && token.substring(0, 7).equalsIgnoreCase("Bearer ")) {
            token = token.substring(7).trim();
        }
        
        return token;
    }

    /**
     * 从请求头获取当前用户信息
     * 兼容新的 token 格式（包含 openid）和旧格式
     *
     * @return 用户信息 JSONObject，包含 userId、openid、phone、userName 等，如果获取失败返回 null
     */
    public static JSONObject getCurrentUserInfo() {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes == null) {
                return null;
            }

            HttpServletRequest request = attributes.getRequest();
            String token = request.getHeader("Authorization");
            
            if (StringUtils.isBlank(token)) {
                return null;
            }

            // 去除 "Bearer " 前缀
            token = removeBearerPrefix(token);
            
            if (StringUtils.isBlank(token)) {
                log.warn("Token 去除前缀后为空");
                return null;
            }

            // 解析 token，验证格式和签名（与 verifyToken 方法保持一致）
            io.jsonwebtoken.Claims claims = JwtUtil.parseJWT(token);
            
            // 从 token 中提取用户信息（与 verifyToken 方法保持一致）
            String sub = claims.get("sub").toString();
            JSONObject userInfo = JSONObject.parseObject(sub);
            
            return userInfo;
        } catch (io.jsonwebtoken.ExpiredJwtException e) {
            log.warn("Token 已过期: {}", e.getMessage());
            return null;
        } catch (io.jsonwebtoken.MalformedJwtException e) {
            log.error("Token 格式错误: {}", e.getMessage());
            return null;
        } catch (io.jsonwebtoken.SignatureException e) {
            log.error("Token 签名验证失败: {}", e.getMessage());
            return null;
        } catch (Exception e) {
            log.warn("获取当前用户信息失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 获取当前用户ID
     *
     * @return 用户ID，如果获取失败返回 null
     */
    public static Integer getCurrentUserId() {
        JSONObject userInfo = getCurrentUserInfo();
        if (userInfo == null) {
            log.debug("getCurrentUserInfo() 返回 null，无法获取 userId");
            return null;
        }
        
        try {
            String userIdStr = userInfo.getString("userId");
            if (StringUtils.isBlank(userIdStr)) {
                log.warn("Token 中的 userId 字段为空或不存在，userInfo keys: {}", userInfo.keySet());
                return null;
            }
            Integer userId = Integer.parseInt(userIdStr);
            log.debug("成功获取 userId: {}", userId);
            return userId;
        } catch (NumberFormatException e) {
            log.error("解析 userId 失败，userIdStr: {}, 错误: {}", userInfo.getString("userId"), e.getMessage());
        } catch (Exception e) {
            log.error("获取 userId 时发生异常: {}", e.getMessage(), e);
        }
        
        return null;
    }

    /**
     * 获取当前用户的 openid
     *
     * @return openid，如果获取失败返回 null
     */
    public static String getCurrentUserOpenid() {
        JSONObject userInfo = getCurrentUserInfo();
        if (userInfo == null) {
            return null;
        }
        return userInfo.getString("openid");
    }

    /**
     * 获取当前用户的手机号
     *
     * @return 手机号，如果获取失败返回 null
     */
    public static String getCurrentUserPhone() {
        JSONObject userInfo = getCurrentUserInfo();
        if (userInfo == null) {
            return null;
        }
        return userInfo.getString("phone");
    }

    /**
     * 检查是否有有效的 token
     *
     * @return 如果有有效的 token 返回 true，否则返回 false
     */
    public static boolean hasValidToken() {
        JSONObject userInfo = getCurrentUserInfo();
        return userInfo != null && userInfo.containsKey("userId");
    }

    /**
     * 从 token 字符串直接解析用户信息（用于调试）
     *
     * @param token Token 字符串
     * @return 用户信息 JSONObject，如果解析失败返回 null
     */
    public static JSONObject parseToken(String token) {
        if (StringUtils.isBlank(token)) {
            log.warn("Token 字符串为空");
            return null;
        }

        try {
            // 去除 "Bearer " 前缀
            token = removeBearerPrefix(token);
            
            if (StringUtils.isBlank(token)) {
                log.warn("Token 去除前缀后为空");
                return null;
            }
            
            log.info("开始解析 token: {}", token.length() > 30 ? token.substring(0, 30) + "..." : token);

            // 解析 token
            io.jsonwebtoken.Claims claims = JwtUtil.parseJWT(token);
            if (claims == null) {
                log.warn("Token 解析失败，claims 为 null");
                return null;
            }

            log.info("Token claims keys: {}", claims.keySet());

            // 从 token 中提取用户信息
            Object subObj = claims.get("sub");
            if (subObj == null) {
                log.warn("Token claims 中没有 'sub' 字段");
                return null;
            }

            String sub;
            if (subObj instanceof String) {
                sub = (String) subObj;
            } else {
                sub = subObj.toString();
            }

            log.info("Token sub 内容: {}", sub);

            JSONObject userInfo = JSONObject.parseObject(sub);
            if (userInfo == null) {
                log.warn("解析 sub 为 JSONObject 返回 null");
                return null;
            }

            log.info("成功解析用户信息: userId={}, openid={}, phone={}, 所有 keys: {}",
                    userInfo.getString("userId"),
                    userInfo.getString("openid"),
                    userInfo.getString("phone"),
                    userInfo.keySet());

            return userInfo;
        } catch (Exception e) {
            log.error("解析 token 失败: {}, 异常类型: {}", e.getMessage(), e.getClass().getName(), e);
            return null;
        }
    }
}
