package origin

import "testing"

func TestCanonicalOrigin(t *testing.T) {
	tests := []struct {
		name string
		raw  string
		want string
		ok   bool
	}{
		{name: "http", raw: "http://127.0.0.1:4173", want: "http://127.0.0.1:4173", ok: true},
		{name: "https with trailing slash", raw: "https://app.example.com/", want: "https://app.example.com", ok: true},
		{name: "path not allowed", raw: "https://app.example.com/callback", ok: false},
		{name: "query not allowed", raw: "https://app.example.com?x=1", ok: false},
		{name: "unsupported scheme", raw: "ws://127.0.0.1:4173", ok: false},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, ok := CanonicalOrigin(tt.raw)
			if ok != tt.ok {
				t.Fatalf("CanonicalOrigin(%q) ok = %v, want %v", tt.raw, ok, tt.ok)
			}
			if got != tt.want {
				t.Fatalf("CanonicalOrigin(%q) = %q, want %q", tt.raw, got, tt.want)
			}
		})
	}
}

func TestLoadConfigFromEnv_DerivesAllowedOriginFromFrontendURL(t *testing.T) {
	t.Setenv("FRONTEND_URL", "http://127.0.0.1:4173")
	t.Setenv("CORS_ALLOWED_ORIGINS", "")
	t.Setenv("ALLOWED_ORIGINS", "")

	cfg := LoadConfigFromEnv()

	if !cfg.IsAllowedOrigin("http://127.0.0.1:4173") {
		t.Fatal("expected FRONTEND_URL to be allowed")
	}
}

func TestLoadConfigFromEnv_UsesConfiguredOriginsAndFrontendURL(t *testing.T) {
	t.Setenv("FRONTEND_URL", "http://127.0.0.1:4173")
	t.Setenv("CORS_ALLOWED_ORIGINS", "https://app.example.com, https://admin.example.com")
	t.Setenv("ALLOWED_ORIGINS", "")

	cfg := LoadConfigFromEnv()

	for _, raw := range []string{
		"http://127.0.0.1:4173",
		"https://app.example.com",
		"https://admin.example.com",
	} {
		if !cfg.IsAllowedOrigin(raw) {
			t.Fatalf("expected %q to be allowed", raw)
		}
	}
}

func TestLoadConfigFromEnv_UsesDeprecatedAlias(t *testing.T) {
	t.Setenv("FRONTEND_URL", "")
	t.Setenv("CORS_ALLOWED_ORIGINS", "")
	t.Setenv("ALLOWED_ORIGINS", "http://127.0.0.1:4173")

	cfg := LoadConfigFromEnv()

	if !cfg.IsAllowedOrigin("http://127.0.0.1:4173") {
		t.Fatal("expected deprecated alias to remain supported")
	}
}

func TestLoopbackEquivalence_OriginAllowsBothSpellings(t *testing.T) {
	t.Setenv("FRONTEND_URL", "http://127.0.0.1:5173")
	t.Setenv("CORS_ALLOWED_ORIGINS", "")
	t.Setenv("ALLOWED_ORIGINS", "")

	cfg := LoadConfigFromEnv()

	if !cfg.IsAllowedOrigin("http://127.0.0.1:5173") {
		t.Fatal("expected 127.0.0.1 origin to be allowed")
	}
	if !cfg.IsAllowedOrigin("http://localhost:5173") {
		t.Fatal("expected localhost equivalent to be allowed")
	}
}

func TestLoopbackEquivalence_LocalhostAlsoAllows127(t *testing.T) {
	t.Setenv("FRONTEND_URL", "http://localhost:3000")
	t.Setenv("CORS_ALLOWED_ORIGINS", "")
	t.Setenv("ALLOWED_ORIGINS", "")

	cfg := LoadConfigFromEnv()

	if !cfg.IsAllowedOrigin("http://localhost:3000") {
		t.Fatal("expected localhost origin to be allowed")
	}
	if !cfg.IsAllowedOrigin("http://127.0.0.1:3000") {
		t.Fatal("expected 127.0.0.1 equivalent to be allowed")
	}
}

func TestLoopbackEquivalence_RedirectHostAllowsBothSpellings(t *testing.T) {
	t.Setenv("FRONTEND_URL", "http://127.0.0.1:5173")
	t.Setenv("CORS_ALLOWED_ORIGINS", "")
	t.Setenv("ALLOWED_ORIGINS", "")
	t.Setenv("GOOGLE_ALLOWED_REDIRECT_HOSTS", "")

	cfg := LoadConfigFromEnv()

	if !cfg.IsAllowedRedirectURI("http://127.0.0.1:5173/oauth/callback") {
		t.Fatal("expected 127.0.0.1 redirect to be allowed")
	}
	if !cfg.IsAllowedRedirectURI("http://localhost:5173/oauth/callback") {
		t.Fatal("expected localhost redirect to be allowed via loopback equivalence")
	}
}

func TestNonLoopbackOrigin_NoEquivalenceAdded(t *testing.T) {
	t.Setenv("FRONTEND_URL", "https://app.example.com")
	t.Setenv("CORS_ALLOWED_ORIGINS", "")
	t.Setenv("ALLOWED_ORIGINS", "")

	cfg := LoadConfigFromEnv()

	if !cfg.IsAllowedOrigin("https://app.example.com") {
		t.Fatal("expected configured origin to be allowed")
	}
	if cfg.IsAllowedOrigin("https://127.0.0.1") {
		t.Fatal("non-loopback origin should not get a 127.0.0.1 equivalent")
	}
}

func TestIsAllowedRedirectURI(t *testing.T) {
	t.Setenv("FRONTEND_URL", "http://127.0.0.1:4173")
	t.Setenv("CORS_ALLOWED_ORIGINS", "")
	t.Setenv("ALLOWED_ORIGINS", "")
	t.Setenv("GOOGLE_ALLOWED_REDIRECT_HOSTS", "auth.example.com")

	cfg := LoadConfigFromEnv()

	if !cfg.IsAllowedRedirectURI("http://127.0.0.1:4173/oauth/callback") {
		t.Fatal("expected configured frontend redirect to be allowed")
	}

	if !cfg.IsAllowedRedirectURI("https://auth.example.com/oauth/callback") {
		t.Fatal("expected explicitly allowed redirect host to be allowed")
	}

	if cfg.IsAllowedRedirectURI("https://evil.example.com/oauth/callback") {
		t.Fatal("expected unconfigured redirect host to be rejected")
	}
}
