package intelligence

import (
	"context"
	"fmt"
	"math"
	"sort"
	"strings"
	"sync"
	"time"

	slurpContext "chorus.services/bzzz/pkg/slurp/context"
)

// GoalAlignmentEngine provides comprehensive goal alignment assessment
type GoalAlignmentEngine struct {
	mu                    sync.RWMutex
	config               *EngineConfig
	scoringEngine        *ScoringEngine
	dimensionAnalyzer    *DimensionAnalyzer
	priorityCalculator   *PriorityCalculator
	trendAnalyzer        *TrendAnalyzer
	recommendationEngine *RecommendationEngine
	metrics              *AlignmentMetrics
}

// ScoringEngine handles multi-dimensional scoring algorithms
type ScoringEngine struct {
	dimensions     []*ScoringDimension
	weightConfig   *WeightConfiguration
	normalizer     *ScoreNormalizer
	aggregator     *ScoreAggregator
}

// ScoringDimension represents a single dimension of goal alignment
type ScoringDimension struct {
	Name         string                 `json:"name"`
	Description  string                 `json:"description"`
	Weight       float64                `json:"weight"`
	Calculator   DimensionCalculator    `json:"-"`
	Threshold    float64                `json:"threshold"`
	Priority     int                    `json:"priority"`
	Category     string                 `json:"category"`
	Metadata     map[string]interface{} `json:"metadata"`
}

// DimensionCalculator interface for calculating dimension scores
type DimensionCalculator interface {
	Calculate(ctx context.Context, node *slurpContext.ContextNode, goal *ProjectGoal) (*DimensionScore, error)
	GetName() string
	GetWeight() float64
	Validate(node *slurpContext.ContextNode, goal *ProjectGoal) error
}

// DimensionScore represents a score for a single dimension
type DimensionScore struct {
	Dimension    string                 `json:"dimension"`
	Score        float64                `json:"score"`
	Confidence   float64                `json:"confidence"`
	Evidence     []string               `json:"evidence"`
	Reasoning    string                 `json:"reasoning"`
	SubScores    map[string]float64     `json:"sub_scores"`
	Metadata     map[string]interface{} `json:"metadata"`
	CalculatedAt time.Time              `json:"calculated_at"`
}

// WeightConfiguration manages dimension weights
type WeightConfiguration struct {
	GlobalWeights   map[string]float64    `json:"global_weights"`
	RoleWeights     map[string]map[string]float64 `json:"role_weights"`
	PhaseWeights    map[string]map[string]float64 `json:"phase_weights"`
	ProjectWeights  map[string]map[string]float64 `json:"project_weights"`
	DynamicWeights  bool                  `json:"dynamic_weights"`
	LastUpdated     time.Time             `json:"last_updated"`
}

// ScoreNormalizer normalizes scores across different dimensions
type ScoreNormalizer struct {
	normalizationMethod string
	referenceData       *NormalizationReference
}

// NormalizationReference contains reference data for normalization
type NormalizationReference struct {
	HistoricalScores map[string]*ScoreDistribution `json:"historical_scores"`
	Percentiles      map[string]map[int]float64    `json:"percentiles"`
	LastCalculated   time.Time                     `json:"last_calculated"`
}

// ScoreDistribution represents score distribution statistics
type ScoreDistribution struct {
	Mean       float64   `json:"mean"`
	Median     float64   `json:"median"`
	StdDev     float64   `json:"std_dev"`
	Min        float64   `json:"min"`
	Max        float64   `json:"max"`
	Count      int       `json:"count"`
	Samples    []float64 `json:"samples"`
}

// ScoreAggregator combines dimension scores into final alignment score
type ScoreAggregator struct {
	method        string
	customLogic   func([]*DimensionScore, *WeightConfiguration) float64
}

// DimensionAnalyzer analyzes alignment dimensions
type DimensionAnalyzer struct {
	calculators map[string]DimensionCalculator
}

// PriorityCalculator calculates priority-based scoring adjustments
type PriorityCalculator struct {
	priorityMatrix *PriorityMatrix
	timeFactors    *TimeFactors
}

// PriorityMatrix defines priority relationships
type PriorityMatrix struct {
	Goals        map[string]int         `json:"goals"`
	Phases       map[string]int         `json:"phases"`
	Technologies map[string]int         `json:"technologies"`
	Roles        map[string]int         `json:"roles"`
	Urgency      map[string]float64     `json:"urgency"`
	Impact       map[string]float64     `json:"impact"`
}

// TimeFactors handles time-based priority adjustments
type TimeFactors struct {
	DecayFunction   string    `json:"decay_function"`
	HalfLife        time.Duration `json:"half_life"`
	UrgencyBoost    float64   `json:"urgency_boost"`
	DeadlineWeight  float64   `json:"deadline_weight"`
	PhaseAlignment  map[string]float64 `json:"phase_alignment"`
}

// TrendAnalyzer analyzes alignment trends over time
type TrendAnalyzer struct {
	historicalData *AlignmentHistory
	trendDetector  *TrendDetector
	predictor      *AlignmentPredictor
}

// AlignmentHistory stores historical alignment data
type AlignmentHistory struct {
	mu            sync.RWMutex
	records       []*AlignmentRecord
	maxRecords    int
	retention     time.Duration
}

// AlignmentRecord represents a historical alignment record
type AlignmentRecord struct {
	NodePath      string                 `json:"node_path"`
	GoalID        string                 `json:"goal_id"`
	Score         float64                `json:"score"`
	Dimensions    []*DimensionScore      `json:"dimensions"`
	Context       map[string]interface{} `json:"context"`
	Timestamp     time.Time              `json:"timestamp"`
	Role          string                 `json:"role"`
	Phase         string                 `json:"phase"`
}

// TrendDetector detects trends in alignment data
type TrendDetector struct {
	methods []TrendDetectionMethod
}

