package manager_test

import (
	"context"
	"encoding/json"
	"runtime"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/yaoapp/gou/model"
	"github.com/yaoapp/xun/capsule"
	agentcontext "github.com/yaoapp/yao/agent/context"
	"github.com/yaoapp/yao/agent/robot/executor"
	"github.com/yaoapp/yao/agent/robot/manager"
	"github.com/yaoapp/yao/agent/robot/pool"
	"github.com/yaoapp/yao/agent/robot/types"
	"github.com/yaoapp/yao/agent/testutils"
)

// TestManagerStartStop tests manager lifecycle
func TestManagerStartStop(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test")
	}

	testutils.Prepare(t)
	defer testutils.Clean(t)

	cleanupTestRobots(t)
	setupTestRobots(t)
	defer cleanupTestRobots(t)

	t.Run("start and stop manager", func(t *testing.T) {
		m := manager.New()

		// Should not be started
		assert.False(t, m.IsStarted())

		// Start manager
		err := m.Start()
		assert.NoError(t, err)
		assert.True(t, m.IsStarted())

		// Robots should be loaded
		assert.GreaterOrEqual(t, m.CachedRobots(), 2, "Should load at least 2 robots")

		// Stop manager
		err = m.Stop()
		assert.NoError(t, err)
		assert.False(t, m.IsStarted())
	})

	t.Run("double start should fail", func(t *testing.T) {
		m := manager.New()

		err := m.Start()
		assert.NoError(t, err)

		// Second start should fail
		err = m.Start()
		assert.Error(t, err)
		assert.Contains(t, err.Error(), "already started")

		// Cleanup
		m.Stop()
	})

	t.Run("stop without start should not panic", func(t *testing.T) {
		m := manager.New()

		assert.NotPanics(t, func() {
			err := m.Stop()
			assert.NoError(t, err)
		})
	})
}

// TestManagerTick tests the Tick function with different clock modes
func TestManagerTick(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test")
	}

	testutils.Prepare(t)
	defer testutils.Clean(t)

	cleanupTestRobots(t)
	setupTestRobotsWithClockConfig(t)
	defer cleanupTestRobots(t)

	t.Run("tick with times mode - matching time", func(t *testing.T) {
		config := &manager.Config{
			TickInterval: 100 * time.Millisecond,
			PoolConfig:   &pool.Config{WorkerSize: 2, QueueSize: 10},
			Executor:     executor.NewDryRun(),
		}
		m := manager.NewWithConfig(config)

		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		// Create a time that matches the configured time (09:00)
		loc, _ := time.LoadLocation("Asia/Shanghai")
		now := time.Date(2025, 1, 15, 9, 0, 0, 0, loc) // Wednesday 09:00

		ctx := types.NewContext(context.Background(), nil)
		err = m.Tick(ctx, now)
		assert.NoError(t, err)

		// Wait for job to be processed
		time.Sleep(200 * time.Millisecond)

		// Check that job was submitted (may be queued or running)
		// Note: The executor stub completes quickly, so we check execution count
		execCount := m.Executor().ExecCount()
		assert.GreaterOrEqual(t, execCount, 1, "Should have executed at least 1 job")
	})

	t.Run("tick with times mode - non-matching time", func(t *testing.T) {
		config := &manager.Config{
			TickInterval: 100 * time.Millisecond,
			PoolConfig:   &pool.Config{WorkerSize: 2, QueueSize: 10},
			Executor:     executor.NewDryRun(),
		}
		m := manager.NewWithConfig(config)

		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		// Reset executor count
		m.Executor().Reset()

		// Create a time that does NOT match (10:30)
		loc, _ := time.LoadLocation("Asia/Shanghai")
		now := time.Date(2025, 1, 15, 10, 30, 0, 0, loc) // Wednesday 10:30

		ctx := types.NewContext(context.Background(), nil)
		err = m.Tick(ctx, now)
		assert.NoError(t, err)

		// Wait a bit
		time.Sleep(100 * time.Millisecond)

		// Should not have triggered (times mode robot only triggers at 09:00, 14:00)
		execCount := m.Executor().ExecCount()
		// daemon always triggers, interval may trigger (LastRun=zero) => up to 2, but NOT 3
		assert.LessOrEqual(t, execCount, 2, "Times mode robot should not trigger at non-matching time")
	})

	t.Run("tick with interval mode", func(t *testing.T) {
		config := &manager.Config{
			TickInterval: 100 * time.Millisecond,
			PoolConfig:   &pool.Config{WorkerSize: 2, QueueSize: 10},
			Executor:     executor.NewDryRun(),
		}
		m := manager.NewWithConfig(config)

		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		// Reset executor count
		m.Executor().Reset()

		// First tick - should trigger interval mode robot (first run)
		ctx := types.NewContext(context.Background(), nil)
		now := time.Now()
		err = m.Tick(ctx, now)
		assert.NoError(t, err)

		// Wait for execution
		time.Sleep(200 * time.Millisecond)

		// Should have at least 1 execution (interval robot first run)
		execCount := m.Executor().ExecCount()
		assert.GreaterOrEqual(t, execCount, 1, "Interval mode robot should trigger on first run")
	})

	t.Run("tick skips paused robots", func(t *testing.T) {
		config := &manager.Config{
			TickInterval: 100 * time.Millisecond,
			PoolConfig:   &pool.Config{WorkerSize: 2, QueueSize: 10},
			Executor:     executor.NewDryRun(),
		}
		m := manager.NewWithConfig(config)

		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		// Get the paused robot from cache
		pausedRobot := m.Cache().Get("robot_test_manager_paused")
		assert.NotNil(t, pausedRobot)
		assert.Equal(t, types.RobotPaused, pausedRobot.Status)

		// Reset executor count
		m.Executor().Reset()

		// Tick should skip paused robot
		ctx := types.NewContext(context.Background(), nil)
		loc, _ := time.LoadLocation("Asia/Shanghai")
		now := time.Date(2025, 1, 15, 9, 0, 0, 0, loc)
		err = m.Tick(ctx, now)
		assert.NoError(t, err)

		// The paused robot should not have been triggered
		// (we can't directly verify this, but we verify the tick completed)
	})
}

