package sqlite

import (
	"context"
	"os"
	"path/filepath"
	"testing"

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

// TestLazyCounterInitialization verifies that counters are initialized lazily
// on first use, not by scanning the entire database on every CreateIssue
func TestLazyCounterInitialization(t *testing.T) {
	// Create temporary directory
	tmpDir, err := os.MkdirTemp("", "beads-lazy-init-test-*")
	if err != nil {
		t.Fatalf("failed to create temp dir: %v", err)
	}
	defer os.RemoveAll(tmpDir)

	dbPath := filepath.Join(tmpDir, "test.db")

	// Initialize database
	store, err := New(dbPath)
	if err != nil {
		t.Fatalf("failed to create storage: %v", err)
	}
	defer store.Close()

	ctx := context.Background()

	// Set the issue prefix to "bd" for this test
	if err := store.SetConfig(ctx, "issue_prefix", "bd"); err != nil {
		t.Fatalf("Failed to set issue_prefix: %v", err)
	}

	// Create some issues with explicit IDs (simulating import)
	existingIssues := []string{"bd-5", "bd-10", "bd-15"}
	for _, id := range existingIssues {
		issue := &types.Issue{
			ID:        id,
			Title:     "Existing issue",
			Status:    types.StatusOpen,
			Priority:  2,
			IssueType: types.TypeTask,
		}
		err := store.CreateIssue(ctx, issue, "test-user")
		if err != nil {
			t.Fatalf("CreateIssue with explicit ID failed: %v", err)
		}
	}

	// Verify no counter exists yet (lazy init hasn't happened)
	var count int
	err = store.db.QueryRow(`SELECT COUNT(*) FROM issue_counters WHERE prefix = 'bd'`).Scan(&count)
	if err != nil {
		t.Fatalf("Failed to query counters: %v", err)
	}

	if count != 0 {
		t.Errorf("Expected no counter yet, but found %d", count)
	}

	// Now create an issue with auto-generated ID
	// This should trigger lazy initialization
	autoIssue := &types.Issue{
		Title:     "Auto-generated ID",
		Status:    types.StatusOpen,
		Priority:  2,
		IssueType: types.TypeTask,
	}

	err = store.CreateIssue(ctx, autoIssue, "test-user")
	if err != nil {
		t.Fatalf("CreateIssue with auto ID failed: %v", err)
	}

	// Verify the ID is correct (should be bd-16, after bd-15)
	if autoIssue.ID != "bd-16" {
		t.Errorf("Expected bd-16, got %s", autoIssue.ID)
	}

	// Verify counter was initialized
	var lastID int
	err = store.db.QueryRow(`SELECT last_id FROM issue_counters WHERE prefix = 'bd'`).Scan(&lastID)
	if err != nil {
		t.Fatalf("Failed to query counter: %v", err)
	}

	if lastID != 16 {
		t.Errorf("Expected counter at 16, got %d", lastID)
	}

	// Create another issue - should NOT re-scan, just increment
	anotherIssue := &types.Issue{
		Title:     "Another auto-generated ID",
		Status:    types.StatusOpen,
		Priority:  2,
		IssueType: types.TypeTask,
	}

	err = store.CreateIssue(ctx, anotherIssue, "test-user")
	if err != nil {
		t.Fatalf("CreateIssue failed: %v", err)
	}

	if anotherIssue.ID != "bd-17" {
		t.Errorf("Expected bd-17, got %s", anotherIssue.ID)
	}
}

// TestLazyCounterInitializationMultiplePrefix tests lazy init with multiple prefixes
func TestLazyCounterInitializationMultiplePrefix(t *testing.T) {
	store, cleanup := setupTestDB(t)
	defer cleanup()

	ctx := context.Background()

	// Set a custom prefix
	err := store.SetConfig(ctx, "issue_prefix", "custom")
	if err != nil {
		t.Fatalf("SetConfig failed: %v", err)
	}

	// Create issue with default prefix first
	err = store.SetConfig(ctx, "issue_prefix", "bd")
	if err != nil {
		t.Fatalf("SetConfig failed: %v", err)
	}

	bdIssue := &types.Issue{
		Title:     "BD issue",
		Status:    types.StatusOpen,
		Priority:  2,
		IssueType: types.TypeTask,
	}

	err = store.CreateIssue(ctx, bdIssue, "test-user")
	if err != nil {
		t.Fatalf("CreateIssue failed: %v", err)
	}

	if bdIssue.ID != "bd-1" {
		t.Errorf("Expected bd-1, got %s", bdIssue.ID)
	}

	// Now switch to custom prefix
	err = store.SetConfig(ctx, "issue_prefix", "custom")
	if err != nil {
		t.Fatalf("SetConfig failed: %v", err)
	}

	customIssue := &types.Issue{
		Title:     "Custom issue",
		Status:    types.StatusOpen,
		Priority:  2,
		IssueType: types.TypeTask,
	}

	err = store.CreateIssue(ctx, customIssue, "test-user")
	if err != nil {
		t.Fatalf("CreateIssue failed: %v", err)
	}

	if customIssue.ID != "custom-1" {
		t.Errorf("Expected custom-1, got %s", customIssue.ID)
	}

	// Verify both counters exist
	var count int
	err = store.db.QueryRow(`SELECT COUNT(*) FROM issue_counters`).Scan(&count)
	if err != nil {
		t.Fatalf("Failed to query counters: %v", err)
	}

	if count != 2 {
		t.Errorf("Expected 2 counters, got %d", count)
	}
}

// TestCounterInitializationFromExisting tests that the counter
// correctly initializes from the max ID of existing issues
func TestCounterInitializationFromExisting(t *testing.T) {
	store, cleanup := setupTestDB(t)
	defer cleanup()

	ctx := context.Background()

	// Set the issue prefix to "bd" for this test
	if err := store.SetConfig(ctx, "issue_prefix", "bd"); err != nil {
		t.Fatalf("Failed to set issue_prefix: %v", err)
	}

	// Create issues with explicit IDs, out of order
	explicitIDs := []string{"bd-5", "bd-100", "bd-42", "bd-7"}
	for _, id := range explicitIDs {
		issue := &types.Issue{
			ID:        id,
			Title:     "Explicit ID",
			Status:    types.StatusOpen,
			Priority:  2,
			IssueType: types.TypeTask,
		}
		err := store.CreateIssue(ctx, issue, "test-user")
		if err != nil {
			t.Fatalf("CreateIssue failed: %v", err)
		}
	}

	// Now auto-generate - should start at 101 (max is bd-100)
	autoIssue := &types.Issue{
		Title:     "Auto ID",
		Status:    types.StatusOpen,
		Priority:  2,
		IssueType: types.TypeTask,
	}

	err := store.CreateIssue(ctx, autoIssue, "test-user")
	if err != nil {
		t.Fatalf("CreateIssue failed: %v", err)
	}

	if autoIssue.ID != "bd-101" {
		t.Errorf("Expected bd-101 (max was bd-100), got %s", autoIssue.ID)
	}
}
