package importer

import (
	"fmt"
	"net/url"
	"regexp"
	"strconv"
	"strings"

	"proxyrotator/internal/model"
)

var (
	// 匹配 host:port 格式
	hostPortRegex = regexp.MustCompile(`^([a-zA-Z0-9.-]+):(\d+)$`)
	// 匹配 user:pass@host:port 格式
	userPassHostPortRegex = regexp.MustCompile(`^([^:@]+):([^@]+)@([a-zA-Z0-9.-]+):(\d+)$`)
	// 匹配 host:port:user:pass 格式
	hostPortUserPassRegex = regexp.MustCompile(`^([a-zA-Z0-9.-]+):(\d+):([^:]+):(.+)$`)
)

// ParseProxyLine 解析单行代理格式
// 支持格式:
//   - host:port
//   - user:pass@host:port
//   - host:port:user:pass
//   - http://host:port
//   - http://user:pass@host:port
//   - socks5://host:port
//   - socks5://user:pass@host:port
func ParseProxyLine(raw string, protocolHint string) (*model.Proxy, error) {
	raw = strings.TrimSpace(raw)
	if raw == "" {
		return nil, fmt.Errorf("empty line")
	}

	// 尝试解析为 URL
	if strings.Contains(raw, "://") {
		return parseAsURL(raw)
	}

	// 尝试解析 host:port:user:pass 格式
	if matches := hostPortUserPassRegex.FindStringSubmatch(raw); matches != nil {
		port, err := strconv.Atoi(matches[2])
		if err != nil || port <= 0 || port >= 65536 {
			return nil, fmt.Errorf("invalid port: %s", matches[2])
		}

		protocol := inferProtocol(protocolHint, port)
		return &model.Proxy{
			Protocol: protocol,
			Host:     matches[1],
			Port:     port,
			Username: matches[3],
			Password: matches[4],
		}, nil
	}

	// 尝试解析 user:pass@host:port 格式
	if matches := userPassHostPortRegex.FindStringSubmatch(raw); matches != nil {
		port, err := strconv.Atoi(matches[4])
		if err != nil || port <= 0 || port >= 65536 {
			return nil, fmt.Errorf("invalid port: %s", matches[4])
		}

		protocol := inferProtocol(protocolHint, port)
		return &model.Proxy{
			Protocol: protocol,
			Host:     matches[3],
			Port:     port,
			Username: matches[1],
			Password: matches[2],
		}, nil
	}

	// 尝试解析 host:port 格式
	if matches := hostPortRegex.FindStringSubmatch(raw); matches != nil {
		port, err := strconv.Atoi(matches[2])
		if err != nil || port <= 0 || port >= 65536 {
			return nil, fmt.Errorf("invalid port: %s", matches[2])
		}

		protocol := inferProtocol(protocolHint, port)
		return &model.Proxy{
			Protocol: protocol,
			Host:     matches[1],
			Port:     port,
		}, nil
	}

	return nil, fmt.Errorf("unrecognized format")
}

// parseAsURL 解析 URL 格式的代理
func parseAsURL(raw string) (*model.Proxy, error) {
	u, err := url.Parse(raw)
	if err != nil {
		return nil, fmt.Errorf("invalid URL: %w", err)
	}

	var protocol model.ProxyProtocol
	switch strings.ToLower(u.Scheme) {
	case "http":
		protocol = model.ProtoHTTP
	case "https":
		protocol = model.ProtoHTTPS
	case "socks5":
		protocol = model.ProtoSOCKS5
	default:
		return nil, fmt.Errorf("unsupported protocol: %s", u.Scheme)
	}

	host := u.Hostname()
	if host == "" {
		return nil, fmt.Errorf("missing host")
	}

	portStr := u.Port()
	if portStr == "" {
		// 默认端口
		switch protocol {
		case model.ProtoHTTP:
			portStr = "80"
		case model.ProtoHTTPS:
			portStr = "443"
		case model.ProtoSOCKS5:
			portStr = "1080"
		}
	}

	port, err := strconv.Atoi(portStr)
	if err != nil || port <= 0 || port >= 65536 {
		return nil, fmt.Errorf("invalid port: %s", portStr)
	}

	var username, password string
	if u.User != nil {
		username = u.User.Username()
		password, _ = u.User.Password()
	}

	return &model.Proxy{
		Protocol: protocol,
		Host:     host,
		Port:     port,
		Username: username,
		Password: password,
	}, nil
}

// inferProtocol 根据提示和端口推断协议
func inferProtocol(hint string, port int) model.ProxyProtocol {
	switch strings.ToLower(hint) {
	case "http":
		return model.ProtoHTTP
	case "https":
		return model.ProtoHTTPS
	case "socks5":
		return model.ProtoSOCKS5
	}

	// 根据端口推断
	switch port {
	case 443:
		return model.ProtoHTTPS
	case 1080:
		return model.ProtoSOCKS5
	default:
		return model.ProtoHTTP
	}
}
