package egress

import (
	"errors"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"strings"
)

var ErrCrossOriginRedirect = errors.New("extension egress cross-origin redirect denied")

func normalizedHTTPSOrigin(value *url.URL) (string, error) {
	if value == nil || !strings.EqualFold(value.Scheme, "https") ||
		value.Host == "" || value.User != nil {
		return "", errors.New("extension egress origin must be a credential-free HTTPS origin")
	}
	host := strings.ToLower(value.Hostname())
	if host == "" {
		return "", errors.New("extension egress origin host is required")
	}
	port := value.Port()
	if port == "" {
		port = "443"
	}
	return "https://" + net.JoinHostPort(host, port), nil
}

func checkRedirectForOrigin(origin, basePath string) func(*http.Request, []*http.Request) error {
	return func(request *http.Request, via []*http.Request) error {
		if len(via) >= 10 {
			return errors.New("extension egress redirect limit exceeded")
		}
		candidate, err := normalizedHTTPSOrigin(request.URL)
		if err != nil || candidate != origin {
			return fmt.Errorf("%w", ErrCrossOriginRedirect)
		}
		if !pathWithinBase(request.URL.EscapedPath(), basePath) {
			return fmt.Errorf("%w: redirect escaped fixed base path", ErrDestinationDenied)
		}
		if len(via) == 0 || request.Method != via[0].Method {
			return fmt.Errorf("%w: redirect changed bound method", ErrDestinationDenied)
		}
		return nil
	}
}
