package tests

import (
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/rockliang/poimen/workflows/statemachine"
)

func TestTypesDefaults(t *testing.T) {
	// Test PiRetryPolicy defaults
	pr := statemachine.NewPiRetryPolicy()
	assert.Equal(t, 5*time.Minute, pr.ScheduleToCloseTimeout, "ScheduleToCloseTimeout should be 5m")
	assert.Equal(t, 2*time.Second, pr.InitialInterval, "InitialInterval should be 2s")
	assert.Equal(t, 30*time.Second, pr.MaximumInterval, "MaximumInterval should be 30s")
	assert.Equal(t, 2.0, pr.BackoffCoefficient, "BackoffCoefficient should be 2.0")
	assert.Equal(t, 30*time.Second, pr.StreamTimeout, "StreamTimeout should be 30s")
	assert.Equal(t, 2*time.Minute, pr.StreamTimeoutMax, "StreamTimeoutMax should be 2m")

	// Test ActivityTuning defaults
	at := statemachine.NewActivityTuning()
	assert.Equal(t, 10*time.Minute, at.ImplementerBaseTimeout, "ImplementerBaseTimeout should be 10m")
	assert.Equal(t, 3, at.ImplementerMaxRetries, "ImplementerMaxRetries should be 3")
	assert.Equal(t, 5*time.Minute, at.JudgeTimeout, "JudgeTimeout should be 5m")

	// Test nested PiRetry in ActivityTuning
	assert.Equal(t, 5*time.Minute, at.PiRetry.ScheduleToCloseTimeout)
	assert.Equal(t, 30*time.Second, at.PiRetry.StreamTimeout)
	assert.Equal(t, 2*time.Minute, at.PiRetry.StreamTimeoutMax)
}

func TestModelSpec(t *testing.T) {
	spec := statemachine.ModelSpec{
		ModelID:  "claude-opus-5",
		Thinking: "adaptive",
		Effort:   "high",
	}
	assert.Equal(t, "claude-opus-5", spec.ModelID)
	assert.Equal(t, "adaptive", spec.Thinking)
	assert.Equal(t, "high", spec.Effort)
}

func TestPromptSpec(t *testing.T) {
	spec := statemachine.PromptSpec{
		TemplateRef: "planner/default.tmpl",
		RawTemplate: "",
		Variables: map[string]any{
			"key": "value",
		},
		Model: statemachine.ModelSpec{
			ModelID: "claude-opus-5",
		},
		LessonsRef: "T0.1",
	}
	assert.Equal(t, "planner/default.tmpl", spec.TemplateRef)
	assert.Empty(t, spec.RawTemplate)
	assert.Equal(t, "value", spec.Variables["key"])
	assert.Equal(t, "claude-opus-5", spec.Model.ModelID)
	assert.Equal(t, "T0.1", spec.LessonsRef)
}

func TestOrchestratorConfig(t *testing.T) {
	cfg := statemachine.OrchestratorConfig{
		SystemPrompt: "You are an expert",
		Skills: []statemachine.SkillRef{
			{Name: "golang-skills", URL: "https://example.com/skill1"},
		},
		RolePrompts: map[string]statemachine.PromptSpec{
			"planner": {
				TemplateRef: "planner/default.tmpl",
				Model: statemachine.ModelSpec{ModelID: "claude-opus-5"},
			},
		},
		Tuning: statemachine.NewActivityTuning(),
	}
	assert.Equal(t, "You are an expert", cfg.SystemPrompt)
	assert.Len(t, cfg.Skills, 1)
	assert.NotEmpty(t, cfg.RolePrompts)
	assert.Equal(t, 10*time.Minute, cfg.Tuning.ImplementerBaseTimeout)
}

func TestTaskUnitInput(t *testing.T) {
	input := statemachine.TaskUnitInput{
		TaskID:         "T0.1",
		RemoteURL:      "https://github.com/example/repo",
		TargetRepoPath: "/tmp/repo",
		Milestone:      "v1.0",
		DryRun:         false,
	}
	assert.Equal(t, "T0.1", input.TaskID)
	assert.Equal(t, "https://github.com/example/repo", input.RemoteURL)
	assert.Equal(t, "/tmp/repo", input.TargetRepoPath)
	assert.Equal(t, "v1.0", input.Milestone)
	assert.Equal(t, false, input.DryRun)
}
