package auth_test

import (
	"testing"

	"switchboard-core/auth"
)

func TestOIDCProvider_Discovery(t *testing.T) {
	idp := newMockIdP()
	defer idp.Close()

	p, err := auth.NewOIDCProvider(auth.OIDCConfig{
		IssuerURL:    idp.IssuerURL(),
		ClientID:     "switchboard",
		ClientSecret: "secret",
		AutoActivate: true,
	})
	if err != nil {
		t.Fatalf("NewOIDCProvider: %v", err)
	}

	disc := p.Discovery()
	if disc == nil {
		t.Fatal("discovery should not be nil")
	}
	if disc.JWKSUri == "" {
		t.Error("JWKS URI should not be empty")
	}
	if disc.TokenEndpoint == "" {
		t.Error("token endpoint should not be empty")
	}
}

func TestOIDCProvider_Mode(t *testing.T) {
	idp := newMockIdP()
	defer idp.Close()

	p, err := auth.NewOIDCProvider(auth.OIDCConfig{
		IssuerURL: idp.IssuerURL(),
		ClientID:  "switchboard",
	})
	if err != nil {
		t.Fatalf("NewOIDCProvider: %v", err)
	}

	if p.Mode() != auth.ModeOIDC {
		t.Errorf("Mode() = %q, want %q", p.Mode(), auth.ModeOIDC)
	}
}

func TestOIDCProvider_NoRegistration(t *testing.T) {
	idp := newMockIdP()
	defer idp.Close()

	p, err := auth.NewOIDCProvider(auth.OIDCConfig{
		IssuerURL: idp.IssuerURL(),
		ClientID:  "switchboard",
	})
	if err != nil {
		t.Fatalf("NewOIDCProvider: %v", err)
	}

	if p.SupportsRegistration() {
		t.Error("OIDC should not support registration")
	}
}

func TestOIDCProvider_MissingIssuer(t *testing.T) {
	_, err := auth.NewOIDCProvider(auth.OIDCConfig{
		ClientID: "switchboard",
	})
	if err == nil {
		t.Error("expected error for missing issuer URL")
	}
}

func TestOIDCProvider_MissingClientID(t *testing.T) {
	idp := newMockIdP()
	defer idp.Close()

	_, err := auth.NewOIDCProvider(auth.OIDCConfig{
		IssuerURL: idp.IssuerURL(),
	})
	if err == nil {
		t.Error("expected error for missing client ID")
	}
}

func TestOIDCProvider_AuthorizationURL(t *testing.T) {
	idp := newMockIdP()
	defer idp.Close()

	p, err := auth.NewOIDCProvider(auth.OIDCConfig{
		IssuerURL: idp.IssuerURL(),
		ClientID:  "switchboard",
	})
	if err != nil {
		t.Fatalf("NewOIDCProvider: %v", err)
	}

	url := p.AuthorizationURL("test-state", "test-nonce", "http://localhost/callback")
	if url == "" {
		t.Fatal("AuthorizationURL should not be empty")
	}

	// Should contain the required OIDC parameters
	for _, want := range []string{"response_type=code", "client_id=switchboard", "state=test-state", "nonce=test-nonce"} {
		if !containsStr(url, want) {
			t.Errorf("AuthorizationURL missing %q in %q", want, url)
		}
	}
}

func TestOIDCProvider_UnreachableIssuer(t *testing.T) {
	_, err := auth.NewOIDCProvider(auth.OIDCConfig{
		IssuerURL: "http://127.0.0.1:1/unreachable",
		ClientID:  "switchboard",
	})
	if err == nil {
		t.Error("expected error for unreachable issuer")
	}
}

func containsStr(s, substr string) bool {
	return len(s) >= len(substr) && (s == substr || len(s) > 0 && containsSubstring(s, substr))
}

func containsSubstring(s, sub string) bool {
	for i := 0; i <= len(s)-len(sub); i++ {
		if s[i:i+len(sub)] == sub {
			return true
		}
	}
	return false
}
