package sdlc

import "time"

// Classification is the output of the classifier engine.
type Classification struct {
	Timestamp    time.Time    `json:"timestamp" yaml:"timestamp"`
	Feature      string       `json:"feature" yaml:"feature"`
	CurrentPhase FeaturePhase `json:"current_phase" yaml:"current_phase"`
	RuleMatched  string       `json:"rule_matched" yaml:"rule_matched"`
	Action       ActionType   `json:"action" yaml:"action"`
	Message      string       `json:"message" yaml:"message"`
	NextCommand  string       `json:"next_command,omitempty" yaml:"next_command,omitempty"`
	OutputPath   string       `json:"output_path,omitempty" yaml:"output_path,omitempty"`
	TransitionTo FeaturePhase `json:"transition_to,omitempty" yaml:"transition_to,omitempty"`
	TaskID       string       `json:"task_id,omitempty" yaml:"task_id,omitempty"`
}

// EvalContext provides all the state needed for rule evaluation.
type EvalContext struct {
	State   *State
	Feature *Feature
	Config  *Config
	Root    string
}

// Rule is a single classifier rule with a condition and resulting action.
type Rule struct {
	ID           string
	Condition    func(ctx *EvalContext) bool
	Action       ActionType
	Message      func(ctx *EvalContext) string
	NextCommand  func(ctx *EvalContext) string
	OutputPath   func(ctx *EvalContext) string
	TransitionTo FeaturePhase
	TaskID       func(ctx *EvalContext) string
}

// Classifier evaluates rules in priority order, returning the first match.
type Classifier struct {
	rules []Rule
}

// NewClassifier creates a classifier with the default rules.
func NewClassifier() *Classifier {
	return &Classifier{rules: DefaultRules()}
}

// NewClassifierWithRules creates a classifier with custom rules.
func NewClassifierWithRules(rules []Rule) *Classifier {
	return &Classifier{rules: rules}
}

// Classify evaluates all rules against the context and returns the first match.
func (c *Classifier) Classify(ctx *EvalContext) *Classification {
	for _, rule := range c.rules {
		if rule.Condition(ctx) {
			cl := &Classification{
				Timestamp:    time.Now().UTC(),
				Feature:      ctx.Feature.Slug,
				CurrentPhase: ctx.Feature.Phase,
				RuleMatched:  rule.ID,
				Action:       rule.Action,
				TransitionTo: rule.TransitionTo,
			}
			if rule.Message != nil {
				cl.Message = rule.Message(ctx)
			}
			if rule.NextCommand != nil {
				cl.NextCommand = rule.NextCommand(ctx)
			}
			if rule.OutputPath != nil {
				cl.OutputPath = rule.OutputPath(ctx)
			}
			if rule.TaskID != nil {
				cl.TaskID = rule.TaskID(ctx)
			}
			return cl
		}
	}

	// Default: nothing to do
	return &Classification{
		Timestamp:    time.Now().UTC(),
		Feature:      ctx.Feature.Slug,
		CurrentPhase: ctx.Feature.Phase,
		RuleMatched:  "nothing-to-do",
		Action:       ActionIdle,
		Message:      "No actionable work found",
	}
}