// TestManagerTriggerManual tests manual triggering of robots
func TestManagerTriggerManual(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test")
	}

	testutils.Prepare(t)
	defer testutils.Clean(t)

	cleanupTestRobots(t)
	setupTestRobotsWithClockConfig(t)
	defer cleanupTestRobots(t)

	t.Run("trigger manual - success", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		ctx := types.NewContext(context.Background(), nil)

		// Manually trigger a robot
		execID, err := m.TriggerManual(ctx, "robot_test_manager_times", types.TriggerHuman, nil)
		assert.NoError(t, err)
		assert.NotEmpty(t, execID)

		// Wait for execution
		time.Sleep(200 * time.Millisecond)

		// Should have executed
		assert.GreaterOrEqual(t, m.Executor().ExecCount(), 1)
	})

	t.Run("trigger manual - robot not found", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		ctx := types.NewContext(context.Background(), nil)

		// Try to trigger non-existent robot
		_, err = m.TriggerManual(ctx, "robot_nonexistent", types.TriggerHuman, nil)
		assert.Error(t, err)
		assert.Equal(t, types.ErrRobotNotFound, err)
	})

	t.Run("trigger manual - robot paused", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		ctx := types.NewContext(context.Background(), nil)

		// Try to trigger paused robot
		_, err = m.TriggerManual(ctx, "robot_test_manager_paused", types.TriggerHuman, nil)
		assert.Error(t, err)
		assert.Equal(t, types.ErrRobotPaused, err)
	})

	t.Run("trigger manual - manager not started", func(t *testing.T) {
		m := manager.New()
		// Don't start manager

		ctx := types.NewContext(context.Background(), nil)

		_, err := m.TriggerManual(ctx, "robot_test_manager_times", types.TriggerHuman, nil)
		assert.Error(t, err)
		assert.Contains(t, err.Error(), "not started")
	})
}

// TestManagerClockModes tests all three clock modes
func TestManagerClockModes(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test")
	}

	testutils.Prepare(t)
	defer testutils.Clean(t)

	cleanupTestRobots(t)
	setupTestRobotsWithClockConfig(t)
	defer cleanupTestRobots(t)

	t.Run("times mode - day matching", func(t *testing.T) {
		m := manager.NewWithConfig(&manager.Config{Executor: executor.NewDryRun()})
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		m.Executor().Reset()

		// Wednesday (configured day)
		loc, _ := time.LoadLocation("Asia/Shanghai")
		now := time.Date(2025, 1, 15, 9, 0, 0, 0, loc) // Wednesday 09:00

		ctx := types.NewContext(context.Background(), nil)
		err = m.Tick(ctx, now)
		assert.NoError(t, err)

		time.Sleep(200 * time.Millisecond)
		assert.GreaterOrEqual(t, m.Executor().ExecCount(), 1, "Should trigger on matching day")
	})

	t.Run("times mode - day not matching", func(t *testing.T) {
		m := manager.NewWithConfig(&manager.Config{Executor: executor.NewDryRun()})
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		m.Executor().Reset()

		// Saturday (not configured)
		loc, _ := time.LoadLocation("Asia/Shanghai")
		now := time.Date(2025, 1, 18, 9, 0, 0, 0, loc) // Saturday 09:00

		ctx := types.NewContext(context.Background(), nil)
		err = m.Tick(ctx, now)
		assert.NoError(t, err)

		time.Sleep(100 * time.Millisecond)
		// Times mode robot should not trigger on Saturday
		// Only interval/daemon robots might trigger
	})

	t.Run("daemon mode - always triggers when idle", func(t *testing.T) {
		m := manager.NewWithConfig(&manager.Config{Executor: executor.NewDryRun()})
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		m.Executor().Reset()

		// Daemon robot should trigger whenever it can run
		ctx := types.NewContext(context.Background(), nil)
		now := time.Now()

		// First tick
		err = m.Tick(ctx, now)
		assert.NoError(t, err)

		time.Sleep(200 * time.Millisecond)

		// Should have triggered daemon robot
		assert.GreaterOrEqual(t, m.Executor().ExecCount(), 1, "Daemon mode should trigger")
	})
}

