package tdd

import (
	"context"
	"encoding/json"

	iexec "github.com/mathiasbq/supervisor/internal/exec"
	"github.com/mathiasbq/supervisor/internal/registry"
)

// ExecutorFn allows injecting a test double for the executor.
type ExecutorFn func(ctx context.Context, req iexec.Request) (iexec.Result, error)

type Config struct {
	SystemPrompt string
	SkillPrompt  string
	ExecutorFn   ExecutorFn // nil = no executor (tests that don't reach execute())
	DefaultModel string
}

type Skill struct {
	cfg Config
}

func New(cfg Config) *Skill {
	return &Skill{cfg: cfg}
}

func (s *Skill) Name() string { return "tdd" }

func (s *Skill) Tools() []registry.ToolDef {
	schema := func(required []string, props map[string]any) json.RawMessage {
		b, _ := json.Marshal(map[string]any{
			"type":       "object",
			"required":   required,
			"properties": props,
		})
		return b
	}
	strProp := map[string]any{"type": "string"}

	return []registry.ToolDef{
		{
			Name:        "tdd_red",
			Description: "Write a failing test for the described behavior. Verifies the test fails before returning.",
			InputSchema: schema(
				[]string{"project_root", "spec"},
				map[string]any{
					"project_root": strProp,
					"spec":         strProp,
					"model":        strProp,
					"test_cmd":     strProp,
				},
			),
		},
		{
			Name:        "tdd_green",
			Description: "Write minimal implementation to make the test at test_path pass.",
			InputSchema: schema(
				[]string{"project_root", "test_path"},
				map[string]any{
					"project_root": strProp,
					"test_path":    strProp,
					"model":        strProp,
					"test_cmd":     strProp,
				},
			),
		},
		{
			Name:        "tdd_refactor",
			Description: "Refactor the implementation at impl_path while keeping tests green.",
			InputSchema: schema(
				[]string{"project_root", "test_path", "impl_path"},
				map[string]any{
					"project_root": strProp,
					"test_path":    strProp,
					"impl_path":    strProp,
					"model":        strProp,
					"test_cmd":     strProp,
				},
			),
		},
	}
}