// TrendDetectionMethod interface for trend detection algorithms
type TrendDetectionMethod interface {
	DetectTrend(data []*AlignmentRecord) (*Trend, error)
	GetName() string
	GetConfidence() float64
}

// Trend represents a detected trend
type Trend struct {
	Type        string    `json:"type"`        // improving, declining, stable, volatile
	Strength    float64   `json:"strength"`    // 0-1 strength of trend
	Confidence  float64   `json:"confidence"`  // 0-1 confidence in detection
	Duration    time.Duration `json:"duration"` // duration of trend
	Slope       float64   `json:"slope"`       // rate of change
	Breakpoints []time.Time `json:"breakpoints"` // trend change points
	Description string    `json:"description"`
	StartTime   time.Time `json:"start_time"`
	EndTime     time.Time `json:"end_time"`
}

// AlignmentPredictor predicts future alignment scores
type AlignmentPredictor struct {
	models []PredictionModel
}

// PredictionModel interface for alignment prediction
type PredictionModel interface {
	Predict(ctx context.Context, history []*AlignmentRecord, horizon time.Duration) (*AlignmentPrediction, error)
	GetName() string
	GetAccuracy() float64
	Train(data []*AlignmentRecord) error
}

// AlignmentPrediction represents predicted alignment
type AlignmentPrediction struct {
	PredictedScore   float64                `json:"predicted_score"`
	ConfidenceInterval *ConfidenceInterval  `json:"confidence_interval"`
	Factors          map[string]float64     `json:"factors"`
	Scenarios        []*Scenario            `json:"scenarios"`
	Recommendations  []string               `json:"recommendations"`
	Horizon          time.Duration          `json:"horizon"`
	Model            string                 `json:"model"`
	PredictedAt      time.Time              `json:"predicted_at"`
}

// ConfidenceInterval represents prediction confidence
type ConfidenceInterval struct {
	Lower      float64 `json:"lower"`
	Upper      float64 `json:"upper"`
	Confidence float64 `json:"confidence"` // e.g., 0.95 for 95% confidence
}

// Scenario represents a prediction scenario
type Scenario struct {
	Name        string    `json:"name"`
	Probability float64   `json:"probability"`
	Score       float64   `json:"score"`
	Description string    `json:"description"`
	Assumptions []string  `json:"assumptions"`
}

// RecommendationEngine generates alignment improvement recommendations
type RecommendationEngine struct {
	ruleEngine    *RecommendationRuleEngine
	mlEngine      *MLRecommendationEngine
	prioritizer   *RecommendationPrioritizer
}

// RecommendationRuleEngine provides rule-based recommendations
type RecommendationRuleEngine struct {
	rules []*RecommendationRule
}

// RecommendationRule defines a recommendation rule
type RecommendationRule struct {
	ID          string                 `json:"id"`
	Name        string                 `json:"name"`
	Condition   RecommendationCondition `json:"condition"`
	Action      RecommendationAction   `json:"action"`
	Priority    int                    `json:"priority"`
	Confidence  float64                `json:"confidence"`
	Category    string                 `json:"category"`
	Tags        []string               `json:"tags"`
}

// RecommendationCondition defines when a rule applies
type RecommendationCondition struct {
	ScoreThreshold    float64            `json:"score_threshold"`
	DimensionFilters  map[string]float64 `json:"dimension_filters"`
	TrendConditions   []string           `json:"trend_conditions"`
	ContextFilters    map[string]interface{} `json:"context_filters"`
	LogicalOperator   string             `json:"logical_operator"` // AND, OR
}

// RecommendationAction defines what to recommend
type RecommendationAction struct {
	Type         string                 `json:"type"`
	Description  string                 `json:"description"`
	Impact       float64                `json:"impact"`
	Effort       float64                `json:"effort"`
	Timeline     string                 `json:"timeline"`
	Resources    []string               `json:"resources"`
	Dependencies []string               `json:"dependencies"`
	Metadata     map[string]interface{} `json:"metadata"`
}

// MLRecommendationEngine provides ML-based recommendations
type MLRecommendationEngine struct {
	models []RecommendationModel
}

// RecommendationModel interface for ML recommendation models
type RecommendationModel interface {
	GenerateRecommendations(ctx context.Context, node *slurpContext.ContextNode, alignmentData *AlignmentAssessment) ([]*Recommendation, error)
	Train(data []*TrainingExample) error
	GetName() string
	GetConfidence() float64
}

// TrainingExample represents training data for ML models
type TrainingExample struct {
	Node            *slurpContext.ContextNode `json:"node"`
	AlignmentBefore *AlignmentAssessment      `json:"alignment_before"`
	AlignmentAfter  *AlignmentAssessment      `json:"alignment_after"`
	Actions         []*RecommendationAction   `json:"actions"`
	Outcome         float64                   `json:"outcome"`
	Timestamp       time.Time                 `json:"timestamp"`
}

// RecommendationPrioritizer prioritizes recommendations
type RecommendationPrioritizer struct {
	criteria []PrioritizationCriterion
}

// PrioritizationCriterion defines how to prioritize recommendations
type PrioritizationCriterion struct {
	Name        string  `json:"name"`
	Weight      float64 `json:"weight"`
	Calculator  func(*Recommendation) float64 `json:"-"`
}

// AlignmentMetrics tracks alignment assessment metrics
type AlignmentMetrics struct {
	mu                  sync.RWMutex
	totalAssessments    int64
	successfulAssessments int64
	averageScore        float64
	scoreDistribution   *ScoreDistribution
	dimensionPerformance map[string]*DimensionMetrics
	goalPerformance     map[string]*GoalMetrics
	lastReset           time.Time
}