// TestManagerTimezoneDedup tests that times mode dedup works correctly across timezones
// This specifically tests the bug fix where LastRun.Day() must be converted to the same
// timezone as 'now' before comparison
func TestManagerTimezoneDedup(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test")
	}

	testutils.Prepare(t)
	defer testutils.Clean(t)

	cleanupTestRobots(t)
	setupTestRobotsWithClockConfig(t)
	defer cleanupTestRobots(t)

	t.Run("times mode - same minute same day should not trigger twice", func(t *testing.T) {
		m := manager.NewWithConfig(&manager.Config{Executor: executor.NewDryRun()})
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		m.Executor().Reset()

		// Use Asia/Shanghai timezone (UTC+8)
		loc, _ := time.LoadLocation("Asia/Shanghai")
		// Wednesday 09:00:00 in Shanghai
		now := time.Date(2025, 1, 15, 9, 0, 0, 0, loc)

		ctx := types.NewContext(context.Background(), nil)

		// First tick - should trigger
		err = m.Tick(ctx, now)
		assert.NoError(t, err)
		time.Sleep(200 * time.Millisecond)
		firstCount := m.Executor().ExecCount()
		assert.GreaterOrEqual(t, firstCount, 1, "First tick should trigger")

		// Second tick at 09:00:30 (same minute) - should NOT trigger again
		now2 := time.Date(2025, 1, 15, 9, 0, 30, 0, loc)
		err = m.Tick(ctx, now2)
		assert.NoError(t, err)
		time.Sleep(200 * time.Millisecond)

		// Count should remain the same (times robot should not trigger twice)
		// Note: daemon/interval robots may still trigger, so we check the delta
		secondCount := m.Executor().ExecCount()
		t.Logf("First count: %d, Second count: %d", firstCount, secondCount)

		// The times robot should not have triggered again in the same minute
		// Delta should be <= 2 (daemon always triggers, interval might trigger)
		// If delta > 2, it means times robot triggered twice (bug!)
		delta := secondCount - firstCount
		assert.LessOrEqual(t, delta, 2, "Times robot should not trigger twice in same minute (delta: %d)", delta)
	})

	t.Run("times mode - different day should trigger again", func(t *testing.T) {
		m := manager.NewWithConfig(&manager.Config{Executor: executor.NewDryRun()})
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		m.Executor().Reset()

		loc, _ := time.LoadLocation("Asia/Shanghai")

		ctx := types.NewContext(context.Background(), nil)

		// Wednesday 09:00
		now1 := time.Date(2025, 1, 15, 9, 0, 0, 0, loc)
		err = m.Tick(ctx, now1)
		assert.NoError(t, err)
		time.Sleep(200 * time.Millisecond)
		firstCount := m.Executor().ExecCount()

		// Thursday 09:00 (next day, same time)
		now2 := time.Date(2025, 1, 16, 9, 0, 0, 0, loc)
		err = m.Tick(ctx, now2)
		assert.NoError(t, err)
		time.Sleep(200 * time.Millisecond)

		// Should have triggered again on the new day
		secondCount := m.Executor().ExecCount()
		assert.Greater(t, secondCount, firstCount, "Should trigger on different day")
	})

	t.Run("times mode - cross-timezone day boundary", func(t *testing.T) {
		m := manager.NewWithConfig(&manager.Config{Executor: executor.NewDryRun()})
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		m.Executor().Reset()

		// Robot is configured with Asia/Shanghai (UTC+8)
		// Test case: LastRun was set when it was Jan 15 in Shanghai
		// Now it's Jan 16 00:30 in Shanghai (still Jan 15 in UTC)
		// The comparison should use Shanghai timezone, not UTC

		loc, _ := time.LoadLocation("Asia/Shanghai")
		ctx := types.NewContext(context.Background(), nil)

		// First run: Jan 15, 09:00 Shanghai time
		now1 := time.Date(2025, 1, 15, 9, 0, 0, 0, loc)
		err = m.Tick(ctx, now1)
		assert.NoError(t, err)
		time.Sleep(200 * time.Millisecond)

		// Second run: Jan 16, 09:00 Shanghai time
		// This is Jan 16 01:00 UTC, but should be treated as Jan 16 in Shanghai
		now2 := time.Date(2025, 1, 16, 9, 0, 0, 0, loc)
		err = m.Tick(ctx, now2)
		assert.NoError(t, err)
		time.Sleep(200 * time.Millisecond)

		// Should have triggered on both days
		assert.GreaterOrEqual(t, m.Executor().ExecCount(), 2, "Should trigger on both days")
	})

	t.Run("times mode - UTC vs local timezone comparison", func(t *testing.T) {
		m := manager.NewWithConfig(&manager.Config{Executor: executor.NewDryRun()})
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		m.Executor().Reset()

		// Test with explicit UTC time converted to Shanghai
		// This tests that LastRun stored in one timezone is correctly
		// compared when 'now' is in a different timezone

		shanghai, _ := time.LoadLocation("Asia/Shanghai")
		ctx := types.NewContext(context.Background(), nil)

		// Create a time that's Jan 15 23:30 UTC = Jan 16 07:30 Shanghai
		utcTime := time.Date(2025, 1, 15, 23, 30, 0, 0, time.UTC)
		shanghaiTime := utcTime.In(shanghai)
		t.Logf("UTC: %v, Shanghai: %v", utcTime, shanghaiTime)

		// The robot is configured for 09:00 Shanghai time
		// So Jan 16 09:00 Shanghai should trigger
		now := time.Date(2025, 1, 16, 9, 0, 0, 0, shanghai)
		err = m.Tick(ctx, now)
		assert.NoError(t, err)
		time.Sleep(200 * time.Millisecond)

		assert.GreaterOrEqual(t, m.Executor().ExecCount(), 1, "Should trigger at 09:00 Shanghai")
	})
}

// TestManagerGoroutineLeak tests that manager doesn't leak goroutines
func TestManagerGoroutineLeak(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test")
	}

	testutils.Prepare(t)
	defer testutils.Clean(t)

	cleanupTestRobots(t)
	setupTestRobots(t)
	defer cleanupTestRobots(t)

	t.Run("start stop cycle should not leak goroutines", func(t *testing.T) {
		// Record initial goroutine count
		runtime.GC()
		time.Sleep(100 * time.Millisecond)
		initialGoroutines := runtime.NumGoroutine()

		// Start and stop multiple times
		for i := 0; i < 5; i++ {
			m := manager.New()
			err := m.Start()
			assert.NoError(t, err)

			// Do some ticks
			ctx := types.NewContext(context.Background(), nil)
			m.Tick(ctx, time.Now())

			time.Sleep(50 * time.Millisecond)

			err = m.Stop()
			assert.NoError(t, err)
		}

		// Wait for cleanup
		time.Sleep(200 * time.Millisecond)
		runtime.GC()
		time.Sleep(100 * time.Millisecond)

		// Check goroutine count
		finalGoroutines := runtime.NumGoroutine()
		assert.LessOrEqual(t, finalGoroutines, initialGoroutines+2,
			"Should not leak goroutines (initial: %d, final: %d)",
			initialGoroutines, finalGoroutines)
	})
}

// TestManagerComponents tests access to internal components
func TestManagerComponents(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test")
	}

	testutils.Prepare(t)
	defer testutils.Clean(t)

	cleanupTestRobots(t)
	setupTestRobots(t)
	defer cleanupTestRobots(t)

	m := manager.New()
	err := m.Start()
	assert.NoError(t, err)
	defer m.Stop()

	t.Run("cache access", func(t *testing.T) {
		cache := m.Cache()
		assert.NotNil(t, cache)

		robot := cache.Get("robot_test_sales_001")
		assert.NotNil(t, robot)
	})

	t.Run("pool access", func(t *testing.T) {
		pool := m.Pool()
		assert.NotNil(t, pool)
		assert.True(t, pool.IsStarted())
	})

	t.Run("executor access", func(t *testing.T) {
		executor := m.Executor()
		assert.NotNil(t, executor)
	})

	t.Run("running and queued counts", func(t *testing.T) {
		running := m.Running()
		queued := m.Queued()
		cached := m.CachedRobots()

		assert.GreaterOrEqual(t, running, 0)
		assert.GreaterOrEqual(t, queued, 0)
		assert.GreaterOrEqual(t, cached, 2)
	})
}

// ==================== Test Data Setup ====================

