package service

import (
	"encoding/json"
	"strings"
	"testing"

	"github.com/user-management-system/internal/domain"
)

// =============================================================================
// Webhook Utility Functions Tests
// =============================================================================

func TestGenerateEventID(t *testing.T) {
	t.Run("generates valid event ID", func(t *testing.T) {
		id, err := generateEventID()
		if err != nil {
			t.Fatalf("generateEventID failed: %v", err)
		}
		if !strings.HasPrefix(id, "evt_") {
			t.Errorf("Expected ID to start with 'evt_', got %q", id)
		}
		if len(id) != 20 { // "evt_" + 16 hex chars (8 bytes)
			t.Errorf("Expected ID length 20, got %d", len(id))
		}
	})

	t.Run("generates unique IDs", func(t *testing.T) {
		id1, _ := generateEventID()
		id2, _ := generateEventID()
		if id1 == id2 {
			t.Error("Expected different IDs on each call")
		}
	})
}

func TestGenerateWebhookSecret(t *testing.T) {
	t.Run("generates valid secret", func(t *testing.T) {
		secret, err := generateWebhookSecret()
		if err != nil {
			t.Fatalf("generateWebhookSecret failed: %v", err)
		}
		if len(secret) != 48 { // 24 bytes = 48 hex chars
			t.Errorf("Expected secret length 48, got %d", len(secret))
		}
		// Check that secret is lowercase hex
		for _, c := range secret {
			if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')) {
				t.Errorf("Expected lowercase hex characters, got %c", c)
				break
			}
		}
	})

	t.Run("generates unique secrets", func(t *testing.T) {
		secret1, _ := generateWebhookSecret()
		secret2, _ := generateWebhookSecret()
		if secret1 == secret2 {
			t.Error("Expected different secrets on each call")
		}
	})
}

func TestWebhookSubscribesTo(t *testing.T) {
	tests := []struct {
		name     string
		events   []domain.WebhookEventType
		event    domain.WebhookEventType
		expected bool
	}{
		{"empty events list", []domain.WebhookEventType{}, "user.created", false},
		{"exact match", []domain.WebhookEventType{"user.created", "user.updated"}, "user.created", true},
		{"no match", []domain.WebhookEventType{"user.created", "user.updated"}, "user.deleted", false},
		{"all events wildcard", []domain.WebhookEventType{"*"}, "any.event", true},
		{"exact match different event", []domain.WebhookEventType{"user.created"}, "user.updated", false},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			eventsJSON, _ := json.Marshal(tt.events)
			webhook := &domain.Webhook{
				Events: string(eventsJSON),
			}
			result := webhookSubscribesTo(webhook, tt.event)
			if result != tt.expected {
				t.Errorf("webhookSubscribesTo(%v, %q) = %v, want %v", tt.events, tt.event, result, tt.expected)
			}
		})
	}
}

func TestWebhookSubscribesTo_InvalidJSON(t *testing.T) {
	t.Run("invalid JSON returns false", func(t *testing.T) {
		webhook := &domain.Webhook{
			Events: "invalid json",
		}
		result := webhookSubscribesTo(webhook, "user.created")
		if result {
			t.Error("Expected false for invalid JSON")
		}
	})
}