// DimensionMetrics tracks metrics for a specific dimension
type DimensionMetrics struct {
	TotalCalculations int64             `json:"total_calculations"`
	AverageScore      float64           `json:"average_score"`
	Distribution      *ScoreDistribution `json:"distribution"`
	FailureRate       float64           `json:"failure_rate"`
	LastCalculated    time.Time         `json:"last_calculated"`
}

// GoalMetrics tracks metrics for a specific goal
type GoalMetrics struct {
	TotalAssessments  int64             `json:"total_assessments"`
	AverageAlignment  float64           `json:"average_alignment"`
	TrendDirection    string            `json:"trend_direction"`
	LastAssessed      time.Time         `json:"last_assessed"`
	SuccessRate       float64           `json:"success_rate"`
}

// AlignmentAssessment represents a complete alignment assessment
type AlignmentAssessment struct {
	NodePath         string                     `json:"node_path"`
	GoalID           string                     `json:"goal_id"`
	OverallScore     float64                    `json:"overall_score"`
	Confidence       float64                    `json:"confidence"`
	DimensionScores  []*DimensionScore          `json:"dimension_scores"`
	Recommendations  []*Recommendation          `json:"recommendations"`
	Trends           []*Trend                   `json:"trends"`
	Predictions      []*AlignmentPrediction     `json:"predictions"`
	Context          map[string]interface{}     `json:"context"`
	AssessedAt       time.Time                  `json:"assessed_at"`
	AssessedBy       string                     `json:"assessed_by"`
	Role             string                     `json:"role"`
	Phase            string                     `json:"phase"`
}

// Recommendation represents an alignment improvement recommendation
type Recommendation struct {
	ID              string                     `json:"id"`
	Title           string                     `json:"title"`
	Description     string                     `json:"description"`
	Action          *RecommendationAction      `json:"action"`
	Priority        int                        `json:"priority"`
	Confidence      float64                    `json:"confidence"`
	Impact          float64                    `json:"impact"`
	Effort          float64                    `json:"effort"`
	Timeline        string                     `json:"timeline"`
	Category        string                     `json:"category"`
	Tags            []string                   `json:"tags"`
	Dependencies    []string                   `json:"dependencies"`
	Resources       []string                   `json:"resources"`
	SuccessCriteria []string                   `json:"success_criteria"`
	RiskFactors     []string                   `json:"risk_factors"`
	Alternatives    []*Recommendation          `json:"alternatives"`
	GeneratedAt     time.Time                  `json:"generated_at"`
	GeneratedBy     string                     `json:"generated_by"`
}

// NewGoalAlignmentEngine creates a new goal alignment engine
func NewGoalAlignmentEngine(config *EngineConfig) *GoalAlignmentEngine {
	engine := &GoalAlignmentEngine{
		config:               config,
		scoringEngine:        NewScoringEngine(config),
		dimensionAnalyzer:    NewDimensionAnalyzer(),
		priorityCalculator:   NewPriorityCalculator(),
		trendAnalyzer:        NewTrendAnalyzer(),
		recommendationEngine: NewRecommendationEngine(),
		metrics:              NewAlignmentMetrics(),
	}

	return engine
}

// NewScoringEngine creates a scoring engine
func NewScoringEngine(config *EngineConfig) *ScoringEngine {
	engine := &ScoringEngine{
		dimensions:   []*ScoringDimension{},
		weightConfig: NewWeightConfiguration(),
		normalizer:   NewScoreNormalizer(),
		aggregator:   NewScoreAggregator(),
	}

	// Initialize standard dimensions
	engine.initializeStandardDimensions()
	return engine
}

// AssessAlignment performs comprehensive goal alignment assessment
func (gae *GoalAlignmentEngine) AssessAlignment(ctx context.Context, node *slurpContext.ContextNode, goal *ProjectGoal, role string) (*AlignmentAssessment, error) {
	start := time.Now()
	defer func() {
		gae.metrics.recordAssessment(time.Since(start))
	}()

	// Calculate dimension scores
	dimensionScores, err := gae.calculateDimensionScores(ctx, node, goal)
	if err != nil {
		gae.metrics.recordFailure()
		return nil, fmt.Errorf("failed to calculate dimension scores: %w", err)
	}

	// Apply priority adjustments
	adjustedScores := gae.priorityCalculator.adjustScores(dimensionScores, goal, role)

	// Calculate overall score
	overallScore := gae.scoringEngine.aggregator.aggregate(adjustedScores, gae.scoringEngine.weightConfig)

	// Normalize scores
	normalizedScore := gae.scoringEngine.normalizer.normalize(overallScore, "overall")

	// Generate recommendations
	recommendations, err := gae.recommendationEngine.generateRecommendations(ctx, node, goal, adjustedScores)
	if err != nil {
		recommendations = []*Recommendation{} // Continue with empty recommendations
	}

	// Analyze trends
	trends := gae.trendAnalyzer.analyzeTrends(node.Path, goal.ID)

	// Generate predictions
	predictions, err := gae.trendAnalyzer.predictor.predictAlignment(ctx, node.Path, goal.ID, 30*24*time.Hour)
	if err != nil {
		predictions = []*AlignmentPrediction{} // Continue with empty predictions
	}

	// Calculate confidence
	confidence := gae.calculateOverallConfidence(adjustedScores)

	assessment := &AlignmentAssessment{
		NodePath:        node.Path,
		GoalID:          goal.ID,
		OverallScore:    normalizedScore,
		Confidence:      confidence,
		DimensionScores: adjustedScores,
		Recommendations: recommendations,
		Trends:          trends,
		Predictions:     predictions,
		Context: map[string]interface{}{
			"role":      role,
			"goal_name": goal.Name,
			"phase":     goal.Phase,
		},
		AssessedAt: time.Now(),
		AssessedBy: "GoalAlignmentEngine",
		Role:       role,
		Phase:      goal.Phase,
	}

	// Record historical data
	gae.trendAnalyzer.recordAlignment(assessment)

	gae.metrics.recordSuccess(normalizedScore)
	return assessment, nil
}