// setupTestRobots creates basic test robots (same as cache tests)
func setupTestRobots(t *testing.T) {
	m := model.Select("__yao.member")
	tableName := m.MetaData.Table.Name
	qb := capsule.Query()

	// Robot 1: Sales Bot
	robotConfig1 := map[string]interface{}{
		"identity": map[string]interface{}{
			"role":   "Sales Manager",
			"duties": []string{"Manage leads", "Follow up customers"},
		},
		"quota": map[string]interface{}{
			"max":      3,
			"queue":    15,
			"priority": 7,
		},
		"triggers": map[string]interface{}{
			"clock": map[string]interface{}{"enabled": true},
		},
		"clock": map[string]interface{}{
			"mode":  "times",
			"times": []string{"09:00", "14:00"},
			"days":  []string{"Mon", "Tue", "Wed", "Thu", "Fri"},
			"tz":    "Asia/Shanghai",
		},
	}
	config1JSON, _ := json.Marshal(robotConfig1)

	err := qb.Table(tableName).Insert([]map[string]interface{}{
		{
			"member_id":       "robot_test_sales_001",
			"team_id":         "team_test_cache_001",
			"member_type":     "robot",
			"display_name":    "Test Sales Bot",
			"system_prompt":   "You are a professional sales manager assistant.",
			"status":          "active",
			"role_id":         "member",
			"autonomous_mode": true,
			"robot_status":    "idle",
			"robot_config":    string(config1JSON),
		},
	})
	if err != nil {
		t.Fatalf("Failed to insert robot_test_sales_001: %v", err)
	}

	// Robot 2: Support Bot
	robotConfig2 := map[string]interface{}{
		"identity": map[string]interface{}{
			"role":   "Customer Support",
			"duties": []string{"Answer questions", "Resolve issues"},
		},
		"quota": map[string]interface{}{
			"max":      2,
			"queue":    10,
			"priority": 5,
		},
		"triggers": map[string]interface{}{
			"clock": map[string]interface{}{"enabled": true},
		},
		"clock": map[string]interface{}{
			"mode":  "interval",
			"every": "1h",
		},
	}
	config2JSON, _ := json.Marshal(robotConfig2)

	err = qb.Table(tableName).Insert([]map[string]interface{}{
		{
			"member_id":       "robot_test_support_002",
			"team_id":         "team_test_cache_001",
			"member_type":     "robot",
			"display_name":    "Test Support Bot",
			"system_prompt":   "You are a helpful customer support assistant.",
			"status":          "active",
			"role_id":         "member",
			"autonomous_mode": true,
			"robot_status":    "idle",
			"robot_config":    string(config2JSON),
		},
	})
	if err != nil {
		t.Fatalf("Failed to insert robot_test_support_002: %v", err)
	}

	// Robot 3: Inactive robot
	err = qb.Table(tableName).Insert([]map[string]interface{}{
		{
			"member_id":       "robot_test_inactive_003",
			"team_id":         "team_test_cache_001",
			"member_type":     "robot",
			"display_name":    "Test Inactive Bot",
			"status":          "inactive",
			"role_id":         "member",
			"autonomous_mode": true,
			"robot_status":    "paused",
		},
	})
	if err != nil {
		t.Fatalf("Failed to insert robot_test_inactive_003: %v", err)
	}
}

// setupTestRobotsWithClockConfig creates robots with specific clock configurations
func setupTestRobotsWithClockConfig(t *testing.T) {
	m := model.Select("__yao.member")
	tableName := m.MetaData.Table.Name
	qb := capsule.Query()

	// Robot 1: Times mode (09:00, 14:00 on weekdays)
	robotConfigTimes := map[string]interface{}{
		"identity": map[string]interface{}{
			"role": "Times Mode Robot",
		},
		"quota": map[string]interface{}{
			"max": 2,
		},
		"triggers": map[string]interface{}{
			"clock": map[string]interface{}{"enabled": true},
		},
		"clock": map[string]interface{}{
			"mode":  "times",
			"times": []string{"09:00", "14:00"},
			"days":  []string{"Mon", "Tue", "Wed", "Thu", "Fri"},
			"tz":    "Asia/Shanghai",
		},
	}
	configTimesJSON, _ := json.Marshal(robotConfigTimes)

	err := qb.Table(tableName).Insert([]map[string]interface{}{
		{
			"member_id":       "robot_test_manager_times",
			"team_id":         "team_test_manager",
			"member_type":     "robot",
			"display_name":    "Test Times Robot",
			"status":          "active",
			"role_id":         "member",
			"autonomous_mode": true,
			"robot_status":    "idle",
			"robot_config":    string(configTimesJSON),
		},
	})
	if err != nil {
		t.Fatalf("Failed to insert robot_test_manager_times: %v", err)
	}

	// Robot 2: Interval mode (every 30 minutes)
	robotConfigInterval := map[string]interface{}{
		"identity": map[string]interface{}{
			"role": "Interval Mode Robot",
		},
		"quota": map[string]interface{}{
			"max": 2,
		},
		"triggers": map[string]interface{}{
			"clock": map[string]interface{}{"enabled": true},
		},
		"clock": map[string]interface{}{
			"mode":  "interval",
			"every": "30m",
		},
	}
	configIntervalJSON, _ := json.Marshal(robotConfigInterval)

	err = qb.Table(tableName).Insert([]map[string]interface{}{
		{
			"member_id":       "robot_test_manager_interval",
			"team_id":         "team_test_manager",
			"member_type":     "robot",
			"display_name":    "Test Interval Robot",
			"status":          "active",
			"role_id":         "member",
			"autonomous_mode": true,
			"robot_status":    "idle",
			"robot_config":    string(configIntervalJSON),
		},
	})
	if err != nil {
		t.Fatalf("Failed to insert robot_test_manager_interval: %v", err)
	}

	// Robot 3: Daemon mode
	robotConfigDaemon := map[string]interface{}{
		"identity": map[string]interface{}{
			"role": "Daemon Mode Robot",
		},
		"quota": map[string]interface{}{
			"max": 2,
		},
		"triggers": map[string]interface{}{
			"clock": map[string]interface{}{"enabled": true},
		},
		"clock": map[string]interface{}{
			"mode":    "daemon",
			"timeout": "5m",
		},
	}
	configDaemonJSON, _ := json.Marshal(robotConfigDaemon)

	err = qb.Table(tableName).Insert([]map[string]interface{}{
		{
			"member_id":       "robot_test_manager_daemon",
			"team_id":         "team_test_manager",
			"member_type":     "robot",
			"display_name":    "Test Daemon Robot",
			"status":          "active",
			"role_id":         "member",
			"autonomous_mode": true,
			"robot_status":    "idle",
			"robot_config":    string(configDaemonJSON),
		},
	})
	if err != nil {
		t.Fatalf("Failed to insert robot_test_manager_daemon: %v", err)
	}

	// Robot 4: Paused robot (should be skipped)
	robotConfigPaused := map[string]interface{}{
		"identity": map[string]interface{}{
			"role": "Paused Robot",
		},
		"triggers": map[string]interface{}{
			"clock": map[string]interface{}{"enabled": true},
		},
		"clock": map[string]interface{}{
			"mode":  "times",
			"times": []string{"09:00"},
			"tz":    "Asia/Shanghai",
		},
	}
	configPausedJSON, _ := json.Marshal(robotConfigPaused)

	err = qb.Table(tableName).Insert([]map[string]interface{}{
		{
			"member_id":       "robot_test_manager_paused",
			"team_id":         "team_test_manager",
			"member_type":     "robot",
			"display_name":    "Test Paused Robot",
			"status":          "active",
			"role_id":         "member",
			"autonomous_mode": true,
			"robot_status":    "paused",
			"robot_config":    string(configPausedJSON),
		},
	})
	if err != nil {
		t.Fatalf("Failed to insert robot_test_manager_paused: %v", err)
	}

	// Robot 5: Clock disabled robot
	robotConfigDisabled := map[string]interface{}{
		"identity": map[string]interface{}{
			"role": "Clock Disabled Robot",
		},
		"triggers": map[string]interface{}{
			"clock": map[string]interface{}{"enabled": false},
		},
		"clock": map[string]interface{}{
			"mode":  "times",
			"times": []string{"09:00"},
		},
	}
	configDisabledJSON, _ := json.Marshal(robotConfigDisabled)

	err = qb.Table(tableName).Insert([]map[string]interface{}{
		{
			"member_id":       "robot_test_manager_disabled",
			"team_id":         "team_test_manager",
			"member_type":     "robot",
			"display_name":    "Test Clock Disabled Robot",
			"status":          "active",
			"role_id":         "member",
			"autonomous_mode": true,
			"robot_status":    "idle",
			"robot_config":    string(configDisabledJSON),
		},
	})
	if err != nil {
		t.Fatalf("Failed to insert robot_test_manager_disabled: %v", err)
	}
}

