// Package loader provides interfaces and implementations for loading targets from various file formats.
package loader

import (
	"net"
	"net/url"
	"strings"
)

// Loader is the interface for loading targets from files.
type Loader interface {
	// Load reads targets from the file at path and returns validated, deduplicated URLs.
	Load(path string) (*LoadResult, error)
}

// LoadResult contains the targets and statistics from a load operation.
type LoadResult struct {
	Targets     []string // Normalized URLs ready for scanning
	TotalRows   int      // Total rows/lines read from file
	Filtered    int      // Rows filtered (status=Down, invalid URL, private IP)
	Duplicates  int      // Duplicate URLs removed
	InvalidURLs int      // URLs with invalid scheme or format
}

// isValidURL returns true if rawURL has an http or https scheme.
// If the URL has no scheme, it's considered invalid.
func isValidURL(rawURL string) bool {
	u, err := url.Parse(rawURL)
	if err != nil {
		return false
	}

	scheme := strings.ToLower(u.Scheme)
	return scheme == "http" || scheme == "https"
}

// isPrivateOrLocalhost returns true if the host is a private IP, loopback, or localhost.
// Handles IPv4 private ranges, IPv6 private ranges, and localhost variants.
func isPrivateOrLocalhost(host string) bool {
	// Strip port if present
	if strings.Contains(host, ":") {
		var err error
		host, _, err = net.SplitHostPort(host)
		if err != nil {
			// If SplitHostPort fails, try with the original host
			// (might be IPv6 without port)
		}
	}

	// Check for literal "localhost"
	if strings.ToLower(host) == "localhost" {
		return true
	}

	// Try to parse as IP
	ip := net.ParseIP(host)
	if ip == nil {
		// Not an IP address, assume it's a domain name
		// Only filter actual IP addresses, not domain names
		return false
	}

	// Use Go 1.17+ methods for private IP detection
	return ip.IsLoopback() || ip.IsPrivate()
}

// normalizeURL normalizes a URL for deduplication.
// Strips scheme (http://, https://), strips trailing slash, lowercases domain, strips www. prefix.
// This matches the database.NormalizeDomain() pattern for consistency.
func normalizeURL(rawURL string) string {
	// Strip scheme
	rawURL = strings.TrimPrefix(rawURL, "http://")
	rawURL = strings.TrimPrefix(rawURL, "https://")

	// Strip trailing slash
	rawURL = strings.TrimRight(rawURL, "/")

	// Parse to extract host
	// Since we stripped scheme, add a temporary one for parsing
	u, err := url.Parse("http://" + rawURL)
	if err != nil {
		// Fallback: just lowercase and strip www.
		rawURL = strings.ToLower(rawURL)
		rawURL = strings.TrimPrefix(rawURL, "www.")
		return rawURL
	}

	// Lowercase the host
	host := strings.ToLower(u.Host)

	// Strip www. prefix
	host = strings.TrimPrefix(host, "www.")

	// Reconstruct without scheme: host + path
	if u.Path == "" || u.Path == "/" {
		return host
	}

	return host + u.Path
}