// calculateDimensionScores calculates scores for all dimensions
func (gae *GoalAlignmentEngine) calculateDimensionScores(ctx context.Context, node *slurpContext.ContextNode, goal *ProjectGoal) ([]*DimensionScore, error) {
	scores := []*DimensionScore{}

	for _, dimension := range gae.scoringEngine.dimensions {
		score, err := dimension.Calculator.Calculate(ctx, node, goal)
		if err != nil {
			// Log error but continue with other dimensions
			continue
		}

		scores = append(scores, score)
	}

	if len(scores) == 0 {
		return nil, fmt.Errorf("no dimension scores calculated")
	}

	return scores, nil
}

// calculateOverallConfidence calculates overall confidence from dimension scores
func (gae *GoalAlignmentEngine) calculateOverallConfidence(scores []*DimensionScore) float64 {
	if len(scores) == 0 {
		return 0.0
	}

	totalConfidence := 0.0
	for _, score := range scores {
		totalConfidence += score.Confidence
	}

	return totalConfidence / float64(len(scores))
}

// Standard dimension calculators

// KeywordAlignmentCalculator calculates alignment based on keyword matching
type KeywordAlignmentCalculator struct {
	name   string
	weight float64
}

func NewKeywordAlignmentCalculator() *KeywordAlignmentCalculator {
	return &KeywordAlignmentCalculator{
		name:   "keyword_alignment",
		weight: 0.3,
	}
}

func (kac *KeywordAlignmentCalculator) GetName() string {
	return kac.name
}

func (kac *KeywordAlignmentCalculator) GetWeight() float64 {
	return kac.weight
}

func (kac *KeywordAlignmentCalculator) Validate(node *slurpContext.ContextNode, goal *ProjectGoal) error {
	if node == nil || goal == nil {
		return fmt.Errorf("node and goal cannot be nil")
	}
	return nil
}

func (kac *KeywordAlignmentCalculator) Calculate(ctx context.Context, node *slurpContext.ContextNode, goal *ProjectGoal) (*DimensionScore, error) {
	if err := kac.Validate(node, goal); err != nil {
		return nil, err
	}

	// Combine node text for analysis
	nodeText := strings.ToLower(node.Summary + " " + node.Purpose + " " + strings.Join(node.Technologies, " ") + " " + strings.Join(node.Tags, " "))
	
	// Calculate keyword matches
	matches := 0
	evidence := []string{}
	
	for _, keyword := range goal.Keywords {
		if strings.Contains(nodeText, strings.ToLower(keyword)) {
			matches++
			evidence = append(evidence, fmt.Sprintf("Found keyword: %s", keyword))
		}
	}

	// Calculate score
	score := 0.0
	if len(goal.Keywords) > 0 {
		score = float64(matches) / float64(len(goal.Keywords))
	}

	// Calculate confidence based on evidence strength
	confidence := math.Min(0.9, float64(matches)*0.2+0.1)

	return &DimensionScore{
		Dimension:    kac.name,
		Score:        score,
		Confidence:   confidence,
		Evidence:     evidence,
		Reasoning:    fmt.Sprintf("Found %d out of %d keywords", matches, len(goal.Keywords)),
		SubScores:    map[string]float64{"keyword_matches": float64(matches)},
		CalculatedAt: time.Now(),
	}, nil
}

// TechnologyAlignmentCalculator calculates alignment based on technology stack
type TechnologyAlignmentCalculator struct {
	name   string
	weight float64
}

func NewTechnologyAlignmentCalculator() *TechnologyAlignmentCalculator {
	return &TechnologyAlignmentCalculator{
		name:   "technology_alignment",
		weight: 0.25,
	}
}

func (tac *TechnologyAlignmentCalculator) GetName() string {
	return tac.name
}

func (tac *TechnologyAlignmentCalculator) GetWeight() float64 {
	return tac.weight
}

func (tac *TechnologyAlignmentCalculator) Validate(node *slurpContext.ContextNode, goal *ProjectGoal) error {
	if node == nil || goal == nil {
		return fmt.Errorf("node and goal cannot be nil")
	}
	return nil
}

func (tac *TechnologyAlignmentCalculator) Calculate(ctx context.Context, node *slurpContext.ContextNode, goal *ProjectGoal) (*DimensionScore, error) {
	if err := tac.Validate(node, goal); err != nil {
		return nil, err
	}

	// Check if goal keywords include technology-related terms
	techKeywords := []string{}
	for _, keyword := range goal.Keywords {
		if tac.isTechnologyKeyword(keyword) {
			techKeywords = append(techKeywords, keyword)
		}
	}

	if len(techKeywords) == 0 {
		// If no tech keywords in goal, score based on general technology presence
		score := 0.5
		if len(node.Technologies) > 0 {
			score = 0.7
		}
		return &DimensionScore{
			Dimension:    tac.name,
			Score:        score,
			Confidence:   0.5,
			Evidence:     []string{"No specific technology requirements in goal"},
			Reasoning:    "General technology assessment",
			CalculatedAt: time.Now(),
		}, nil
	}

	// Calculate technology alignment
	matches := 0
	evidence := []string{}
	
	for _, tech := range node.Technologies {
		for _, keyword := range techKeywords {
			if strings.Contains(strings.ToLower(tech), strings.ToLower(keyword)) ||
				strings.Contains(strings.ToLower(keyword), strings.ToLower(tech)) {
				matches++
				evidence = append(evidence, fmt.Sprintf("Technology match: %s ~ %s", tech, keyword))
			}
		}
	}

	score := 0.0
	if len(techKeywords) > 0 {
		score = float64(matches) / float64(len(techKeywords))
	}

	confidence := math.Min(0.9, float64(matches)*0.3+0.2)

	return &DimensionScore{
		Dimension:    tac.name,
		Score:        score,
		Confidence:   confidence,
		Evidence:     evidence,
		Reasoning:    fmt.Sprintf("Technology alignment: %d matches out of %d tech keywords", matches, len(techKeywords)),
		SubScores:    map[string]float64{"tech_matches": float64(matches)},
		CalculatedAt: time.Now(),
	}, nil
}