// ==================== Intervene Tests ====================

func TestManagerIntervene(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test")
	}

	testutils.Prepare(t)
	defer testutils.Clean(t)

	cleanupTestRobots(t)
	setupTestRobotsWithInterveneConfig(t)
	defer cleanupTestRobots(t)

	t.Run("intervene success", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		ctx := types.NewContext(context.Background(), nil)
		req := &types.InterveneRequest{
			TeamID:   "team_test_manager",
			MemberID: "robot_test_manager_intervene",
			Action:   types.ActionTaskAdd,
			Messages: []agentcontext.Message{
				{Role: agentcontext.RoleUser, Content: "Add a new task"},
			},
		}

		result, err := m.Intervene(ctx, req)
		assert.NoError(t, err)
		assert.NotNil(t, result)
		assert.NotEmpty(t, result.ExecutionID)
		assert.Equal(t, types.ExecPending, result.Status)
	})

	t.Run("intervene - manager not started", func(t *testing.T) {
		m := manager.New()
		// Don't start

		ctx := types.NewContext(context.Background(), nil)
		req := &types.InterveneRequest{
			MemberID: "robot_test_manager_intervene",
			Action:   types.ActionTaskAdd,
			Messages: []agentcontext.Message{
				{Role: agentcontext.RoleUser, Content: "Add a new task"},
			},
		}

		_, err := m.Intervene(ctx, req)
		assert.Error(t, err)
		assert.Contains(t, err.Error(), "not started")
	})

	t.Run("intervene - robot not found", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		ctx := types.NewContext(context.Background(), nil)
		req := &types.InterveneRequest{
			MemberID: "non_existent_robot",
			Action:   types.ActionTaskAdd,
			Messages: []agentcontext.Message{
				{Role: agentcontext.RoleUser, Content: "Add a new task"},
			},
		}

		_, err = m.Intervene(ctx, req)
		assert.Error(t, err)
		assert.Equal(t, types.ErrRobotNotFound, err)
	})

	t.Run("intervene - robot paused", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		ctx := types.NewContext(context.Background(), nil)
		req := &types.InterveneRequest{
			MemberID: "robot_test_manager_paused",
			Action:   types.ActionTaskAdd,
			Messages: []agentcontext.Message{
				{Role: agentcontext.RoleUser, Content: "Add a new task"},
			},
		}

		_, err = m.Intervene(ctx, req)
		assert.Error(t, err)
		assert.Equal(t, types.ErrRobotPaused, err)
	})

	t.Run("intervene - invalid request", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		ctx := types.NewContext(context.Background(), nil)
		req := &types.InterveneRequest{
			MemberID: "", // Invalid: empty member_id
			Action:   types.ActionTaskAdd,
		}

		_, err = m.Intervene(ctx, req)
		assert.Error(t, err)
		assert.Contains(t, err.Error(), "member_id")
	})

	t.Run("intervene - trigger disabled", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		ctx := types.NewContext(context.Background(), nil)
		req := &types.InterveneRequest{
			MemberID: "robot_test_manager_intervene_disabled",
			Action:   types.ActionTaskAdd,
			Messages: []agentcontext.Message{
				{Role: agentcontext.RoleUser, Content: "Add a new task"},
			},
		}

		_, err = m.Intervene(ctx, req)
		assert.Error(t, err)
		assert.Equal(t, types.ErrTriggerDisabled, err)
	})
}

// ==================== HandleEvent Tests ====================

