package workflow

import (
	"strings"
	"time"
)

// RunStatus bir yürütmenin genel durumudur.
type RunStatus string

const (
	RunRunning   RunStatus = "running"
	RunSucceeded RunStatus = "succeeded"
	RunFailed    RunStatus = "failed"
	RunCancelled RunStatus = "cancelled"
)

// Valid bilinen bir durum mu?
func (s RunStatus) Valid() bool {
	switch s {
	case RunRunning, RunSucceeded, RunFailed, RunCancelled:
		return true
	}
	return false
}

// Terminal yürütme bitti mi (artık değişmez)?
func (s RunStatus) Terminal() bool { return s != RunRunning && s.Valid() }

// StepStatus tek adımın durumudur.
type StepStatus string

const (
	StepRunning StepStatus = "running"
	StepOK      StepStatus = "ok"
	StepError   StepStatus = "error"
)

// MaxPreviewRunes Step.Input/Output ve Execution.Input/Output önizlemesinin üst sınırıdır.
// Kayıt GÖRÜNTÜ içindir: dev bir LLM çıktısı yürütme kaydını şişirmesin.
const MaxPreviewRunes = 2000

// Step yürütmenin tek bir node çalıştırmasıdır. Aynı node döngüde birden çok kez çalışabilir
// (Iteration >= 1); döngü dışında Iteration 0'dır.
type Step struct {
	Index      int        `bson:"index" json:"index"`
	NodeID     string     `bson:"nodeId" json:"nodeId"`
	NodeType   NodeType   `bson:"nodeType" json:"nodeType"`
	Label      string     `bson:"label,omitempty" json:"label,omitempty"`
	Iteration  int        `bson:"iteration,omitempty" json:"iteration,omitempty"`
	Status     StepStatus `bson:"status" json:"status"`
	Branch     string     `bson:"branch,omitempty" json:"branch,omitempty"` // condition: seçilen dal
	Input      string     `bson:"input,omitempty" json:"input,omitempty"`
	Output     string     `bson:"output,omitempty" json:"output,omitempty"`
	Error      string     `bson:"error,omitempty" json:"error,omitempty"`
	StartedAt  time.Time  `bson:"startedAt" json:"startedAt"`
	FinishedAt *time.Time `bson:"finishedAt,omitempty" json:"finishedAt,omitempty"`
	DurationMs int64      `bson:"durationMs" json:"durationMs"`
}

// Execution bir akışın tek çalıştırmasının kaydıdır (PROJE.MD "EXECUTION SYSTEM").
// AgentID alanı PROJE.MD'deki adıyla WorkflowID'dir: Agent = kayıtlı akış.
type Execution struct {
	ID               string     `bson:"_id" json:"id"`
	UserID           string     `bson:"userId" json:"userId"`
	WorkflowID       string     `bson:"workflowId" json:"workflowId"`
	WorkflowName     string     `bson:"workflowName" json:"workflowName"`
	ConversationID   string     `bson:"conversationId,omitempty" json:"conversationId,omitempty"`
	Input            string     `bson:"input,omitempty" json:"input,omitempty"`
	Output           string     `bson:"output,omitempty" json:"output,omitempty"`
	Status           RunStatus  `bson:"status" json:"status"`
	Error            string     `bson:"error,omitempty" json:"error,omitempty"`
	Steps            []Step     `bson:"steps" json:"steps"`
	ToolCalls        int        `bson:"toolCalls" json:"toolCalls"`
	PromptTokens     int        `bson:"promptTokens" json:"promptTokens"`
	CompletionTokens int        `bson:"completionTokens" json:"completionTokens"`
	StartedAt        time.Time  `bson:"startedAt" json:"startedAt"`
	FinishedAt       *time.Time `bson:"finishedAt,omitempty" json:"finishedAt,omitempty"`
	LatencyMs        int64      `bson:"latencyMs" json:"latencyMs"`
}

// Clone derin kopya döndürür (adım dilimi ve zaman işaretçileri dahil).
func (e Execution) Clone() Execution {
	c := e
	c.Steps = make([]Step, len(e.Steps))
	for i, s := range e.Steps {
		s.FinishedAt = cloneTime(s.FinishedAt)
		c.Steps[i] = s
	}
	c.FinishedAt = cloneTime(e.FinishedAt)
	return c
}

func cloneTime(t *time.Time) *time.Time {
	if t == nil {
		return nil
	}
	v := *t
	return &v
}

// preview metni MaxPreviewRunes ile sınırlar (kırpıldıysa "…" ekler).
func preview(s string) string {
	s = strings.TrimSpace(s)
	if runes(s) <= MaxPreviewRunes {
		return s
	}
	r := []rune(s)
	return string(r[:MaxPreviewRunes]) + "…"
}