func (tac *TechnologyAlignmentCalculator) isTechnologyKeyword(keyword string) bool {
	techTerms := []string{
		"go", "golang", "python", "javascript", "typescript", "java", "rust", "c++", "c#",
		"react", "vue", "angular", "node", "express", "django", "flask", "spring",
		"docker", "kubernetes", "aws", "azure", "gcp", "terraform", "ansible",
		"mysql", "postgresql", "mongodb", "redis", "elasticsearch",
		"microservices", "api", "rest", "graphql", "grpc", "websocket",
	}

	lowerKeyword := strings.ToLower(keyword)
	for _, term := range techTerms {
		if strings.Contains(lowerKeyword, term) {
			return true
		}
	}
	return false
}

// Initialize scoring engine with standard dimensions
func (se *ScoringEngine) initializeStandardDimensions() {
	dimensions := []*ScoringDimension{
		{
			Name:        "keyword_alignment",
			Description: "Alignment based on keyword matching",
			Weight:      0.3,
			Calculator:  NewKeywordAlignmentCalculator(),
			Threshold:   0.3,
			Priority:    1,
			Category:    "content",
		},
		{
			Name:        "technology_alignment",
			Description: "Alignment based on technology stack",
			Weight:      0.25,
			Calculator:  NewTechnologyAlignmentCalculator(),
			Threshold:   0.2,
			Priority:    2,
			Category:    "technical",
		},
		{
			Name:        "purpose_alignment",
			Description: "Alignment based on stated purpose",
			Weight:      0.2,
			Calculator:  NewPurposeAlignmentCalculator(),
			Threshold:   0.25,
			Priority:    1,
			Category:    "functional",
		},
		{
			Name:        "phase_alignment",
			Description: "Alignment with project phase",
			Weight:      0.15,
			Calculator:  NewPhaseAlignmentCalculator(),
			Threshold:   0.3,
			Priority:    3,
			Category:    "temporal",
		},
		{
			Name:        "context_relevance",
			Description: "Overall context relevance",
			Weight:      0.1,
			Calculator:  NewContextRelevanceCalculator(),
			Threshold:   0.2,
			Priority:    4,
			Category:    "contextual",
		},
	}

	se.dimensions = dimensions
}

// Additional calculator implementations would follow similar patterns...

// PurposeAlignmentCalculator calculates alignment based on stated purpose
type PurposeAlignmentCalculator struct {
	name   string
	weight float64
}

func NewPurposeAlignmentCalculator() *PurposeAlignmentCalculator {
	return &PurposeAlignmentCalculator{
		name:   "purpose_alignment",
		weight: 0.2,
	}
}

func (pac *PurposeAlignmentCalculator) GetName() string { return pac.name }
func (pac *PurposeAlignmentCalculator) GetWeight() float64 { return pac.weight }
func (pac *PurposeAlignmentCalculator) Validate(node *slurpContext.ContextNode, goal *ProjectGoal) error {
	if node == nil || goal == nil {
		return fmt.Errorf("node and goal cannot be nil")
	}
	return nil
}

func (pac *PurposeAlignmentCalculator) Calculate(ctx context.Context, node *slurpContext.ContextNode, goal *ProjectGoal) (*DimensionScore, error) {
	// Semantic similarity between node purpose and goal description
	purposeAlignment := pac.calculateSemanticSimilarity(node.Purpose, goal.Description)
	
	return &DimensionScore{
		Dimension:    pac.name,
		Score:        purposeAlignment,
		Confidence:   0.7,
		Evidence:     []string{fmt.Sprintf("Purpose: %s", node.Purpose)},
		Reasoning:    "Semantic similarity between purpose and goal description",
		CalculatedAt: time.Now(),
	}, nil
}

func (pac *PurposeAlignmentCalculator) calculateSemanticSimilarity(purpose, description string) float64 {
	// Simple implementation - in production would use more sophisticated NLP
	purposeWords := strings.Fields(strings.ToLower(purpose))
	descWords := strings.Fields(strings.ToLower(description))
	
	matches := 0
	for _, pWord := range purposeWords {
		for _, dWord := range descWords {
			if pWord == dWord || strings.Contains(pWord, dWord) || strings.Contains(dWord, pWord) {
				matches++
				break
			}
		}
	}
	
	if len(purposeWords) == 0 {
		return 0.0
	}
	
	return float64(matches) / float64(len(purposeWords))
}

// PhaseAlignmentCalculator calculates alignment with project phase
type PhaseAlignmentCalculator struct {
	name   string
	weight float64
}

func NewPhaseAlignmentCalculator() *PhaseAlignmentCalculator {
	return &PhaseAlignmentCalculator{
		name:   "phase_alignment",
		weight: 0.15,
	}
}

func (phac *PhaseAlignmentCalculator) GetName() string { return phac.name }
func (phac *PhaseAlignmentCalculator) GetWeight() float64 { return phac.weight }
func (phac *PhaseAlignmentCalculator) Validate(node *slurpContext.ContextNode, goal *ProjectGoal) error {
	return nil
}

func (phac *PhaseAlignmentCalculator) Calculate(ctx context.Context, node *slurpContext.ContextNode, goal *ProjectGoal) (*DimensionScore, error) {
	// Phase alignment logic
	phaseScore := phac.calculatePhaseRelevance(node, goal.Phase)
	
	return &DimensionScore{
		Dimension:    phac.name,
		Score:        phaseScore,
		Confidence:   0.8,
		Evidence:     []string{fmt.Sprintf("Goal phase: %s", goal.Phase)},
		Reasoning:    "Alignment with current project phase",
		CalculatedAt: time.Now(),
	}, nil
}