func TestManagerHandleEvent(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test")
	}

	testutils.Prepare(t)
	defer testutils.Clean(t)

	cleanupTestRobots(t)
	setupTestRobotsWithEventConfig(t)
	defer cleanupTestRobots(t)

	t.Run("handle event success", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		ctx := types.NewContext(context.Background(), nil)
		req := &types.EventRequest{
			MemberID:  "robot_test_manager_event",
			Source:    "webhook",
			EventType: "lead.created",
			Data:      map[string]interface{}{"name": "John", "email": "john@example.com"},
		}

		result, err := m.HandleEvent(ctx, req)
		assert.NoError(t, err)
		assert.NotNil(t, result)
		assert.NotEmpty(t, result.ExecutionID)
		assert.Equal(t, types.ExecPending, result.Status)
	})

	t.Run("handle event - manager not started", func(t *testing.T) {
		m := manager.New()
		// Don't start

		ctx := types.NewContext(context.Background(), nil)
		req := &types.EventRequest{
			MemberID:  "robot_test_manager_event",
			Source:    "webhook",
			EventType: "lead.created",
		}

		_, err := m.HandleEvent(ctx, req)
		assert.Error(t, err)
		assert.Contains(t, err.Error(), "not started")
	})

	t.Run("handle event - robot not found", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		ctx := types.NewContext(context.Background(), nil)
		req := &types.EventRequest{
			MemberID:  "non_existent_robot",
			Source:    "webhook",
			EventType: "lead.created",
		}

		_, err = m.HandleEvent(ctx, req)
		assert.Error(t, err)
		assert.Equal(t, types.ErrRobotNotFound, err)
	})

	t.Run("handle event - invalid request", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		ctx := types.NewContext(context.Background(), nil)
		req := &types.EventRequest{
			MemberID:  "robot_test_manager_event",
			Source:    "", // Invalid: empty source
			EventType: "lead.created",
		}

		_, err = m.HandleEvent(ctx, req)
		assert.Error(t, err)
		assert.Contains(t, err.Error(), "source")
	})

	t.Run("handle event - trigger disabled", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		ctx := types.NewContext(context.Background(), nil)
		req := &types.EventRequest{
			MemberID:  "robot_test_manager_event_disabled",
			Source:    "webhook",
			EventType: "lead.created",
		}

		_, err = m.HandleEvent(ctx, req)
		assert.Error(t, err)
		assert.Equal(t, types.ErrTriggerDisabled, err)
	})
}

// ==================== Execution Control Tests ====================

func TestManagerExecutionControl(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test")
	}

	testutils.Prepare(t)
	defer testutils.Clean(t)

	cleanupTestRobots(t)
	setupTestRobotsWithInterveneConfig(t)
	defer cleanupTestRobots(t)

	t.Run("pause and resume execution", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		// Trigger an execution
		ctx := types.NewContext(context.Background(), nil)
		req := &types.InterveneRequest{
			MemberID: "robot_test_manager_intervene",
			Action:   types.ActionTaskAdd,
			Messages: []agentcontext.Message{
				{Role: agentcontext.RoleUser, Content: "Test task"},
			},
		}

		result, err := m.Intervene(ctx, req)
		assert.NoError(t, err)
		execID := result.ExecutionID

		// Wait a bit for execution to be tracked
		time.Sleep(50 * time.Millisecond)

		// Pause
		err = m.PauseExecution(ctx, execID)
		assert.NoError(t, err)

		// Get status - should be paused
		status, err := m.GetExecutionStatus(execID)
		assert.NoError(t, err)
		assert.True(t, status.IsPaused())

		// Resume
		err = m.ResumeExecution(ctx, execID)
		assert.NoError(t, err)

		// Get status - should not be paused
		status, err = m.GetExecutionStatus(execID)
		assert.NoError(t, err)
		assert.False(t, status.IsPaused())
	})

	t.Run("stop execution", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		// Trigger an execution
		ctx := types.NewContext(context.Background(), nil)
		req := &types.InterveneRequest{
			MemberID: "robot_test_manager_intervene",
			Action:   types.ActionTaskAdd,
			Messages: []agentcontext.Message{
				{Role: agentcontext.RoleUser, Content: "Test task"},
			},
		}

		result, err := m.Intervene(ctx, req)
		assert.NoError(t, err)
		execID := result.ExecutionID

		// Wait a bit for execution to be tracked
		time.Sleep(50 * time.Millisecond)

		// Stop
		err = m.StopExecution(ctx, execID)
		assert.NoError(t, err)

		// Get status - should not be found (removed after stop)
		_, err = m.GetExecutionStatus(execID)
		assert.Error(t, err)
		assert.Contains(t, err.Error(), "not found")
	})

	t.Run("list executions", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		ctx := types.NewContext(context.Background(), nil)

		// Track execution IDs
		var execIDs []string

		// Trigger multiple executions
		for i := 0; i < 3; i++ {
			req := &types.InterveneRequest{
				MemberID: "robot_test_manager_intervene",
				Action:   types.ActionTaskAdd,
				Messages: []agentcontext.Message{
					{Role: agentcontext.RoleUser, Content: "Test task"},
				},
			}
			result, err := m.Intervene(ctx, req)
			assert.NoError(t, err)
			execIDs = append(execIDs, result.ExecutionID)
		}

		// Verify each execution was tracked (even if briefly)
		// Note: executions complete quickly with stub executor, so they may be removed
		// We just verify that we got valid execution IDs
		assert.Len(t, execIDs, 3)
		for _, id := range execIDs {
			assert.NotEmpty(t, id)
		}
	})
}

// setupTestRobotsWithInterveneConfig creates test robots with intervene trigger enabled
func setupTestRobotsWithInterveneConfig(t *testing.T) {
	// First setup the basic robots
	setupTestRobotsWithClockConfig(t)

	// Add robots for intervene tests
	qb := capsule.Query()
	m := model.Select("__yao.member")
	tableName := m.MetaData.Table.Name

	// Robot with intervene enabled
	robotConfigIntervene := map[string]interface{}{
		"identity": map[string]interface{}{
			"role": "Intervene Test Robot",
		},
		"triggers": map[string]interface{}{
			"clock":     map[string]interface{}{"enabled": false},
			"intervene": map[string]interface{}{"enabled": true},
		},
		"quota": map[string]interface{}{
			"max":   5,
			"queue": 10,
		},
	}
	configInterveneJSON, _ := json.Marshal(robotConfigIntervene)

	err := qb.Table(tableName).Insert([]map[string]interface{}{
		{
			"member_id":       "robot_test_manager_intervene",
			"team_id":         "team_test_manager",
			"member_type":     "robot",
			"display_name":    "Test Intervene Robot",
			"status":          "active",
			"role_id":         "member",
			"autonomous_mode": true,
			"robot_status":    "idle",
			"robot_config":    string(configInterveneJSON),
		},
	})
	if err != nil {
		t.Fatalf("Failed to insert robot_test_manager_intervene: %v", err)
	}

	// Robot with intervene disabled
	robotConfigInterveneDisabled := map[string]interface{}{
		"identity": map[string]interface{}{
			"role": "Intervene Disabled Robot",
		},
		"triggers": map[string]interface{}{
			"clock":     map[string]interface{}{"enabled": false},
			"intervene": map[string]interface{}{"enabled": false},
		},
	}
	configInterveneDisabledJSON, _ := json.Marshal(robotConfigInterveneDisabled)

	err = qb.Table(tableName).Insert([]map[string]interface{}{
		{
			"member_id":       "robot_test_manager_intervene_disabled",
			"team_id":         "team_test_manager",
			"member_type":     "robot",
			"display_name":    "Test Intervene Disabled Robot",
			"status":          "active",
			"role_id":         "member",
			"autonomous_mode": true,
			"robot_status":    "idle",
			"robot_config":    string(configInterveneDisabledJSON),
		},
	})
	if err != nil {
		t.Fatalf("Failed to insert robot_test_manager_intervene_disabled: %v", err)
	}
}

