//go:build integration
// +build integration

package sqlite

import (
	"context"
	"strings"
	"testing"

	"github.com/steveyegge/beads/internal/types"
)

func TestAdaptiveIDLength_E2E(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping slow E2E test in short mode")
	}
	// Create in-memory database
	ctx := context.Background()
	db, err := New(ctx, ":memory:")
	if err != nil {
		t.Fatalf("Failed to create database: %v", err)
	}
	defer db.Close()
	
	// Initialize with prefix
	if err := db.SetConfig(ctx, "issue_prefix", "test"); err != nil {
		t.Fatalf("Failed to set prefix: %v", err)
	}
	
	// Helper to create issue and verify ID length
	createAndCheckLength := func(title string, expectedHashLen int) string {
		issue := &types.Issue{
			Title:       title,
			Description: "Test",
			Status:      "open",
			Priority:    1,
			IssueType:   "task",
		}
		
		if err := db.CreateIssue(ctx, issue, "test@example.com"); err != nil {
			t.Fatalf("Failed to create issue: %v", err)
		}
		
		// Check ID format: test-xxxx
		if !strings.HasPrefix(issue.ID, "test-") {
			t.Errorf("ID should start with test-, got %s", issue.ID)
		}
		
		hashPart := strings.TrimPrefix(issue.ID, "test-")
		if len(hashPart) != expectedHashLen {
			t.Errorf("Issue %s: hash length = %d, want %d", title, len(hashPart), expectedHashLen)
		}
		
		return issue.ID
	}
	
	// Test 1: First few issues should use 3-char IDs (base36 allows shorter IDs)
	t.Run("first_50_issues_use_3_chars", func(t *testing.T) {
		for i := 0; i < 50; i++ {
			title := formatTitle("Issue %d", i)
			createAndCheckLength(title, 3)
		}
	})

	// Test 2: Issues 50-200 should transition to 4 chars
	// (3 chars good up to ~160 issues with 25% threshold)
	t.Run("issues_50_to_200_use_3_or_4_chars", func(t *testing.T) {
		for i := 50; i < 200; i++ {
			title := formatTitle("Issue %d", i)
			issue := &types.Issue{
				Title:       title,
				Description: "Test",
				Status:      "open",
				Priority:    1,
				IssueType:   "task",
			}

			if err := db.CreateIssue(ctx, issue, "test@example.com"); err != nil {
				t.Fatalf("Failed to create issue: %v", err)
			}

			// Most should be 3 chars initially, transitioning to 4 after ~160
			hashPart := strings.TrimPrefix(issue.ID, "test-")
			if len(hashPart) < 3 || len(hashPart) > 4 {
				t.Errorf("Issue %d has hash length %d, expected 3-4", i, len(hashPart))
			}
		}
	})
	
	// Test 3: At 500-1000 issues, should scale to 4-5 chars
	// (4 chars good up to ~980 issues with 25% threshold)
	t.Run("verify_adaptive_scaling_works", func(t *testing.T) {
		// Just verify that we can create more issues and the algorithm doesn't break
		// The actual length will be determined by the adaptive algorithm
		for i := 200; i < 250; i++ {
			title := formatTitle("Issue %d", i)
			issue := &types.Issue{
				Title:       title,
				Description: "Test",
				Status:      "open",
				Priority:    1,
				IssueType:   "task",
			}

			if err := db.CreateIssue(ctx, issue, "test@example.com"); err != nil {
				t.Fatalf("Failed to create issue: %v", err)
			}

			// Should use 4-5 chars depending on database size
			hashPart := strings.TrimPrefix(issue.ID, "test-")
			if len(hashPart) < 3 || len(hashPart) > 5 {
				t.Errorf("Issue %d has hash length %d, expected 3-5", i, len(hashPart))
			}
		}
	})
}

func formatTitle(format string, i int) string {
	// Use sprintf to format title
	return strings.Replace(format, "%d", strings.Repeat("x", i%10), 1) + string(rune('a'+i%26))
}

func TestAdaptiveIDLength_CustomConfig(t *testing.T) {
	// Create in-memory database
	ctx := context.Background()
	db, err := New(ctx, ":memory:")
	if err != nil {
		t.Fatalf("Failed to create database: %v", err)
	}
	defer db.Close()
	
	// Initialize with custom config
	if err := db.SetConfig(ctx, "issue_prefix", "test"); err != nil {
		t.Fatalf("Failed to set prefix: %v", err)
	}
	
	// Set stricter collision threshold (1%) and min length of 5
	if err := db.SetConfig(ctx, "max_collision_prob", "0.01"); err != nil {
		t.Fatalf("Failed to set max_collision_prob: %v", err)
	}
	if err := db.SetConfig(ctx, "min_hash_length", "5"); err != nil {
		t.Fatalf("Failed to set min_hash_length: %v", err)
	}
	
	// With min_hash_length=5, all IDs should be at least 5 chars
	for i := 0; i < 20; i++ {
		issue := &types.Issue{
			Title:       formatTitle("Issue %d", i),
			Description: "Test",
			Status:      "open",
			Priority:    1,
			IssueType:   "task",
		}
		
		if err := db.CreateIssue(ctx, issue, "test@example.com"); err != nil {
			t.Fatalf("Failed to create issue: %v", err)
		}
		
		hashPart := strings.TrimPrefix(issue.ID, "test-")
		// With min_hash_length=5, should use at least 5 chars
		if len(hashPart) < 5 {
			t.Errorf("Issue %d with min_hash_length=5: hash length = %d, want >= 5", i, len(hashPart))
		}
	}
}