func (phac *PhaseAlignmentCalculator) calculatePhaseRelevance(node *slurpContext.ContextNode, phase string) float64 {
	// Simple phase relevance calculation
	phaseRelevance := map[string]map[string]float64{
		"planning": {
			"documentation": 0.9,
			"architecture":  0.8,
			"research":      0.9,
			"design":        0.8,
		},
		"development": {
			"implementation": 0.9,
			"testing":       0.7,
			"coding":        0.9,
			"api":           0.8,
		},
		"testing": {
			"testing":    0.9,
			"quality":    0.8,
			"validation": 0.9,
			"bug":        0.7,
		},
		"deployment": {
			"deployment":     0.9,
			"infrastructure": 0.8,
			"monitoring":     0.8,
			"production":     0.9,
		},
	}
	
	nodeText := strings.ToLower(node.Purpose + " " + node.Summary)
	relevanceMap, exists := phaseRelevance[strings.ToLower(phase)]
	if !exists {
		return 0.5 // Default relevance
	}
	
	maxRelevance := 0.0
	for keyword, score := range relevanceMap {
		if strings.Contains(nodeText, keyword) {
			if score > maxRelevance {
				maxRelevance = score
			}
		}
	}
	
	if maxRelevance == 0.0 {
		return 0.4 // Default when no specific phase keywords found
	}
	
	return maxRelevance
}

// ContextRelevanceCalculator calculates overall context relevance
type ContextRelevanceCalculator struct {
	name   string
	weight float64
}

func NewContextRelevanceCalculator() *ContextRelevanceCalculator {
	return &ContextRelevanceCalculator{
		name:   "context_relevance",
		weight: 0.1,
	}
}

func (crc *ContextRelevanceCalculator) GetName() string { return crc.name }
func (crc *ContextRelevanceCalculator) GetWeight() float64 { return crc.weight }
func (crc *ContextRelevanceCalculator) Validate(node *slurpContext.ContextNode, goal *ProjectGoal) error {
	return nil
}

func (crc *ContextRelevanceCalculator) Calculate(ctx context.Context, node *slurpContext.ContextNode, goal *ProjectGoal) (*DimensionScore, error) {
	// Calculate overall context relevance
	relevanceScore := crc.calculateRelevance(node, goal)
	
	return &DimensionScore{
		Dimension:    crc.name,
		Score:        relevanceScore,
		Confidence:   0.6,
		Evidence:     []string{"Overall context assessment"},
		Reasoning:    "Calculated based on multiple context factors",
		CalculatedAt: time.Now(),
	}, nil
}

func (crc *ContextRelevanceCalculator) calculateRelevance(node *slurpContext.ContextNode, goal *ProjectGoal) float64 {
	// Combine multiple factors for overall relevance
	factors := []float64{}
	
	// Factor 1: Specificity vs Goal Priority
	specificityFactor := float64(node.ContextSpecificity) / 10.0 * (1.0 / float64(goal.Priority))
	factors = append(factors, specificityFactor)
	
	// Factor 2: RAG Confidence
	factors = append(factors, node.RAGConfidence)
	
	// Factor 3: Technology richness
	techFactor := math.Min(1.0, float64(len(node.Technologies))/3.0)
	factors = append(factors, techFactor)
	
	// Factor 4: Insight richness
	insightFactor := math.Min(1.0, float64(len(node.Insights))/5.0)
	factors = append(factors, insightFactor)
	
	// Calculate weighted average
	totalWeight := 0.0
	weightedSum := 0.0
	weights := []float64{0.4, 0.3, 0.2, 0.1}
	
	for i, factor := range factors {
		if i < len(weights) {
			weightedSum += factor * weights[i]
			totalWeight += weights[i]
		}
	}
	
	if totalWeight == 0.0 {
		return 0.5
	}
	
	return weightedSum / totalWeight
}

// Helper methods for scoring engine components

func NewWeightConfiguration() *WeightConfiguration {
	return &WeightConfiguration{
		GlobalWeights:  make(map[string]float64),
		RoleWeights:    make(map[string]map[string]float64),
		PhaseWeights:   make(map[string]map[string]float64),
		ProjectWeights: make(map[string]map[string]float64),
		DynamicWeights: true,
		LastUpdated:    time.Now(),
	}
}

func NewScoreNormalizer() *ScoreNormalizer {
	return &ScoreNormalizer{
		normalizationMethod: "z_score",
		referenceData: &NormalizationReference{
			HistoricalScores: make(map[string]*ScoreDistribution),
			Percentiles:      make(map[string]map[int]float64),
			LastCalculated:   time.Now(),
		},
	}
}

func NewScoreAggregator() *ScoreAggregator {
	return &ScoreAggregator{
		method: "weighted_average",
	}
}

func (sa *ScoreAggregator) aggregate(scores []*DimensionScore, weights *WeightConfiguration) float64 {
	if len(scores) == 0 {
		return 0.0
	}
	
	totalWeight := 0.0
	weightedSum := 0.0
	
	for _, score := range scores {
		weight := 1.0 // Default weight
		if globalWeight, exists := weights.GlobalWeights[score.Dimension]; exists {
			weight = globalWeight
		}
		
		weightedSum += score.Score * weight
		totalWeight += weight
	}
	
	if totalWeight == 0.0 {
		return 0.0
	}
	
	return weightedSum / totalWeight
}

func (sn *ScoreNormalizer) normalize(score float64, dimension string) float64 {
	// Simple normalization - in production would use more sophisticated methods
	return math.Max(0.0, math.Min(1.0, score))
}

// Create remaining component constructors...

func NewDimensionAnalyzer() *DimensionAnalyzer {
	return &DimensionAnalyzer{
		calculators: make(map[string]DimensionCalculator),
	}
}