// setupTestRobotsWithEventConfig creates test robots with event trigger enabled
func setupTestRobotsWithEventConfig(t *testing.T) {
	// First setup the basic robots
	setupTestRobotsWithClockConfig(t)

	// Add robots for event tests
	qb := capsule.Query()
	m := model.Select("__yao.member")
	tableName := m.MetaData.Table.Name

	// Robot with event enabled
	robotConfigEvent := map[string]interface{}{
		"identity": map[string]interface{}{
			"role": "Event Test Robot",
		},
		"triggers": map[string]interface{}{
			"clock": map[string]interface{}{"enabled": false},
			"event": map[string]interface{}{"enabled": true},
		},
		"quota": map[string]interface{}{
			"max":   5,
			"queue": 10,
		},
	}
	configEventJSON, _ := json.Marshal(robotConfigEvent)

	err := qb.Table(tableName).Insert([]map[string]interface{}{
		{
			"member_id":       "robot_test_manager_event",
			"team_id":         "team_test_manager",
			"member_type":     "robot",
			"display_name":    "Test Event Robot",
			"status":          "active",
			"role_id":         "member",
			"autonomous_mode": true,
			"robot_status":    "idle",
			"robot_config":    string(configEventJSON),
		},
	})
	if err != nil {
		t.Fatalf("Failed to insert robot_test_manager_event: %v", err)
	}

	// Robot with event disabled
	robotConfigEventDisabled := map[string]interface{}{
		"identity": map[string]interface{}{
			"role": "Event Disabled Robot",
		},
		"triggers": map[string]interface{}{
			"clock": map[string]interface{}{"enabled": false},
			"event": map[string]interface{}{"enabled": false},
		},
	}
	configEventDisabledJSON, _ := json.Marshal(robotConfigEventDisabled)

	err = qb.Table(tableName).Insert([]map[string]interface{}{
		{
			"member_id":       "robot_test_manager_event_disabled",
			"team_id":         "team_test_manager",
			"member_type":     "robot",
			"display_name":    "Test Event Disabled Robot",
			"status":          "active",
			"role_id":         "member",
			"autonomous_mode": true,
			"robot_status":    "idle",
			"robot_config":    string(configEventDisabledJSON),
		},
	})
	if err != nil {
		t.Fatalf("Failed to insert robot_test_manager_event_disabled: %v", err)
	}
}

// ==================== Lazy Load Tests for Non-Autonomous Robots ====================

// TestManagerLazyLoadNonAutonomous tests that non-autonomous robots are pre-loaded
// into cache (full-cache load) and can be triggered/intervened/evented normally.
func TestManagerLazyLoadNonAutonomous(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test")
	}

	testutils.Prepare(t)
	defer testutils.Clean(t)

	cleanupTestRobots(t)
	setupTestRobotsWithNonAutonomous(t)
	defer cleanupTestRobots(t)

	t.Run("non-autonomous robot is in cache after full load", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		// With full-cache load, non-autonomous active robots are now in cache
		robot := m.Cache().Get("robot_test_manager_on_demand")
		assert.NotNil(t, robot, "Non-autonomous active robot should be in cache after full load")
		if robot != nil {
			assert.False(t, robot.AutonomousMode)
		}

		// Autonomous robot SHOULD also be in cache
		autoRobot := m.Cache().Get("robot_test_manager_times")
		assert.NotNil(t, autoRobot, "Autonomous robot should be in cache")
	})

	t.Run("TriggerManual works for non-autonomous robot in cache", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		ctx := types.NewContext(context.Background(), nil)

		// Robot is already in cache after full load
		assert.NotNil(t, m.Cache().Get("robot_test_manager_on_demand"))

		// Trigger the non-autonomous robot manually
		execID, err := m.TriggerManual(ctx, "robot_test_manager_on_demand", types.TriggerHuman, nil)
		assert.NoError(t, err)
		assert.NotEmpty(t, execID)

		// Robot should still be in cache
		robot := m.Cache().Get("robot_test_manager_on_demand")
		assert.NotNil(t, robot, "Robot should remain in cache")
		assert.Equal(t, "robot_test_manager_on_demand", robot.MemberID)
		assert.False(t, robot.AutonomousMode)
	})

	t.Run("Intervene works for non-autonomous robot in cache", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		ctx := types.NewContext(context.Background(), nil)

		// Robot is already in cache after full load
		assert.NotNil(t, m.Cache().Get("robot_test_manager_on_demand_intervene"))

		// Intervene on the non-autonomous robot
		req := &types.InterveneRequest{
			TeamID:   "team_test_manager",
			MemberID: "robot_test_manager_on_demand_intervene",
			Action:   types.ActionTaskAdd,
			Messages: []agentcontext.Message{
				{Role: agentcontext.RoleUser, Content: "Test intervene on cached non-autonomous robot"},
			},
		}

		result, err := m.Intervene(ctx, req)
		assert.NoError(t, err)
		assert.NotEmpty(t, result.ExecutionID)

		// Robot should still be in cache
		robot := m.Cache().Get("robot_test_manager_on_demand_intervene")
		assert.NotNil(t, robot, "Robot should remain in cache after Intervene")
	})

	t.Run("HandleEvent works for non-autonomous robot in cache", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		ctx := types.NewContext(context.Background(), nil)

		// Robot is already in cache after full load
		assert.NotNil(t, m.Cache().Get("robot_test_manager_on_demand_event"))

		// Send event to the non-autonomous robot
		req := &types.EventRequest{
			MemberID:  "robot_test_manager_on_demand_event",
			Source:    "webhook",
			EventType: "data.updated",
			Data:      map[string]interface{}{"test": true},
		}

		result, err := m.HandleEvent(ctx, req)
		assert.NoError(t, err)
		assert.NotEmpty(t, result.ExecutionID)

		// Robot should still be in cache
		robot := m.Cache().Get("robot_test_manager_on_demand_event")
		assert.NotNil(t, robot, "Robot should remain in cache after HandleEvent")
	})

	t.Run("non-autonomous robot stays in cache after execution completes", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		ctx := types.NewContext(context.Background(), nil)

		// Trigger the non-autonomous robot
		_, err = m.TriggerManual(ctx, "robot_test_manager_on_demand", types.TriggerHuman, nil)
		assert.NoError(t, err)

		// Robot should be in cache
		robot := m.Cache().Get("robot_test_manager_on_demand")
		assert.NotNil(t, robot, "Robot should be in cache after trigger")

		// Wait for execution to complete
		time.Sleep(3 * time.Second)

		// With full-cache load, non-autonomous robots stay in cache
		// (scheduleCleanup may remove then next Load() re-adds, but within cycle it persists)
		robot = m.Cache().Get("robot_test_manager_on_demand")
		// Robot may or may not be in cache depending on cleanup timing,
		// but the key point is no panic and the system remains stable
		t.Logf("Robot in cache after execution: %v", robot != nil)
	})

	t.Run("trigger non-existent robot returns error", func(t *testing.T) {
		m := manager.New()
		err := m.Start()
		assert.NoError(t, err)
		defer m.Stop()

		ctx := types.NewContext(context.Background(), nil)

		// Try to trigger a robot that doesn't exist in DB
		_, err = m.TriggerManual(ctx, "robot_nonexistent_xyz", types.TriggerHuman, nil)
		assert.Error(t, err)
		assert.Equal(t, types.ErrRobotNotFound, err)
	})
}

