// Package models contains domain models for claude-mnemonic.
package models

// ConceptWeight represents a configurable weight for a concept.
type ConceptWeight struct {
	Concept   string  `db:"concept" json:"concept"`
	UpdatedAt string  `db:"updated_at" json:"updated_at"`
	Weight    float64 `db:"weight" json:"weight"`
}

// UserFeedbackType represents the type of user feedback.
type UserFeedbackType int

const (
	// FeedbackNegative represents a thumbs down.
	FeedbackNegative UserFeedbackType = -1
	// FeedbackNeutral represents no feedback.
	FeedbackNeutral UserFeedbackType = 0
	// FeedbackPositive represents a thumbs up.
	FeedbackPositive UserFeedbackType = 1
)

// DefaultConceptWeights contains the default weights for concepts.
// Higher weights indicate more important concepts.
var DefaultConceptWeights = map[string]float64{
	// Critical concepts (0.25-0.30)
	"security": 0.30, // Security issues are most critical

	// High importance (0.20-0.25)
	"gotcha":        0.25, // Gotchas prevent future mistakes
	"best-practice": 0.20, // Best practices guide development
	"anti-pattern":  0.20, // Anti-patterns prevent bad code

	// Medium importance (0.10-0.15)
	"architecture":     0.15, // Architectural decisions have lasting impact
	"performance":      0.15, // Performance patterns matter for scale
	"error-handling":   0.15, // Error handling prevents failures
	"pattern":          0.10, // General patterns are useful
	"testing":          0.10, // Testing knowledge helps quality
	"debugging":        0.10, // Debugging tips save time
	"problem-solution": 0.10, // Problem-solution pairs are actionable
	"trade-off":        0.10, // Trade-offs inform decisions

	// Lower importance (0.05)
	"workflow":      0.05, // Workflow optimizations are nice-to-have
	"tooling":       0.05, // Tooling preferences are subjective
	"how-it-works":  0.05, // Understanding is foundational but less urgent
	"why-it-exists": 0.05, // Context is helpful but less actionable
	"what-changed":  0.05, // Changes are informational
}

// TypeBaseScores contains the base importance multipliers for each observation type.
// These are multiplied with the core score to weight different observation types.
var TypeBaseScores = map[ObservationType]float64{
	ObsTypeBugfix:    1.3, // Bugfixes are valuable - prevent regressions
	ObsTypeFeature:   1.2, // New features expand capabilities
	ObsTypeDiscovery: 1.1, // Discoveries inform future work
	ObsTypeDecision:  1.1, // Architectural decisions guide development
	ObsTypeRefactor:  1.0, // Refactoring is neutral
	ObsTypeChange:    0.9, // Minor changes are slightly less important
}

// ScoringConfig contains all scoring weights and parameters.
type ScoringConfig struct {
	ConceptWeights      map[string]float64 `json:"concept_weights"`
	RecencyHalfLifeDays float64            `json:"recency_half_life_days"`
	FeedbackWeight      float64            `json:"feedback_weight"`
	ConceptWeight       float64            `json:"concept_weight"`
	RetrievalWeight     float64            `json:"retrieval_weight"`
	MinScore            float64            `json:"min_score"`
}

// DefaultScoringConfig returns the default scoring configuration.
func DefaultScoringConfig() *ScoringConfig {
	conceptWeights := make(map[string]float64, len(DefaultConceptWeights))
	for k, v := range DefaultConceptWeights {
		conceptWeights[k] = v
	}

	return &ScoringConfig{
		RecencyHalfLifeDays: 7.0,  // Score halves every 7 days
		FeedbackWeight:      0.30, // Feedback has moderate impact
		ConceptWeight:       0.20, // Concept weights have smaller impact
		RetrievalWeight:     0.15, // Retrieval has smallest impact
		ConceptWeights:      conceptWeights,
		MinScore:            0.01, // Never completely disappear
	}
}

// TypeBaseScore returns the base weight for an observation type.
func TypeBaseScore(t ObservationType) float64 {
	if score, ok := TypeBaseScores[t]; ok {
		return score
	}
	return 1.0 // Default for unknown types
}