func NewPriorityCalculator() *PriorityCalculator {
	return &PriorityCalculator{
		priorityMatrix: &PriorityMatrix{
			Goals:        make(map[string]int),
			Phases:       make(map[string]int),
			Technologies: make(map[string]int),
			Roles:        make(map[string]int),
			Urgency:      make(map[string]float64),
			Impact:       make(map[string]float64),
		},
		timeFactors: &TimeFactors{
			DecayFunction:  "exponential",
			HalfLife:       30 * 24 * time.Hour,
			UrgencyBoost:   1.5,
			DeadlineWeight: 2.0,
			PhaseAlignment: make(map[string]float64),
		},
	}
}

func (pc *PriorityCalculator) adjustScores(scores []*DimensionScore, goal *ProjectGoal, role string) []*DimensionScore {
	adjusted := make([]*DimensionScore, len(scores))
	
	for i, score := range scores {
		adjustedScore := *score // Copy the score
		
		// Apply priority adjustments
		priorityMultiplier := pc.calculatePriorityMultiplier(goal, role)
		adjustedScore.Score *= priorityMultiplier
		
		// Apply time-based adjustments
		timeMultiplier := pc.calculateTimeMultiplier(goal)
		adjustedScore.Score *= timeMultiplier
		
		// Ensure score stays within bounds
		adjustedScore.Score = math.Max(0.0, math.Min(1.0, adjustedScore.Score))
		
		adjusted[i] = &adjustedScore
	}
	
	return adjusted
}

func (pc *PriorityCalculator) calculatePriorityMultiplier(goal *ProjectGoal, role string) float64 {
	// Base multiplier from goal priority (inverse - higher priority = higher multiplier)
	priorityMultiplier := 1.0 + (1.0 / float64(goal.Priority))
	
	// Role-specific adjustments
	if roleMultiplier, exists := pc.priorityMatrix.Urgency[role]; exists {
		priorityMultiplier *= roleMultiplier
	}
	
	return priorityMultiplier
}

func (pc *PriorityCalculator) calculateTimeMultiplier(goal *ProjectGoal) float64 {
	if goal.Deadline == nil {
		return 1.0
	}
	
	// Calculate urgency based on deadline proximity
	timeToDeadline := time.Until(*goal.Deadline)
	if timeToDeadline <= 0 {
		return pc.timeFactors.UrgencyBoost // Past deadline
	}
	
	// Exponential urgency increase as deadline approaches
	urgencyFactor := math.Exp(-float64(timeToDeadline) / float64(pc.timeFactors.HalfLife))
	return 1.0 + urgencyFactor*pc.timeFactors.DeadlineWeight
}

func NewTrendAnalyzer() *TrendAnalyzer {
	return &TrendAnalyzer{
		historicalData: &AlignmentHistory{
			records:    []*AlignmentRecord{},
			maxRecords: 10000,
			retention:  90 * 24 * time.Hour,
		},
		trendDetector: &TrendDetector{
			methods: []TrendDetectionMethod{},
		},
		predictor: &AlignmentPredictor{
			models: []PredictionModel{},
		},
	}
}

func (ta *TrendAnalyzer) analyzeTrends(nodePath, goalID string) []*Trend {
	// Simple trend analysis - in production would be more sophisticated
	return []*Trend{}
}

func (ta *TrendAnalyzer) recordAlignment(assessment *AlignmentAssessment) {
	record := &AlignmentRecord{
		NodePath:   assessment.NodePath,
		GoalID:     assessment.GoalID,
		Score:      assessment.OverallScore,
		Dimensions: assessment.DimensionScores,
		Context:    assessment.Context,
		Timestamp:  assessment.AssessedAt,
		Role:       assessment.Role,
		Phase:      assessment.Phase,
	}
	
	ta.historicalData.mu.Lock()
	ta.historicalData.records = append(ta.historicalData.records, record)
	
	// Trim old records if necessary
	if len(ta.historicalData.records) > ta.historicalData.maxRecords {
		ta.historicalData.records = ta.historicalData.records[1:]
	}
	ta.historicalData.mu.Unlock()
}

func (ap *AlignmentPredictor) predictAlignment(ctx context.Context, nodePath, goalID string, horizon time.Duration) ([]*AlignmentPrediction, error) {
	// Simple prediction - in production would use ML models
	return []*AlignmentPrediction{}, nil
}

func NewRecommendationEngine() *RecommendationEngine {
	return &RecommendationEngine{
		ruleEngine:  NewRecommendationRuleEngine(),
		mlEngine:    NewMLRecommendationEngine(),
		prioritizer: NewRecommendationPrioritizer(),
	}
}

func (re *RecommendationEngine) generateRecommendations(ctx context.Context, node *slurpContext.ContextNode, goal *ProjectGoal, scores []*DimensionScore) ([]*Recommendation, error) {
	recommendations := []*Recommendation{}
	
	// Generate rule-based recommendations
	ruleRecs, err := re.ruleEngine.generateRecommendations(scores)
	if err == nil {
		recommendations = append(recommendations, ruleRecs...)
	}
	
	// Generate ML-based recommendations (if available)
	// mlRecs, err := re.mlEngine.generateRecommendations(ctx, node, scores)
	// if err == nil {
	//     recommendations = append(recommendations, mlRecs...)
	// }
	
	// Prioritize recommendations
	prioritized := re.prioritizer.prioritize(recommendations)
	
	return prioritized, nil
}

func NewRecommendationRuleEngine() *RecommendationRuleEngine {
	engine := &RecommendationRuleEngine{
		rules: []*RecommendationRule{},
	}
	
	engine.loadDefaultRules()
	return engine
}

