package types

import (
	"strings"
	"time"
)

type ToolKind string

const (
	ToolShell ToolKind = "shell"
	ToolLLM   ToolKind = "llm"
	ToolFiles ToolKind = "file"
)

type OutcomeKind string

const (
	OutcomeOK     OutcomeKind = "ok"
	OutcomeDryRun OutcomeKind = "dry-run"
	OutcomeError  OutcomeKind = "error"
)

type Config struct {
	MaxSteps int
	DryRun   bool
	WorkDir  string
}

type Plan struct {
	Goal  string
	Steps []Step
}

type Step struct {
	Type ToolKind

	Description string

	// Shell
	Command string
	Args    []string

	// LLM
	Prompt string

	// Files
	Path string
	Op   string

	// For write/patch: Data is the full content or unified diff
	Data string

	// For replace:
	Old string
	New string
	N   int
}

type ExecContext struct {
	Goal    string
	Plan    Plan
	Results []StepResult
}

type StepResult struct {
	Step       Step
	Outcome    OutcomeKind
	Transcript string
	Duration   time.Duration
	Exec       *Result
	Output     string
	Effects    Effects
}

type Result struct {
	Stdout   string
	Stderr   string
	ExitCode int
	Duration time.Duration
}

type StepEffect struct {
	Kind  string         // "file.write" | "file.patch" | "file.replace" | "shell.exec" | ...
	Path  string         // for file ops
	Bytes int            // for writes (optional)
	Meta  map[string]any // extra stats, like hunks, replaced count, exit code, etc.
}

type Effects []StepEffect

func (e Effects) HasKind(kind string) bool {
	for _, eff := range e {
		if eff.Kind == kind {
			return true
		}
	}
	return false
}

func (e Effects) HasPrefix(prefix string) bool {
	for _, eff := range e {
		if strings.HasPrefix(eff.Kind, prefix) {
			return true
		}
	}
	return false
}
