package httputil

import (
	"regexp"
	"strings"
)

func ParseUserAgent(ua string) string {
	if ua == "" {
		return "Unknown"
	}

	browser := parseBrowser(ua)
	os := parseOS(ua)

	if browser == "" && os == "" {
		return "Unknown"
	}
	if browser == "" {
		return os
	}
	if os == "" {
		return browser
	}

	return browser + " on " + os
}

func parseBrowser(ua string) string {
	if match := regexp.MustCompile(`Edg(?:e|A|iOS)?/(\d+)`).FindStringSubmatch(ua); match != nil {
		return "Edge " + match[1]
	}

	if match := regexp.MustCompile(`(?:OPR|Opera)[/ ](\d+)`).FindStringSubmatch(ua); match != nil {
		return "Opera " + match[1]
	}

	if match := regexp.MustCompile(`SamsungBrowser/(\d+)`).FindStringSubmatch(ua); match != nil {
		return "Samsung Browser " + match[1]
	}

	if strings.Contains(ua, "Chrome") && !strings.Contains(ua, "Chromium") {
		if match := regexp.MustCompile(`Chrome/(\d+)`).FindStringSubmatch(ua); match != nil {
			return "Chrome " + match[1]
		}
	}

	if match := regexp.MustCompile(`Chromium/(\d+)`).FindStringSubmatch(ua); match != nil {
		return "Chromium " + match[1]
	}

	if match := regexp.MustCompile(`Firefox/(\d+)`).FindStringSubmatch(ua); match != nil {
		return "Firefox " + match[1]
	}

	if strings.Contains(ua, "Safari") && !strings.Contains(ua, "Chrome") {
		if match := regexp.MustCompile(`Version/(\d+)`).FindStringSubmatch(ua); match != nil {
			return "Safari " + match[1]
		}
		return "Safari"
	}

	if match := regexp.MustCompile(`MSIE (\d+)`).FindStringSubmatch(ua); match != nil {
		return "Internet Explorer " + match[1]
	}
	if strings.Contains(ua, "Trident/") {
		if match := regexp.MustCompile(`rv:(\d+)`).FindStringSubmatch(ua); match != nil {
			return "Internet Explorer " + match[1]
		}
		return "Internet Explorer"
	}

	return ""
}

func parseOS(ua string) string {
	if strings.Contains(ua, "iPhone") {
		if match := regexp.MustCompile(`iPhone OS (\d+)[_\d]*`).FindStringSubmatch(ua); match != nil {
			return "iOS " + match[1]
		}
		return "iOS"
	}
	if strings.Contains(ua, "iPad") {
		if match := regexp.MustCompile(`CPU OS (\d+)[_\d]*`).FindStringSubmatch(ua); match != nil {
			return "iPadOS " + match[1]
		}
		return "iPadOS"
	}

	if match := regexp.MustCompile(`Android (\d+)`).FindStringSubmatch(ua); match != nil {
		return "Android " + match[1]
	}

	if strings.Contains(ua, "Windows") {
		if strings.Contains(ua, "Windows NT 10.0") {
			return "Windows 10/11"
		}
		if strings.Contains(ua, "Windows NT 6.3") {
			return "Windows 8.1"
		}
		if strings.Contains(ua, "Windows NT 6.2") {
			return "Windows 8"
		}
		if strings.Contains(ua, "Windows NT 6.1") {
			return "Windows 7"
		}
		if strings.Contains(ua, "Windows NT 6.0") {
			return "Windows Vista"
		}
		if strings.Contains(ua, "Windows NT 5.1") {
			return "Windows XP"
		}
		return "Windows"
	}

	if strings.Contains(ua, "Mac OS X") || strings.Contains(ua, "Macintosh") {
		if match := regexp.MustCompile(`Mac OS X (\d+)[_.](\d+)`).FindStringSubmatch(ua); match != nil {
			return "macOS " + match[1] + "." + match[2]
		}
		return "macOS"
	}

	if strings.Contains(ua, "Ubuntu") {
		return "Ubuntu"
	}
	if strings.Contains(ua, "Fedora") {
		return "Fedora"
	}
	if strings.Contains(ua, "Linux") {
		return "Linux"
	}

	if strings.Contains(ua, "CrOS") {
		return "Chrome OS"
	}

	return ""
}