func (rre *RecommendationRuleEngine) loadDefaultRules() {
	rules := []*RecommendationRule{
		{
			ID:   "low_keyword_alignment",
			Name: "Improve Keyword Alignment",
			Condition: RecommendationCondition{
				DimensionFilters: map[string]float64{"keyword_alignment": 0.3},
				LogicalOperator:  "LT",
			},
			Action: RecommendationAction{
				Type:        "content_enhancement",
				Description: "Add more relevant keywords to improve alignment with project goals",
				Impact:      0.7,
				Effort:      0.3,
				Timeline:    "short",
				Resources:   []string{"documentation", "content_review"},
			},
			Priority:   1,
			Confidence: 0.8,
			Category:   "content",
		},
		{
			ID:   "technology_mismatch",
			Name: "Address Technology Mismatch",
			Condition: RecommendationCondition{
				DimensionFilters: map[string]float64{"technology_alignment": 0.2},
				LogicalOperator:  "LT",
			},
			Action: RecommendationAction{
				Type:        "technology_update",
				Description: "Update technology stack or documentation to better align with project goals",
				Impact:      0.8,
				Effort:      0.6,
				Timeline:    "medium",
				Resources:   []string{"development", "architecture_review"},
			},
			Priority:   2,
			Confidence: 0.7,
			Category:   "technical",
		},
	}
	
	rre.rules = rules
}

func (rre *RecommendationRuleEngine) generateRecommendations(scores []*DimensionScore) ([]*Recommendation, error) {
	recommendations := []*Recommendation{}
	
	for _, rule := range rre.rules {
		if rre.evaluateCondition(rule.Condition, scores) {
			rec := &Recommendation{
				ID:          rule.ID,
				Title:       rule.Name,
				Description: rule.Action.Description,
				Action:      &rule.Action,
				Priority:    rule.Priority,
				Confidence:  rule.Confidence,
				Impact:      rule.Action.Impact,
				Effort:      rule.Action.Effort,
				Timeline:    rule.Action.Timeline,
				Category:    rule.Category,
				Resources:   rule.Action.Resources,
				GeneratedAt: time.Now(),
				GeneratedBy: "RuleEngine",
			}
			recommendations = append(recommendations, rec)
		}
	}
	
	return recommendations, nil
}

func (rre *RecommendationRuleEngine) evaluateCondition(condition RecommendationCondition, scores []*DimensionScore) bool {
	for dimension, threshold := range condition.DimensionFilters {
		for _, score := range scores {
			if score.Dimension == dimension {
				switch condition.LogicalOperator {
				case "LT":
					return score.Score < threshold
				case "GT":
					return score.Score > threshold
				case "EQ":
					return math.Abs(score.Score-threshold) < 0.01
				default:
					return score.Score < threshold
				}
			}
		}
	}
	return false
}

func NewMLRecommendationEngine() *MLRecommendationEngine {
	return &MLRecommendationEngine{
		models: []RecommendationModel{},
	}
}

func NewRecommendationPrioritizer() *RecommendationPrioritizer {
	return &RecommendationPrioritizer{
		criteria: []PrioritizationCriterion{
			{
				Name:   "impact_effort_ratio",
				Weight: 0.4,
				Calculator: func(rec *Recommendation) float64 {
					if rec.Effort == 0 {
						return rec.Impact
					}
					return rec.Impact / rec.Effort
				},
			},
			{
				Name:   "confidence",
				Weight: 0.3,
				Calculator: func(rec *Recommendation) float64 {
					return rec.Confidence
				},
			},
			{
				Name:   "priority",
				Weight: 0.3,
				Calculator: func(rec *Recommendation) float64 {
					return 1.0 / float64(rec.Priority) // Inverse priority
				},
			},
		},
	}
}

func (rp *RecommendationPrioritizer) prioritize(recommendations []*Recommendation) []*Recommendation {
	// Calculate priority scores for each recommendation
	for _, rec := range recommendations {
		score := 0.0
		totalWeight := 0.0
		
		for _, criterion := range rp.criteria {
			criterionScore := criterion.Calculator(rec)
			score += criterionScore * criterion.Weight
			totalWeight += criterion.Weight
		}
		
		if totalWeight > 0 {
			rec.Priority = int((score / totalWeight) * 100) // Convert to 0-100 scale
		}
	}
	
	// Sort by priority score (higher is better)
	sort.Slice(recommendations, func(i, j int) bool {
		return recommendations[i].Priority > recommendations[j].Priority
	})
	
	return recommendations
}

func NewAlignmentMetrics() *AlignmentMetrics {
	return &AlignmentMetrics{
		dimensionPerformance: make(map[string]*DimensionMetrics),
		goalPerformance:      make(map[string]*GoalMetrics),
		lastReset:            time.Now(),
	}
}

func (am *AlignmentMetrics) recordAssessment(duration time.Duration) {
	am.mu.Lock()
	defer am.mu.Unlock()
	am.totalAssessments++
}

func (am *AlignmentMetrics) recordSuccess(score float64) {
	am.mu.Lock()
	defer am.mu.Unlock()
	am.successfulAssessments++
	
	// Update average score
	if am.totalAssessments == 1 {
		am.averageScore = score
	} else {
		am.averageScore = (am.averageScore*float64(am.totalAssessments-1) + score) / float64(am.totalAssessments)
	}
}

func (am *AlignmentMetrics) recordFailure() {
	am.mu.Lock()
	defer am.mu.Unlock()
	// Failure count is totalAssessments - successfulAssessments
}

func (am *AlignmentMetrics) GetMetrics() map[string]interface{} {
	am.mu.RLock()
	defer am.mu.RUnlock()
	
	successRate := 0.0
	if am.totalAssessments > 0 {
		successRate = float64(am.successfulAssessments) / float64(am.totalAssessments)
	}
	
	return map[string]interface{}{
		"total_assessments":     am.totalAssessments,
		"successful_assessments": am.successfulAssessments,
		"success_rate":          successRate,
		"average_score":         am.averageScore,
		"last_reset":            am.lastReset,
	}
}