package com.qqchen.deploy.backend.framework.utils;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import nl.basjes.parse.useragent.UserAgent;
import nl.basjes.parse.useragent.UserAgentAnalyzer;
import org.springframework.stereotype.Component;

/**
 * User-Agent解析工具类
 * 
 * @author qqchen
 * @date 2025-11-20
 */
@Slf4j
@Component
public class UserAgentUtil {
    
    private static final UserAgentAnalyzer USER_AGENT_ANALYZER = UserAgentAnalyzer
            .newBuilder()
            .hideMatcherLoadStats()
            .withCache(10000)
            .build();
    
    /**
     * 解析User-Agent信息
     * 
     * @param userAgentString User-Agent字符串
     * @return 解析结果
     */
    public UserAgentInfo parseUserAgent(String userAgentString) {
        if (userAgentString == null || userAgentString.trim().isEmpty()) {
            return UserAgentInfo.unknown();
        }
        
        try {
            UserAgent userAgent = USER_AGENT_ANALYZER.parse(userAgentString);
            
            return UserAgentInfo.builder()
                    .browser(getBrowserName(userAgent))
                    .browserVersion(userAgent.getValue(UserAgent.AGENT_VERSION))
                    .os(getOperatingSystem(userAgent))
                    .osVersion(userAgent.getValue(UserAgent.OPERATING_SYSTEM_VERSION))
                    .deviceType(userAgent.getValue(UserAgent.DEVICE_CLASS))
                    .build();
        } catch (Exception e) {
            log.warn("解析User-Agent失败: {}", userAgentString, e);
            return UserAgentInfo.unknown();
        }
    }
    
    /**
     * 从HttpServletRequest获取真实IP地址
     * 
     * @param request HTTP请求
     * @return IP地址
     */
    public String getRealIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
            // 多级代理的情况，第一个IP为客户端真实IP
            int index = ip.indexOf(',');
            if (index != -1) {
                return ip.substring(0, index).trim();
            } else {
                return ip.trim();
            }
        }
        
        ip = request.getHeader("X-Real-IP");
        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
            return ip.trim();
        }
        
        ip = request.getHeader("Proxy-Client-IP");
        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
            return ip.trim();
        }
        
        ip = request.getHeader("WL-Proxy-Client-IP");
        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
            return ip.trim();
        }
        
        ip = request.getHeader("HTTP_CLIENT_IP");
        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
            return ip.trim();
        }
        
        ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
            return ip.trim();
        }
        
        // 如果都没有，返回request.getRemoteAddr()
        return request.getRemoteAddr();
    }
    
    /**
     * 获取浏览器名称
     */
    private String getBrowserName(UserAgent userAgent) {
        String agentName = userAgent.getValue(UserAgent.AGENT_NAME);
        String agentVersion = userAgent.getValue(UserAgent.AGENT_VERSION);
        
        if ("Unknown".equals(agentName)) {
            return "Unknown";
        }
        
        // 返回浏览器名称 + 主版本号
        if (agentVersion != null && !agentVersion.isEmpty() && !"Unknown".equals(agentVersion)) {
            String majorVersion = agentVersion.split("\\.")[0];
            return agentName + " " + majorVersion;
        }
        
        return agentName;
    }
    
    /**
     * 获取操作系统名称
     */
    private String getOperatingSystem(UserAgent userAgent) {
        String osName = userAgent.getValue(UserAgent.OPERATING_SYSTEM_NAME);
        String osVersion = userAgent.getValue(UserAgent.OPERATING_SYSTEM_VERSION);
        
        if ("Unknown".equals(osName)) {
            return "Unknown";
        }
        
        // Windows NT 版本号转换为友好名称
        if ("Windows NT".equals(osName) && osVersion != null && !osVersion.isEmpty()) {
            return convertWindowsNTVersion(osVersion);
        }
        
        // 返回操作系统名称 + 版本
        if (osVersion != null && !osVersion.isEmpty() && !"Unknown".equals(osVersion)) {
            return osName + " " + osVersion;
        }
        
        return osName;
    }
    
    /**
     * 将Windows NT版本号转换为用户友好的显示名称
     */
    private String convertWindowsNTVersion(String ntVersion) {
        switch (ntVersion) {
            case "10.0":
                return "Windows 10/11";  // Windows 10 和 11 都是 NT 10.0
            case "6.3":
                return "Windows 8.1";
            case "6.2":
                return "Windows 8";
            case "6.1":
                return "Windows 7";
            case "6.0":
                return "Windows Vista";
            case "5.2":
                return "Windows Server 2003";
            case "5.1":
                return "Windows XP";
            case "5.0":
                return "Windows 2000";
            default:
                return "Windows NT " + ntVersion;  // 未知版本保持原样
        }
    }
    
    /**
     * User-Agent解析结果
     */
    public static class UserAgentInfo {
        private String browser;
        private String browserVersion;
        private String os;
        private String osVersion;
        private String deviceType;
        
        public static UserAgentInfo unknown() {
            return UserAgentInfo.builder()
                    .browser("Unknown")
                    .browserVersion("Unknown")
                    .os("Unknown")
                    .osVersion("Unknown")
                    .deviceType("Unknown")
                    .build();
        }
        
        public static UserAgentInfoBuilder builder() {
            return new UserAgentInfoBuilder();
        }
        
        // Getters
        public String getBrowser() { return browser; }
        public String getBrowserVersion() { return browserVersion; }
        public String getOs() { return os; }
        public String getOsVersion() { return osVersion; }
        public String getDeviceType() { return deviceType; }
        
        // Builder
        public static class UserAgentInfoBuilder {
            private String browser;
            private String browserVersion;
            private String os;
            private String osVersion;
            private String deviceType;
            
            public UserAgentInfoBuilder browser(String browser) {
                this.browser = browser;
                return this;
            }
            
            public UserAgentInfoBuilder browserVersion(String browserVersion) {
                this.browserVersion = browserVersion;
                return this;
            }
            
            public UserAgentInfoBuilder os(String os) {
                this.os = os;
                return this;
            }
            
            public UserAgentInfoBuilder osVersion(String osVersion) {
                this.osVersion = osVersion;
                return this;
            }
            
            public UserAgentInfoBuilder deviceType(String deviceType) {
                this.deviceType = deviceType;
                return this;
            }
            
            public UserAgentInfo build() {
                UserAgentInfo info = new UserAgentInfo();
                info.browser = this.browser;
                info.browserVersion = this.browserVersion;
                info.os = this.os;
                info.osVersion = this.osVersion;
                info.deviceType = this.deviceType;
                return info;
            }
        }
    }
}
