package http

import (
	"net"
	"testing"
)

func TestValidateDomain_EmptyAllowed(t *testing.T) {
	if err := validateDomain("example.com", nil); err != nil {
		t.Fatalf("empty list should allow all: %v", err)
	}
}

func TestValidateDomain_Allowed(t *testing.T) {
	if err := validateDomain("api.example.com", []string{"api.example.com"}); err != nil {
		t.Fatalf("should be allowed: %v", err)
	}
}

func TestValidateDomain_Denied(t *testing.T) {
	if err := validateDomain("evil.com", []string{"api.example.com"}); err == nil {
		t.Fatal("should be denied")
	}
}

func TestValidateDomain_CaseInsensitive(t *testing.T) {
	if err := validateDomain("API.Example.COM", []string{"api.example.com"}); err != nil {
		t.Fatalf("should be case-insensitive: %v", err)
	}
}

func TestRejectInternalHost_Localhost(t *testing.T) {
	if err := rejectInternalHost("localhost"); err == nil {
		t.Fatal("localhost should be blocked")
	}
}

func TestRejectInternalHost_Loopback(t *testing.T) {
	if err := rejectInternalHost("127.0.0.1"); err == nil {
		t.Fatal("loopback should be blocked")
	}
}

func TestRejectInternalHost_IPv6Loopback(t *testing.T) {
	if err := rejectInternalHost("::1"); err == nil {
		t.Fatal("IPv6 loopback should be blocked")
	}
}

func TestRejectInternalHost_PrivateA(t *testing.T) {
	if err := rejectInternalHost("10.0.0.1"); err == nil {
		t.Fatal("10.x should be blocked")
	}
}

func TestRejectInternalHost_PrivateB(t *testing.T) {
	if err := rejectInternalHost("172.16.0.1"); err == nil {
		t.Fatal("172.16.x should be blocked")
	}
}

func TestRejectInternalHost_PrivateC(t *testing.T) {
	if err := rejectInternalHost("192.168.1.1"); err == nil {
		t.Fatal("192.168.x should be blocked")
	}
}

func TestRejectInternalHost_LinkLocal(t *testing.T) {
	if err := rejectInternalHost("169.254.1.1"); err == nil {
		t.Fatal("link-local should be blocked")
	}
}

func TestRejectInternalHost_Metadata(t *testing.T) {
	if err := rejectInternalHost("169.254.169.254"); err == nil {
		t.Fatal("metadata IP should be blocked")
	}
}

func TestRejectInternalHost_PublicIP(t *testing.T) {
	if err := rejectInternalHost("8.8.8.8"); err != nil {
		t.Fatalf("public IP should be allowed: %v", err)
	}
}

func TestIsPrivateIP(t *testing.T) {
	cases := []struct {
		ip   string
		want bool
	}{
		{"127.0.0.1", true},
		{"10.0.0.1", true},
		{"172.16.0.1", true},
		{"192.168.0.1", true},
		{"169.254.169.254", true},
		{"8.8.8.8", false},
		{"1.1.1.1", false},
	}
	for _, c := range cases {
		ip := net.ParseIP(c.ip)
		got := isPrivateIP(ip)
		if got != c.want {
			t.Errorf("isPrivateIP(%s) = %v, want %v", c.ip, got, c.want)
		}
	}
}

func TestValidateURL_Valid(t *testing.T) {
	if err := validateURL("https://example.com/api", nil); err != nil {
		t.Fatalf("public URL should pass: %v", err)
	}
}

func TestValidateURL_InternalIP(t *testing.T) {
	if err := validateURL("http://127.0.0.1:8080/admin", nil); err == nil {
		t.Fatal("internal IP in URL should be blocked")
	}
}

func TestValidateURL_NoHost(t *testing.T) {
	if err := validateURL("file:///etc/passwd", nil); err == nil {
		t.Fatal("URL with no host should be rejected")
	}
}
