package redis

import (
	"context"
	"os"
	"testing"
	"time"

	"log/slog"
)

// Integration tests - require REDIS_TEST_URL env var
// Example: REDIS_TEST_URL=redis://:password@localhost:6379 go test ./internal/adapter/redis/...

func TestProvisioner_Integration(t *testing.T) {
	redisURL := os.Getenv("REDIS_TEST_URL")
	if redisURL == "" {
		t.Skip("REDIS_TEST_URL not set, skipping integration test")
	}

	// Parse URL for config (simplified, assumes redis://:password@host:port format)
	// In real tests, use a proper URL parser
	cfg := Config{
		Host:      "localhost",
		Port:      6379,
		Password:  "",
		KeyPrefix: "test:",
	}

	logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug}))
	prov, err := NewProvisioner(cfg, logger)
	if err != nil {
		t.Fatalf("failed to create provisioner: %v", err)
	}
	defer prov.Close()

	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	projectID := "test-project-" + time.Now().Format("20060102150405")

	// Test CreateProjectCache
	t.Run("CreateProjectCache", func(t *testing.T) {
		creds, err := prov.CreateProjectCache(ctx, projectID)
		if err != nil {
			t.Fatalf("CreateProjectCache failed: %v", err)
		}

		if creds.ProjectID != projectID {
			t.Errorf("ProjectID = %q, want %q", creds.ProjectID, projectID)
		}
		if creds.Username == "" {
			t.Error("Username is empty")
		}
		if creds.URL == "" {
			t.Error("URL is empty")
		}
		if creds.Prefix == "" {
			t.Error("Prefix is empty")
		}
		t.Logf("Created cache: username=%s prefix=%s", creds.Username, creds.Prefix)
	})

	// Test GetProjectCache
	t.Run("GetProjectCache", func(t *testing.T) {
		creds, err := prov.GetProjectCache(ctx, projectID)
		if err != nil {
			t.Fatalf("GetProjectCache failed: %v", err)
		}
		if creds == nil {
			t.Fatal("GetProjectCache returned nil")
		}
		if creds.Username == "" {
			t.Error("Username is empty")
		}
	})

	// Test DeleteProjectCache
	t.Run("DeleteProjectCache", func(t *testing.T) {
		err := prov.DeleteProjectCache(ctx, projectID, true)
		if err != nil {
			t.Fatalf("DeleteProjectCache failed: %v", err)
		}

		// Verify user is deleted
		creds, err := prov.GetProjectCache(ctx, projectID)
		if err != nil {
			t.Fatalf("GetProjectCache after delete failed: %v", err)
		}
		if creds != nil {
			t.Error("User still exists after delete")
		}
	})
}

func TestUsernameFor(t *testing.T) {
	p := &Provisioner{keyPrefix: "project:"}

	tests := []struct {
		projectID string
		want      string
	}{
		{"my-app", "proj-my-app"},
		{"my_app", "proj-my-app"}, // underscore converted to hyphen
		{"MyApp123", "proj-MyApp123"},
		{"app.name", "proj-app-name"}, // dot converted to hyphen
	}

	for _, tt := range tests {
		t.Run(tt.projectID, func(t *testing.T) {
			got := p.usernameFor(tt.projectID)
			if got != tt.want {
				t.Errorf("usernameFor(%q) = %q, want %q", tt.projectID, got, tt.want)
			}
		})
	}
}

func TestPrefixFor(t *testing.T) {
	p := &Provisioner{keyPrefix: "project:"}

	tests := []struct {
		projectID string
		want      string
	}{
		{"my-app", "project:my-app:"},
		{"app123", "project:app123:"},
	}

	for _, tt := range tests {
		t.Run(tt.projectID, func(t *testing.T) {
			got := p.prefixFor(tt.projectID)
			if got != tt.want {
				t.Errorf("prefixFor(%q) = %q, want %q", tt.projectID, got, tt.want)
			}
		})
	}
}
