package routing

import (
	"context"
	"fmt"
)

// ActivityExecutor defines how to execute an activity
type ActivityExecutor interface {
	// Execute runs the activity with given parameters
	Execute(ctx context.Context, activityName string, params map[string]interface{}) (interface{}, error)
}

// TemporalActivityExecutor executes activities via Temporal
type TemporalActivityExecutor struct {
	// This would be implemented by workflow context
	executor func(context.Context, string, interface{}) error
}

// StateTransitioner defines state machine transitions
type StateTransitioner interface {
	// CanTransition checks if transition is allowed
	CanTransition(from, to *State) bool
	// Transit performs the transition
	Transit(from, to *State) error
}

// DefaultStateTransitioner implements basic transitions
type DefaultStateTransitioner struct {
	validators []TransitionValidator
}

// TransitionValidator validates a specific transition
type TransitionValidator interface {
	Validate(from, to *State) error
}

// NewDefaultStateTransitioner creates a new transitioner
func NewDefaultStateTransitioner() *DefaultStateTransitioner {
	return &DefaultStateTransitioner{
		validators: []TransitionValidator{
			&StateTypeValidator{},
			&OutputMatchValidator{},
		},
	}
}

// CanTransition checks if transition is valid
func (dst *DefaultStateTransitioner) CanTransition(from, to *State) bool {
	return dst.Transit(from, to) == nil
}

// Transit validates and performs transition
func (dst *DefaultStateTransitioner) Transit(from, to *State) error {
	for _, v := range dst.validators {
		if err := v.Validate(from, to); err != nil {
			return err
		}
	}
	return nil
}

// StateTypeValidator checks state type compatibility
type StateTypeValidator struct{}

func (stv *StateTypeValidator) Validate(from, to *State) error {
	if from == nil {
		return nil // Initial transition
	}
	
	// Can't transition from terminal states
	if from.Type == StateTypeFail {
		return fmt.Errorf("cannot transition from Fail state")
	}
	if from.End && from.Type != StateTypePass {
		return fmt.Errorf("cannot transition from end state")
	}
	
	return nil
}

// OutputMatchValidator checks output-input binding
type OutputMatchValidator struct{}

func (omv *OutputMatchValidator) Validate(from, to *State) error {
	// Could validate that outputs from previous state match inputs needed
	return nil
}

// ParameterBinder resolves parameters from context
type ParameterBinder interface {
	// Bind resolves all parameters for a state
	Bind(state *State, context *ExecutionContext) (map[string]interface{}, error)
}

// DefaultParameterBinder implements parameter resolution
type DefaultParameterBinder struct {
	resolver *JSONPathResolver
}

// NewDefaultParameterBinder creates a new binder
func NewDefaultParameterBinder() *DefaultParameterBinder {
	return &DefaultParameterBinder{
		resolver: NewJSONPathResolver(nil, nil),
	}
}

// Bind resolves all parameters
func (dpb *DefaultParameterBinder) Bind(state *State, context *ExecutionContext) (map[string]interface{}, error) {
	dpb.resolver.input = context.Input
	dpb.resolver.stepResults = context.StepResults
	
	resolved, err := dpb.resolver.ResolvePaths(state.Parameters)
	if err != nil {
		return nil, fmt.Errorf("parameter binding failed: %w", err)
	}
	
	return resolved, nil
}

// WorkflowValidator validates workflow specs
type WorkflowValidator interface {
	// Validate checks if workflow is valid
	Validate(spec *WorkflowSpec) error
}

// CompositeValidator combines multiple validators
type CompositeValidator struct {
	validators []WorkflowValidator
}

// NewCompositeValidator creates a composite validator
func NewCompositeValidator(validators ...WorkflowValidator) *CompositeValidator {
	return &CompositeValidator{validators: validators}
}

// Validate runs all validators
func (cv *CompositeValidator) Validate(spec *WorkflowSpec) error {
	for _, v := range cv.validators {
		if err := v.Validate(spec); err != nil {
			return err
		}
	}
	return nil
}

// StateGraphValidator validates state graph structure
type StateGraphValidator struct{}

func (sgv *StateGraphValidator) Validate(spec *WorkflowSpec) error {
	if spec == nil {
		return fmt.Errorf("workflow spec is nil")
	}
	if len(spec.States) == 0 {
		return fmt.Errorf("workflow has no states")
	}
	
	stateMap := make(map[string]*State)
	for i := range spec.States {
		stateMap[spec.States[i].Name] = &spec.States[i]
	}
	
	// Check all transitions point to valid states
	for _, state := range spec.States {
		if state.Type == StateTypeTask && !state.End {
			if state.Next == "" {
				return fmt.Errorf("state %s has no next state and is not end", state.Name)
			}
			if _, exists := stateMap[state.Next]; !exists {
				return fmt.Errorf("state %s references non-existent next state %s", state.Name, state.Next)
			}
		}
		
		// Validate catch clauses
		for _, catch := range state.Catch {
			if _, exists := stateMap[catch.Next]; !exists {
				return fmt.Errorf("catch handler in %s references non-existent state %s", state.Name, catch.Next)
			}
		}
	}
	
	return nil
}

// ActivityAvailabilityValidator validates activities exist
type ActivityAvailabilityValidator struct {
	kb *KnowledgeBase
}

// NewActivityAvailabilityValidator creates a new validator
func NewActivityAvailabilityValidator(kb *KnowledgeBase) *ActivityAvailabilityValidator {
	return &ActivityAvailabilityValidator{kb: kb}
}

// Validate checks all activities are available
func (aav *ActivityAvailabilityValidator) Validate(spec *WorkflowSpec) error {
	for _, state := range spec.States {
		if state.Type == StateTypeTask {
			if !aav.kb.HasActivity(state.Resource) {
				return fmt.Errorf("activity %s not found in knowledge base", state.Resource)
			}
		}
	}
	return nil
}

// TimeoutValidator validates timeouts
type TimeoutValidator struct{}

func (tv *TimeoutValidator) Validate(spec *WorkflowSpec) error {
	for _, state := range spec.States {
		if state.Timeout != "" {
			if _, err := parseDuration(state.Timeout); err != nil {
				return fmt.Errorf("invalid timeout in state %s: %w", state.Name, err)
			}
		}
	}
	return nil
}

func parseDuration(d string) (interface{}, error) {
	// Placeholder for duration parsing
	return nil, nil
}
