package heroic_ops

import (
	"context"
	"fmt"
	"path/filepath"
	"testing"
	"time"

	"zombiezen.com/go/sqlite"
	"zombiezen.com/go/sqlite/sqlitex"
)

// createTestPool creates a temporary test database pool
func createTestPool(t *testing.T) *sqlitex.Pool {
	// Create temporary directory for test database
	tempDir := t.TempDir()
	dbPath := filepath.Join(tempDir, "test_heroic_ops.db")

	// Create and initialize database pool
	pool, err := sqlitex.NewPool(dbPath, sqlitex.PoolOptions{
		Flags: sqlite.OpenReadWrite | sqlite.OpenCreate,
	})
	if err != nil {
		t.Fatalf("Failed to create test database pool: %v", err)
	}

	// Create heroic ops tables for testing
	dhom := NewDatabaseHeroicOPManager(pool)
	err = dhom.EnsureHOTables(context.Background())
	if err != nil {
		t.Fatalf("Failed to create heroic ops tables: %v", err)
	}

	return pool
}

// execSQL is a helper to execute SQL with parameters
func execSQL(t *testing.T, pool *sqlitex.Pool, query string, args ...interface{}) {
	conn, err := pool.Take(context.Background())
	if err != nil {
		t.Fatalf("Failed to get connection: %v", err)
	}
	defer pool.Put(conn)

	err = sqlitex.Execute(conn, query, &sqlitex.ExecOptions{
		Args: args,
	})
	if err != nil {
		t.Fatalf("Failed to execute SQL: %v", err)
	}
}

// TestDatabaseHeroicOPManager_LoadStarters tests loading starters from database
func TestDatabaseHeroicOPManager_LoadStarters(t *testing.T) {
	pool := createTestPool(t)
	defer pool.Close()

	dhom := NewDatabaseHeroicOPManager(pool)
	ctx := context.Background()

	// Insert test starter data
	execSQL(t, pool, `INSERT INTO heroic_ops 
		(id, ho_type, starter_class, starter_icon, starter_link_id, chain_order,
		 shift_icon, spell_id, chance, ability1, ability2, ability3, ability4,
		 ability5, ability6, name, description)
		VALUES (?, ?, ?, ?, 0, 0, 0, 0, 0.0, ?, ?, ?, ?, ?, ?, ?, ?)`,
		1, HOTypeStarter, 5, 100, 10, 20, 30, 40, 50, 60, "Test Starter", "A test starter")

	// Test loading starters
	starters, err := dhom.LoadStarters(ctx)
	if err != nil {
		t.Fatalf("Failed to load starters: %v", err)
	}

	if len(starters) != 1 {
		t.Errorf("Expected 1 starter, got %d", len(starters))
	}

	if len(starters) > 0 {
		starter := starters[0]
		if starter.ID != 1 {
			t.Errorf("Expected starter ID 1, got %d", starter.ID)
		}
		if starter.StarterClass != 5 {
			t.Errorf("Expected starter class 5, got %d", starter.StarterClass)
		}
		if starter.Name != "Test Starter" {
			t.Errorf("Expected name 'Test Starter', got '%s'", starter.Name)
		}
		if starter.Ability1 != 10 {
			t.Errorf("Expected ability1 10, got %d", starter.Ability1)
		}
	}
}

// TestDatabaseHeroicOPManager_LoadStarter tests loading a specific starter
func TestDatabaseHeroicOPManager_LoadStarter(t *testing.T) {
	pool := createTestPool(t)
	defer pool.Close()

	dhom := NewDatabaseHeroicOPManager(pool)
	ctx := context.Background()

	// Insert test starter data
	execSQL(t, pool, `INSERT INTO heroic_ops 
		(id, ho_type, starter_class, starter_icon, starter_link_id, chain_order,
		 shift_icon, spell_id, chance, ability1, ability2, ability3, ability4,
		 ability5, ability6, name, description)
		VALUES (?, ?, ?, ?, 0, 0, 0, 0, 0.0, ?, ?, ?, ?, ?, ?, ?, ?)`,
		2, HOTypeStarter, 10, 200, 11, 21, 31, 41, 51, 61, "Specific Starter", "A specific test starter")

	// Test loading specific starter
	starter, err := dhom.LoadStarter(ctx, 2)
	if err != nil {
		t.Fatalf("Failed to load starter: %v", err)
	}

	if starter.ID != 2 {
		t.Errorf("Expected starter ID 2, got %d", starter.ID)
	}
	if starter.StarterClass != 10 {
		t.Errorf("Expected starter class 10, got %d", starter.StarterClass)
	}
	if starter.Name != "Specific Starter" {
		t.Errorf("Expected name 'Specific Starter', got '%s'", starter.Name)
	}

	// Test loading non-existent starter
	_, err = dhom.LoadStarter(ctx, 999)
	if err == nil {
		t.Error("Expected error loading non-existent starter, got nil")
	}
}

