package executor

import (
	"context"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/yaoapp/yao/agent/robot/types"
)

// Smoke tests to verify basic flow works
// Real integration tests are in manager_test.go

func TestExecutorSmoke(t *testing.T) {
	exec := NewDryRunWithDelay(0)
	robot := &types.Robot{
		MemberID: "test-smoke",
		TeamID:   "team-1",
		Config:   &types.Config{Quota: &types.Quota{Max: 1}},
	}
	ctx := types.NewContext(context.Background(), nil)

	result, err := exec.Execute(ctx, robot, types.TriggerClock, nil)

	assert.NoError(t, err)
	assert.NotNil(t, result)
	assert.Equal(t, types.ExecCompleted, result.Status)
	assert.Equal(t, types.TriggerClock, result.TriggerType)

	// Clock trigger executes all phases (P0-P5)
	assert.NotNil(t, result.Inspiration, "P0 should be executed for clock trigger")
	assert.NotNil(t, result.Goals, "P1 should be executed")
	assert.NotEmpty(t, result.Tasks, "P2 should generate tasks")
	assert.NotEmpty(t, result.Results, "P3 should generate results")
	assert.NotNil(t, result.Delivery, "P4 should be executed")
	assert.NotEmpty(t, result.Learning, "P5 should be executed")
}

func TestExecutorHumanTriggerSkipsP0(t *testing.T) {
	exec := NewDryRunWithDelay(0)
	robot := &types.Robot{
		MemberID: "test-human",
		TeamID:   "team-1",
		Config:   &types.Config{Quota: &types.Quota{Max: 1}},
	}
	ctx := types.NewContext(context.Background(), nil)

	result, err := exec.Execute(ctx, robot, types.TriggerHuman, nil)

	assert.NoError(t, err)
	assert.NotNil(t, result)
	assert.Equal(t, types.ExecCompleted, result.Status)

	// Human trigger skips P0 (Inspiration)
	assert.Nil(t, result.Inspiration, "P0 should be skipped for human trigger")
	assert.NotNil(t, result.Goals, "P1 should be executed")
}

func TestExecutorEventTriggerSkipsP0(t *testing.T) {
	exec := NewDryRunWithDelay(0)
	robot := &types.Robot{
		MemberID: "test-event",
		TeamID:   "team-1",
		Config:   &types.Config{Quota: &types.Quota{Max: 1}},
	}
	ctx := types.NewContext(context.Background(), nil)

	result, err := exec.Execute(ctx, robot, types.TriggerEvent, nil)

	assert.NoError(t, err)
	assert.Nil(t, result.Inspiration, "P0 should be skipped for event trigger")
	assert.NotNil(t, result.Goals)
}

func TestExecutorNilRobot(t *testing.T) {
	exec := NewDryRunWithDelay(0)
	ctx := types.NewContext(context.Background(), nil)

	result, err := exec.Execute(ctx, nil, types.TriggerClock, nil)

	assert.Error(t, err)
	assert.Nil(t, result)
	assert.Contains(t, err.Error(), "robot cannot be nil")
}

func TestExecutorSimulatedFailure(t *testing.T) {
	exec := NewDryRunWithDelay(0)
	robot := &types.Robot{
		MemberID: "test-fail",
		TeamID:   "team-1",
		Config:   &types.Config{Quota: &types.Quota{Max: 1}},
	}
	ctx := types.NewContext(context.Background(), nil)

	// Pass "simulate_failure" to trigger simulated failure
	result, err := exec.Execute(ctx, robot, types.TriggerClock, "simulate_failure")

	assert.NoError(t, err) // Execute returns nil error, failure is in result
	assert.NotNil(t, result)
	assert.Equal(t, types.ExecFailed, result.Status)
	assert.Equal(t, "simulated failure", result.Error)
}

func TestExecutorCounters(t *testing.T) {
	exec := NewDryRunWithDelay(0)
	robot := &types.Robot{
		MemberID: "test-counter",
		TeamID:   "team-1",
		Config:   &types.Config{Quota: &types.Quota{Max: 10}},
	}
	ctx := types.NewContext(context.Background(), nil)

	assert.Equal(t, 0, exec.ExecCount())
	assert.Equal(t, 0, exec.CurrentCount())

	_, _ = exec.Execute(ctx, robot, types.TriggerClock, nil)
	assert.Equal(t, 1, exec.ExecCount())
	assert.Equal(t, 0, exec.CurrentCount()) // Completed, so 0

	_, _ = exec.Execute(ctx, robot, types.TriggerClock, nil)
	assert.Equal(t, 2, exec.ExecCount())

	exec.Reset()
	assert.Equal(t, 0, exec.ExecCount())
}
