package com.emotion.interceptor;

import com.emotion.service.AuthService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.stomp.StompCommand;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.messaging.support.MessageHeaderAccessor;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.security.Principal;
import java.util.Collections;

/**
 * WebSocket认证拦截器
 * 用于在WebSocket连接时验证用户身份
 * 
 * @author huazhongmin
 * @date 2025-07-24
 */
@Slf4j
@Component
public class WebSocketAuthInterceptor implements ChannelInterceptor {

    @Autowired
    private AuthService authService;

    @Override
    public Message<?> preSend(Message<?> message, MessageChannel channel) {
        StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);

        if (accessor != null && StompCommand.CONNECT.equals(accessor.getCommand())) {
            log.info("WebSocket CONNECT命令检测到，开始处理认证");
            // 处理WebSocket连接时的认证
            handleAuthentication(accessor);
        }

        return message;
    }

    /**
     * 处理WebSocket连接认证
     */
    private void handleAuthentication(StompHeaderAccessor accessor) {
        try {
            // 从连接头中获取token
            String authHeader = accessor.getFirstNativeHeader("Authorization");
            String userId = accessor.getFirstNativeHeader("X-User-Id");

            log.info("WebSocket连接认证开始: authHeader={}, userId={}, sessionId={}",
                    authHeader != null ? "Bearer ***" : null, userId, accessor.getSessionId());

            if (StringUtils.hasText(authHeader) && authHeader.startsWith("Bearer ")) {
                String token = authHeader.substring(7);
                log.info("提取到token: {}...", token.length() > 10 ? token.substring(0, 10) : token);

                // 验证token
                boolean isValidToken = authService.validateToken(token);
                log.info("Token验证结果: {}", isValidToken);

                if (isValidToken) {
                    String tokenUserId = authService.getUserIdFromToken(token);
                    String username = authService.getUsernameFromToken(token);

                    log.info("WebSocket token验证成功: userId={}, username={}", tokenUserId, username);

                    // 创建认证对象
                    Authentication authentication = new UsernamePasswordAuthenticationToken(
                            tokenUserId,
                            null,
                            Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"))
                    );

                    // 设置用户认证信息
                    accessor.setUser(authentication);

                    // 设置会话属性
                    if (accessor.getSessionAttributes() != null) {
                        accessor.getSessionAttributes().put("userId", tokenUserId);
                        accessor.getSessionAttributes().put("username", username);
                        accessor.getSessionAttributes().put("authenticated", true);
                    }

                    log.info("WebSocket认证用户设置完成: principal={}", authentication.getName());

                } else {
                    log.warn("WebSocket token验证失败: token无效或已过期");
                    // token无效，但不阻止连接，作为访客处理
                    handleGuestUser(accessor, userId);
                }
            } else {
                log.info("WebSocket连接无token或格式错误，作为访客处理: userId={}", userId);
                // 无token，作为访客处理
                handleGuestUser(accessor, userId);
            }

        } catch (Exception e) {
            log.error("WebSocket认证处理失败", e);
            // 认证失败，作为访客处理
            handleGuestUser(accessor, accessor.getFirstNativeHeader("X-User-Id"));
        }
    }

    /**
     * 处理访客用户
     */
    private void handleGuestUser(StompHeaderAccessor accessor, String userId) {
        String guestId = StringUtils.hasText(userId) ? userId : "guest_" + System.currentTimeMillis();
        
        log.info("设置访客用户: guestId={}", guestId);
        
        // 创建访客认证对象
        Authentication guestAuth = new UsernamePasswordAuthenticationToken(
                guestId, 
                null, 
                Collections.singletonList(new SimpleGrantedAuthority("ROLE_GUEST"))
        );
        
        accessor.setUser(guestAuth);
        
        // 设置会话属性
        if (accessor.getSessionAttributes() != null) {
            accessor.getSessionAttributes().put("userId", guestId);
            accessor.getSessionAttributes().put("username", guestId);
            accessor.getSessionAttributes().put("authenticated", false);
        }
    }
}