// TestDatabaseHeroicOPManager_LoadWheels tests loading wheels from database
func TestDatabaseHeroicOPManager_LoadWheels(t *testing.T) {
	pool := createTestPool(t)
	defer pool.Close()

	dhom := NewDatabaseHeroicOPManager(pool)
	ctx := context.Background()

	// Insert test wheel data
	execSQL(t, pool, `INSERT INTO heroic_ops 
		(id, ho_type, starter_class, starter_icon, starter_link_id, chain_order,
		 shift_icon, spell_id, chance, ability1, ability2, ability3, ability4,
		 ability5, ability6, name, description)
		VALUES (?, ?, 0, 0, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
		10, HOTypeWheel, 1, 1, 300, 1001, 0.75, 15, 25, 35, 45, 55, 65, "Test Wheel", "A test wheel")

	// Test loading wheels
	wheels, err := dhom.LoadWheels(ctx)
	if err != nil {
		t.Fatalf("Failed to load wheels: %v", err)
	}

	if len(wheels) != 1 {
		t.Errorf("Expected 1 wheel, got %d", len(wheels))
	}

	if len(wheels) > 0 {
		wheel := wheels[0]
		if wheel.ID != 10 {
			t.Errorf("Expected wheel ID 10, got %d", wheel.ID)
		}
		if wheel.StarterLinkID != 1 {
			t.Errorf("Expected starter link ID 1, got %d", wheel.StarterLinkID)
		}
		if wheel.SpellID != 1001 {
			t.Errorf("Expected spell ID 1001, got %d", wheel.SpellID)
		}
		if wheel.Chance != 0.75 {
			t.Errorf("Expected chance 0.75, got %f", wheel.Chance)
		}
	}
}

// TestDatabaseHeroicOPManager_LoadWheelsForStarter tests loading wheels for specific starter
func TestDatabaseHeroicOPManager_LoadWheelsForStarter(t *testing.T) {
	pool := createTestPool(t)
	defer pool.Close()

	dhom := NewDatabaseHeroicOPManager(pool)
	ctx := context.Background()

	starterID := int32(5)

	// Insert multiple wheels for the same starter
	execSQL(t, pool, `INSERT INTO heroic_ops 
		(id, ho_type, starter_class, starter_icon, starter_link_id, chain_order,
		 shift_icon, spell_id, chance, ability1, ability2, ability3, ability4,
		 ability5, ability6, name, description)
		VALUES (?, ?, 0, 0, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
		20, HOTypeWheel, starterID, 1, 400, 1002, 0.5, 16, 26, 36, 46, 56, 66, "Wheel 1", "First wheel")

	execSQL(t, pool, `INSERT INTO heroic_ops 
		(id, ho_type, starter_class, starter_icon, starter_link_id, chain_order,
		 shift_icon, spell_id, chance, ability1, ability2, ability3, ability4,
		 ability5, ability6, name, description)
		VALUES (?, ?, 0, 0, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
		21, HOTypeWheel, starterID, 2, 500, 1003, 0.8, 17, 27, 37, 47, 57, 67, "Wheel 2", "Second wheel")

	// Test loading wheels for specific starter
	wheels, err := dhom.LoadWheelsForStarter(ctx, starterID)
	if err != nil {
		t.Fatalf("Failed to load wheels for starter: %v", err)
	}

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

	// Test loading wheels for non-existent starter
	wheels, err = dhom.LoadWheelsForStarter(ctx, 999)
	if err != nil {
		t.Fatalf("Failed to load wheels for non-existent starter: %v", err)
	}

	if len(wheels) != 0 {
		t.Errorf("Expected 0 wheels for non-existent starter, got %d", len(wheels))
	}
}

// TestDatabaseHeroicOPManager_SaveStarter tests saving a heroic op starter
func TestDatabaseHeroicOPManager_SaveStarter(t *testing.T) {
	pool := createTestPool(t)
	defer pool.Close()

	dhom := NewDatabaseHeroicOPManager(pool)
	ctx := context.Background()

	// Create a test starter
	starter := &HeroicOPStarter{
		ID:          100,
		StartClass:  15,
		StarterIcon: 500,
		Abilities:   [6]int16{70, 80, 90, 100, 110, 120},
		Name:        "Saved Starter",
		Description: "A saved test starter",
	}

	// Save the starter
	err := dhom.SaveStarter(ctx, starter)
	if err != nil {
		t.Fatalf("Failed to save starter: %v", err)
	}

	// Load and verify
	loaded, err := dhom.LoadStarter(ctx, 100)
	if err != nil {
		t.Fatalf("Failed to load saved starter: %v", err)
	}

	if loaded.StarterClass != 15 {
		t.Errorf("Expected starter class 15, got %d", loaded.StarterClass)
	}
	if loaded.Name != "Saved Starter" {
		t.Errorf("Expected name 'Saved Starter', got '%s'", loaded.Name)
	}
	if loaded.Ability1 != 70 {
		t.Errorf("Expected ability1 70, got %d", loaded.Ability1)
	}
}

// TestDatabaseHeroicOPManager_SaveWheel tests saving a heroic op wheel
func TestDatabaseHeroicOPManager_SaveWheel(t *testing.T) {
	pool := createTestPool(t)
	defer pool.Close()

	dhom := NewDatabaseHeroicOPManager(pool)
	ctx := context.Background()

	// Create a test wheel
	wheel := &HeroicOPWheel{
		ID:            200,
		StarterLinkID: 100,
		Order:         2,
		ShiftIcon:     600,
		SpellID:       2001,
		Chance:        0.9,
		Abilities:     [6]int16{71, 81, 91, 101, 111, 121},
		Name:          "Saved Wheel",
		Description:   "A saved test wheel",
	}

	// Save the wheel
	err := dhom.SaveWheel(ctx, wheel)
	if err != nil {
		t.Fatalf("Failed to save wheel: %v", err)
	}

	// Load and verify
	loaded, err := dhom.LoadWheel(ctx, 200)
	if err != nil {
		t.Fatalf("Failed to load saved wheel: %v", err)
	}

	if loaded.StarterLinkID != 100 {
		t.Errorf("Expected starter link ID 100, got %d", loaded.StarterLinkID)
	}
	if loaded.SpellID != 2001 {
		t.Errorf("Expected spell ID 2001, got %d", loaded.SpellID)
	}
	if loaded.Chance != 0.9 {
		t.Errorf("Expected chance 0.9, got %f", loaded.Chance)
	}
}

// TestDatabaseHeroicOPManager_DeleteStarter tests deleting a starter and its wheels
func TestDatabaseHeroicOPManager_DeleteStarter(t *testing.T) {
	pool := createTestPool(t)
	defer pool.Close()

	dhom := NewDatabaseHeroicOPManager(pool)
	ctx := context.Background()

	starterID := int32(300)

	// Insert starter
	execSQL(t, pool, `INSERT INTO heroic_ops 
		(id, ho_type, starter_class, starter_icon, starter_link_id, chain_order,
		 shift_icon, spell_id, chance, ability1, ability2, ability3, ability4,
		 ability5, ability6, name, description)
		VALUES (?, ?, ?, ?, 0, 0, 0, 0, 0.0, ?, ?, ?, ?, ?, ?, ?, ?)`,
		starterID, HOTypeStarter, 20, 700, 72, 82, 92, 102, 112, 122, "Delete Test Starter", "To be deleted")

	// Insert associated wheels
	execSQL(t, pool, `INSERT INTO heroic_ops 
		(id, ho_type, starter_class, starter_icon, starter_link_id, chain_order,
		 shift_icon, spell_id, chance, ability1, ability2, ability3, ability4,
		 ability5, ability6, name, description)
		VALUES (?, ?, 0, 0, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
		400, HOTypeWheel, starterID, 1, 800, 3001, 0.6, 73, 83, 93, 103, 113, 123, "Wheel to Delete", "Will be deleted")

	// Verify they exist
	_, err := dhom.LoadStarter(ctx, starterID)
	if err != nil {
		t.Fatalf("Starter should exist before deletion: %v", err)
	}

	wheels, err := dhom.LoadWheelsForStarter(ctx, starterID)
	if err != nil {
		t.Fatalf("Failed to load wheels before deletion: %v", err)
	}
	if len(wheels) != 1 {
		t.Errorf("Expected 1 wheel before deletion, got %d", len(wheels))
	}

	// Delete the starter
	err = dhom.DeleteStarter(ctx, starterID)
	if err != nil {
		t.Fatalf("Failed to delete starter: %v", err)
	}

	// Verify they're gone
	_, err = dhom.LoadStarter(ctx, starterID)
	if err == nil {
		t.Error("Expected error loading deleted starter, got nil")
	}

	wheels, err = dhom.LoadWheelsForStarter(ctx, starterID)
	if err != nil {
		t.Fatalf("Failed to load wheels after deletion: %v", err)
	}
	if len(wheels) != 0 {
		t.Errorf("Expected 0 wheels after deletion, got %d", len(wheels))
	}
}

// TestDatabaseHeroicOPManager_HeroicOPInstance tests HO instance operations
func TestDatabaseHeroicOPManager_HeroicOPInstance(t *testing.T) {
	pool := createTestPool(t)
	defer pool.Close()

	dhom := NewDatabaseHeroicOPManager(pool)
	ctx := context.Background()

	// Create a test HO instance
	ho := &HeroicOP{
		ID:               1000,
		EncounterID:      500,
		StarterID:        10,
		WheelID:          20,
		State:            int8(HOStateWheelPhase),
		StartTime:        time.Now(),
		WheelStartTime:   time.Now().Add(5 * time.Second),
		TimeRemaining:    8000,
		TotalTime:        10000,
		Complete:         0,
		Countered:        [6]int8{1, 1, 0, 0, 0, 0},
		ShiftUsed:        0,
		StarterProgress:  3,
		CompletedBy:      0,
		SpellName:        "Test Spell",
		SpellDescription: "A test completion spell",
	}

	// Save the HO instance
	err := dhom.SaveHOInstance(ctx, ho)
	if err != nil {
		t.Fatalf("Failed to save HO instance: %v", err)
	}

	// Load and verify
	loaded, err := dhom.LoadHOInstance(ctx, 1000)
	if err != nil {
		t.Fatalf("Failed to load HO instance: %v", err)
	}

	if loaded.EncounterID != 500 {
		t.Errorf("Expected encounter ID 500, got %d", loaded.EncounterID)
	}
	if loaded.State != int8(HOStateWheelPhase) {
		t.Errorf("Expected state %d, got %d", HOStateWheelPhase, loaded.State)
	}
	if loaded.TimeRemaining != 8000 {
		t.Errorf("Expected time remaining 8000, got %d", loaded.TimeRemaining)
	}
	if loaded.SpellName != "Test Spell" {
		t.Errorf("Expected spell name 'Test Spell', got '%s'", loaded.SpellName)
	}

	// Delete the instance
	err = dhom.DeleteHOInstance(ctx, 1000)
	if err != nil {
		t.Fatalf("Failed to delete HO instance: %v", err)
	}

	// Verify it's gone
	_, err = dhom.LoadHOInstance(ctx, 1000)
	if err == nil {
		t.Error("Expected error loading deleted HO instance, got nil")
	}
}

// TestDatabaseHeroicOPManager_HeroicOPEvents tests HO event operations
func TestDatabaseHeroicOPManager_HeroicOPEvents(t *testing.T) {
	pool := createTestPool(t)
	defer pool.Close()

	dhom := NewDatabaseHeroicOPManager(pool)
	ctx := context.Background()

	instanceID := int64(2000)

	// Create test events
	events := []*HeroicOPEvent{
		{
			ID:          1,
			InstanceID:  instanceID,
			EventType:   EventHOStarted,
			CharacterID: 100,
			AbilityIcon: 50,
			Timestamp:   time.Now(),
			Data:        "started",
		},
		{
			ID:          2,
			InstanceID:  instanceID,
			EventType:   EventHOAbilityUsed,
			CharacterID: 101,
			AbilityIcon: 51,
			Timestamp:   time.Now().Add(1 * time.Second),
			Data:        "ability used",
		},
	}

	// Save events
	for _, event := range events {
		err := dhom.SaveHOEvent(ctx, event)
		if err != nil {
			t.Fatalf("Failed to save HO event: %v", err)
		}
	}

	// Load and verify
	loadedEvents, err := dhom.LoadHOEvents(ctx, instanceID)
	if err != nil {
		t.Fatalf("Failed to load HO events: %v", err)
	}

	if len(loadedEvents) != 2 {
		t.Errorf("Expected 2 events, got %d", len(loadedEvents))
	}

	// Events should be ordered by timestamp
	if len(loadedEvents) >= 2 {
		if loadedEvents[0].EventType != EventHOStarted {
			t.Errorf("Expected first event type %d, got %d", EventHOStarted, loadedEvents[0].EventType)
		}
		if loadedEvents[1].EventType != EventHOAbilityUsed {
			t.Errorf("Expected second event type %d, got %d", EventHOAbilityUsed, loadedEvents[1].EventType)
		}
	}
}

// TestDatabaseHeroicOPManager_Statistics tests HO statistics retrieval
func TestDatabaseHeroicOPManager_Statistics(t *testing.T) {
	pool := createTestPool(t)
	defer pool.Close()

	dhom := NewDatabaseHeroicOPManager(pool)
	ctx := context.Background()

	characterID := int32(1001)

	// Insert test events for statistics
	execSQL(t, pool, `INSERT INTO heroic_op_events 
		(id, instance_id, event_type, character_id, ability_icon, timestamp, data)
		VALUES (?, ?, ?, ?, ?, ?, ?)`,
		1, 100, EventHOStarted, characterID, 0, time.Now().Unix(), "")

	execSQL(t, pool, `INSERT INTO heroic_op_events 
		(id, instance_id, event_type, character_id, ability_icon, timestamp, data)
		VALUES (?, ?, ?, ?, ?, ?, ?)`,
		2, 100, EventHOCompleted, characterID, 0, time.Now().Add(10*time.Second).Unix(), "")

	execSQL(t, pool, `INSERT INTO heroic_op_events 
		(id, instance_id, event_type, character_id, ability_icon, timestamp, data)
		VALUES (?, ?, ?, ?, ?, ?, ?)`,
		3, 101, EventHOStarted, characterID, 0, time.Now().Add(20*time.Second).Unix(), "")

	// Get statistics
	stats, err := dhom.GetHOStatistics(ctx, characterID)
	if err != nil {
		t.Fatalf("Failed to get HO statistics: %v", err)
	}

	if stats.TotalHOsStarted != 2 {
		t.Errorf("Expected 2 HOs started, got %d", stats.TotalHOsStarted)
	}
	if stats.TotalHOsCompleted != 1 {
		t.Errorf("Expected 1 HO completed, got %d", stats.TotalHOsCompleted)
	}
	if stats.SuccessRate != 50.0 {
		t.Errorf("Expected success rate 50.0, got %f", stats.SuccessRate)
	}
}

// TestDatabaseHeroicOPManager_NextIDs tests ID generation
func TestDatabaseHeroicOPManager_NextIDs(t *testing.T) {
	pool := createTestPool(t)
	defer pool.Close()

	dhom := NewDatabaseHeroicOPManager(pool)
	ctx := context.Background()

	// Test next starter ID (should be 1 for empty database)
	starterID, err := dhom.GetNextStarterID(ctx)
	if err != nil {
		t.Fatalf("Failed to get next starter ID: %v", err)
	}
	if starterID != 1 {
		t.Errorf("Expected next starter ID 1, got %d", starterID)
	}

	// Insert a starter and test again
	execSQL(t, pool, `INSERT INTO heroic_ops 
		(id, ho_type, starter_class, starter_icon, starter_link_id, chain_order,
		 shift_icon, spell_id, chance, ability1, ability2, ability3, ability4,
		 ability5, ability6, name, description)
		VALUES (?, ?, ?, ?, 0, 0, 0, 0, 0.0, ?, ?, ?, ?, ?, ?, ?, ?)`,
		5, HOTypeStarter, 1, 100, 1, 2, 3, 4, 5, 6, "Test", "Test")

	starterID, err = dhom.GetNextStarterID(ctx)
	if err != nil {
		t.Fatalf("Failed to get next starter ID after insert: %v", err)
	}
	if starterID != 6 {
		t.Errorf("Expected next starter ID 6, got %d", starterID)
	}

	// Test next wheel ID
	wheelID, err := dhom.GetNextWheelID(ctx)
	if err != nil {
		t.Fatalf("Failed to get next wheel ID: %v", err)
	}
	if wheelID != 1 {
		t.Errorf("Expected next wheel ID 1, got %d", wheelID)
	}

	// Test next instance ID
	instanceID, err := dhom.GetNextInstanceID(ctx)
	if err != nil {
		t.Fatalf("Failed to get next instance ID: %v", err)
	}
	if instanceID != 1 {
		t.Errorf("Expected next instance ID 1, got %d", instanceID)
	}
}

// BenchmarkDatabaseHeroicOPManager_LoadStarters benchmarks loading starters
func BenchmarkDatabaseHeroicOPManager_LoadStarters(b *testing.B) {
	pool := createTestPool(&testing.T{})
	defer pool.Close()

	dhom := NewDatabaseHeroicOPManager(pool)
	ctx := context.Background()

	// Insert test data
	for i := 1; i <= 50; i++ {
		execSQL(&testing.T{}, pool, `INSERT INTO heroic_ops 
			(id, ho_type, starter_class, starter_icon, starter_link_id, chain_order,
			 shift_icon, spell_id, chance, ability1, ability2, ability3, ability4,
			 ability5, ability6, name, description)
			VALUES (?, ?, ?, ?, 0, 0, 0, 0, 0.0, ?, ?, ?, ?, ?, ?, ?, ?)`,
			i, HOTypeStarter, i%10+1, i*10, 
			i*1, i*2, i*3, i*4, i*5, i*6, 
			fmt.Sprintf("Starter %d", i), fmt.Sprintf("Description %d", i))
	}

	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		starters, err := dhom.LoadStarters(ctx)
		if err != nil {
			b.Fatalf("Failed to load starters: %v", err)
		}
		if len(starters) != 50 {
			b.Errorf("Expected 50 starters, got %d", len(starters))
		}
	}
}

// BenchmarkDatabaseHeroicOPManager_LoadWheels benchmarks loading wheels
func BenchmarkDatabaseHeroicOPManager_LoadWheels(b *testing.B) {
	pool := createTestPool(&testing.T{})
	defer pool.Close()

	dhom := NewDatabaseHeroicOPManager(pool)
	ctx := context.Background()

	// Insert test wheel data
	for i := 1; i <= 100; i++ {
		execSQL(&testing.T{}, pool, `INSERT INTO heroic_ops 
			(id, ho_type, starter_class, starter_icon, starter_link_id, chain_order,
			 shift_icon, spell_id, chance, ability1, ability2, ability3, ability4,
			 ability5, ability6, name, description)
			VALUES (?, ?, 0, 0, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
			i, HOTypeWheel, i%10+1, i%3+1, i*10, i*100+1000, float32(i%100)/100.0,
			i*1, i*2, i*3, i*4, i*5, i*6,
			fmt.Sprintf("Wheel %d", i), fmt.Sprintf("Wheel Description %d", i))
	}

	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		wheels, err := dhom.LoadWheels(ctx)
		if err != nil {
			b.Fatalf("Failed to load wheels: %v", err)
		}
		if len(wheels) != 100 {
			b.Errorf("Expected 100 wheels, got %d", len(wheels))
		}
	}
}

// BenchmarkDatabaseHeroicOPManager_SaveStarter benchmarks saving starters
func BenchmarkDatabaseHeroicOPManager_SaveStarter(b *testing.B) {
	pool := createTestPool(&testing.T{})
	defer pool.Close()

	dhom := NewDatabaseHeroicOPManager(pool)
	ctx := context.Background()

	starter := &HeroicOPStarter{
		ID:          1000,
		StartClass:  5,
		StarterIcon: 100,
		Abilities:   [6]int16{10, 20, 30, 40, 50, 60},
		Name:        "Benchmark Starter",
		Description: "A benchmark test starter",
	}

	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		err := dhom.SaveStarter(ctx, starter)
		if err != nil {
			b.Fatalf("Failed to save starter: %v", err)
		}
	}
}

// BenchmarkDatabaseHeroicOPManager_SaveHOInstance benchmarks saving HO instances
func BenchmarkDatabaseHeroicOPManager_SaveHOInstance(b *testing.B) {
	pool := createTestPool(&testing.T{})
	defer pool.Close()

	dhom := NewDatabaseHeroicOPManager(pool)
	ctx := context.Background()

	ho := &HeroicOP{
		ID:               5000,
		EncounterID:      1000,
		StarterID:        50,
		WheelID:          100,
		State:            int8(HOStateWheelPhase),
		StartTime:        time.Now(),
		WheelStartTime:   time.Now(),
		TimeRemaining:    10000,
		TotalTime:        10000,
		Complete:         0,
		Countered:        [6]int8{0, 0, 0, 0, 0, 0},
		ShiftUsed:        0,
		StarterProgress:  0,
		CompletedBy:      0,
		SpellName:        "Benchmark Spell",
		SpellDescription: "A benchmark spell",
	}

	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		err := dhom.SaveHOInstance(ctx, ho)
		if err != nil {
			b.Fatalf("Failed to save HO instance: %v", err)
		}
	}
}