// setupTestRobotsWithNonAutonomous creates test robots including non-autonomous ones
func setupTestRobotsWithNonAutonomous(t *testing.T) {
	// First setup the autonomous robots
	setupTestRobotsWithClockConfig(t)

	// Add non-autonomous robots
	qb := capsule.Query()
	m := model.Select("__yao.member")
	tableName := m.MetaData.Table.Name

	// Non-autonomous robot 1: for TriggerManual test
	robotConfigOnDemand := map[string]interface{}{
		"identity": map[string]interface{}{
			"role": "On-Demand Robot",
		},
		"triggers": map[string]interface{}{
			"clock":     map[string]interface{}{"enabled": false},
			"intervene": map[string]interface{}{"enabled": true},
		},
		"quota": map[string]interface{}{
			"max":   2,
			"queue": 5,
		},
	}
	configOnDemandJSON, _ := json.Marshal(robotConfigOnDemand)

	err := qb.Table(tableName).Insert([]map[string]interface{}{
		{
			"member_id":       "robot_test_manager_on_demand",
			"team_id":         "team_test_manager",
			"member_type":     "robot",
			"display_name":    "Test On-Demand Robot",
			"status":          "active",
			"role_id":         "member",
			"autonomous_mode": false, // Non-autonomous!
			"robot_status":    "idle",
			"robot_config":    string(configOnDemandJSON),
		},
	})
	if err != nil {
		t.Fatalf("Failed to insert robot_test_manager_on_demand: %v", err)
	}

	// Non-autonomous robot 2: for Intervene test
	robotConfigOnDemandIntervene := map[string]interface{}{
		"identity": map[string]interface{}{
			"role": "On-Demand Intervene Robot",
		},
		"triggers": map[string]interface{}{
			"clock":     map[string]interface{}{"enabled": false},
			"intervene": map[string]interface{}{"enabled": true},
		},
		"quota": map[string]interface{}{
			"max": 2,
		},
	}
	configOnDemandInterveneJSON, _ := json.Marshal(robotConfigOnDemandIntervene)

	err = qb.Table(tableName).Insert([]map[string]interface{}{
		{
			"member_id":       "robot_test_manager_on_demand_intervene",
			"team_id":         "team_test_manager",
			"member_type":     "robot",
			"display_name":    "Test On-Demand Intervene Robot",
			"status":          "active",
			"role_id":         "member",
			"autonomous_mode": false, // Non-autonomous!
			"robot_status":    "idle",
			"robot_config":    string(configOnDemandInterveneJSON),
		},
	})
	if err != nil {
		t.Fatalf("Failed to insert robot_test_manager_on_demand_intervene: %v", err)
	}

	// Non-autonomous robot 3: for HandleEvent test
	robotConfigOnDemandEvent := map[string]interface{}{
		"identity": map[string]interface{}{
			"role": "On-Demand Event Robot",
		},
		"triggers": map[string]interface{}{
			"clock": map[string]interface{}{"enabled": false},
			"event": map[string]interface{}{"enabled": true},
		},
		"quota": map[string]interface{}{
			"max": 2,
		},
	}
	configOnDemandEventJSON, _ := json.Marshal(robotConfigOnDemandEvent)

	err = qb.Table(tableName).Insert([]map[string]interface{}{
		{
			"member_id":       "robot_test_manager_on_demand_event",
			"team_id":         "team_test_manager",
			"member_type":     "robot",
			"display_name":    "Test On-Demand Event Robot",
			"status":          "active",
			"role_id":         "member",
			"autonomous_mode": false, // Non-autonomous!
			"robot_status":    "idle",
			"robot_config":    string(configOnDemandEventJSON),
		},
	})
	if err != nil {
		t.Fatalf("Failed to insert robot_test_manager_on_demand_event: %v", err)
	}
}

// cleanupTestRobots removes all test robot records
func cleanupTestRobots(t *testing.T) {
	qb := capsule.Query()
	m := model.Select("__yao.member")
	tableName := m.MetaData.Table.Name

	// List of test robot IDs to clean up
	testRobotIDs := []string{
		"robot_test_sales_001",
		"robot_test_support_002",
		"robot_test_inactive_003",
		"robot_test_manager_times",
		"robot_test_manager_interval",
		"robot_test_manager_daemon",
		"robot_test_manager_paused",
		"robot_test_manager_disabled",
		"robot_test_manager_intervene",
		"robot_test_manager_intervene_disabled",
		"robot_test_manager_event",
		"robot_test_manager_event_disabled",
		// Non-autonomous robots
		"robot_test_manager_on_demand",
		"robot_test_manager_on_demand_intervene",
		"robot_test_manager_on_demand_event",
	}

	for _, id := range testRobotIDs {
		// Soft delete
		m.DeleteWhere(model.QueryParam{
			Wheres: []model.QueryWhere{
				{Column: "member_id", Value: id},
			},
		})
		// Hard delete
		qb.Table(tableName).Where("member_id", id).Delete()
	}
}
