package intelligence

import (
	"crypto/md5"
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"math"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"time"

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

// Utility functions and helper types for the intelligence engine

// ContentAnalysisUtils provides utilities for content analysis
type ContentAnalysisUtils struct{}

// NewContentAnalysisUtils creates new content analysis utilities
func NewContentAnalysisUtils() *ContentAnalysisUtils {
	return &ContentAnalysisUtils{}
}

// ExtractIdentifiers extracts identifiers from code content
func (cau *ContentAnalysisUtils) ExtractIdentifiers(content, language string) (functions, classes, variables []string) {
	switch strings.ToLower(language) {
	case "go":
		return cau.extractGoIdentifiers(content)
	case "javascript", "typescript":
		return cau.extractJSIdentifiers(content)
	case "python":
		return cau.extractPythonIdentifiers(content)
	case "java":
		return cau.extractJavaIdentifiers(content)
	case "rust":
		return cau.extractRustIdentifiers(content)
	default:
		return cau.extractGenericIdentifiers(content)
	}
}

func (cau *ContentAnalysisUtils) extractGoIdentifiers(content string) (functions, classes, variables []string) {
	// Go function pattern: func FunctionName
	funcPattern := regexp.MustCompile(`func\s+(\w+)\s*\(`)
	funcMatches := funcPattern.FindAllStringSubmatch(content, -1)
	for _, match := range funcMatches {
		if len(match) > 1 {
			functions = append(functions, match[1])
		}
	}

	// Go type/struct pattern: type TypeName struct
	typePattern := regexp.MustCompile(`type\s+(\w+)\s+struct`)
	typeMatches := typePattern.FindAllStringSubmatch(content, -1)
	for _, match := range typeMatches {
		if len(match) > 1 {
			classes = append(classes, match[1])
		}
	}

	// Go variable pattern: var varName or varName :=
	varPattern := regexp.MustCompile(`(?:var\s+(\w+)|(\w+)\s*:=)`)
	varMatches := varPattern.FindAllStringSubmatch(content, -1)
	for _, match := range varMatches {
		if len(match) > 1 && match[1] != "" {
			variables = append(variables, match[1])
		} else if len(match) > 2 && match[2] != "" {
			variables = append(variables, match[2])
		}
	}

	return removeDuplicates(functions), removeDuplicates(classes), removeDuplicates(variables)
}

func (cau *ContentAnalysisUtils) extractJSIdentifiers(content string) (functions, classes, variables []string) {
	// JavaScript function patterns
	funcPatterns := []*regexp.Regexp{
		regexp.MustCompile(`function\s+(\w+)\s*\(`),
		regexp.MustCompile(`(\w+)\s*:\s*function\s*\(`),
		regexp.MustCompile(`const\s+(\w+)\s*=\s*\(`),
		regexp.MustCompile(`(?:let|var)\s+(\w+)\s*=\s*\(`),
	}

	for _, pattern := range funcPatterns {
		matches := pattern.FindAllStringSubmatch(content, -1)
		for _, match := range matches {
			if len(match) > 1 {
				functions = append(functions, match[1])
			}
		}
	}

	// JavaScript class pattern
	classPattern := regexp.MustCompile(`class\s+(\w+)`)
	classMatches := classPattern.FindAllStringSubmatch(content, -1)
	for _, match := range classMatches {
		if len(match) > 1 {
			classes = append(classes, match[1])
		}
	}

	// JavaScript variable patterns
	varPatterns := []*regexp.Regexp{
		regexp.MustCompile(`(?:const|let|var)\s+(\w+)`),
	}

	for _, pattern := range varPatterns {
		matches := pattern.FindAllStringSubmatch(content, -1)
		for _, match := range matches {
			if len(match) > 1 {
				variables = append(variables, match[1])
			}
		}
	}

	return removeDuplicates(functions), removeDuplicates(classes), removeDuplicates(variables)
}

func (cau *ContentAnalysisUtils) extractPythonIdentifiers(content string) (functions, classes, variables []string) {
	// Python function pattern
	funcPattern := regexp.MustCompile(`def\s+(\w+)\s*\(`)
	funcMatches := funcPattern.FindAllStringSubmatch(content, -1)
	for _, match := range funcMatches {
		if len(match) > 1 {
			functions = append(functions, match[1])
		}
	}

	// Python class pattern
	classPattern := regexp.MustCompile(`class\s+(\w+)`)
	classMatches := classPattern.FindAllStringSubmatch(content, -1)
	for _, match := range classMatches {
		if len(match) > 1 {
			classes = append(classes, match[1])
		}
	}

	// Python variable pattern (simple assignment)
	varPattern := regexp.MustCompile(`^(\w+)\s*=`)
	lines := strings.Split(content, "\n")
	for _, line := range lines {
		line = strings.TrimSpace(line)
		if matches := varPattern.FindStringSubmatch(line); matches != nil && len(matches) > 1 {
			variables = append(variables, matches[1])
		}
	}

	return removeDuplicates(functions), removeDuplicates(classes), removeDuplicates(variables)
}

func (cau *ContentAnalysisUtils) extractJavaIdentifiers(content string) (functions, classes, variables []string) {
	// Java method pattern
	methodPattern := regexp.MustCompile(`(?:public|private|protected)?\s*(?:static)?\s*\w+\s+(\w+)\s*\(`)
	methodMatches := methodPattern.FindAllStringSubmatch(content, -1)
	for _, match := range methodMatches {
		if len(match) > 1 {
			functions = append(functions, match[1])
		}
	}

	// Java class pattern
	classPattern := regexp.MustCompile(`(?:public|private)?\s*class\s+(\w+)`)
	classMatches := classPattern.FindAllStringSubmatch(content, -1)
	for _, match := range classMatches {
		if len(match) > 1 {
			classes = append(classes, match[1])
		}
	}

	// Java field/variable pattern
	varPattern := regexp.MustCompile(`(?:private|public|protected)?\s*\w+\s+(\w+)\s*[=;]`)
	varMatches := varPattern.FindAllStringSubmatch(content, -1)
	for _, match := range varMatches {
		if len(match) > 1 {
			variables = append(variables, match[1])
		}
	}

	return removeDuplicates(functions), removeDuplicates(classes), removeDuplicates(variables)
}

func (cau *ContentAnalysisUtils) extractRustIdentifiers(content string) (functions, classes, variables []string) {
	// Rust function pattern
	funcPattern := regexp.MustCompile(`fn\s+(\w+)\s*\(`)
	funcMatches := funcPattern.FindAllStringSubmatch(content, -1)
	for _, match := range funcMatches {
		if len(match) > 1 {
			functions = append(functions, match[1])
		}
	}

	// Rust struct pattern
	structPattern := regexp.MustCompile(`struct\s+(\w+)`)
	structMatches := structPattern.FindAllStringSubmatch(content, -1)
	for _, match := range structMatches {
		if len(match) > 1 {
			classes = append(classes, match[1])
		}
	}

	// Rust variable pattern
	varPattern := regexp.MustCompile(`let\s+(?:mut\s+)?(\w+)`)
	varMatches := varPattern.FindAllStringSubmatch(content, -1)
	for _, match := range varMatches {
		if len(match) > 1 {
			variables = append(variables, match[1])
		}
	}

	return removeDuplicates(functions), removeDuplicates(classes), removeDuplicates(variables)
}

func (cau *ContentAnalysisUtils) extractGenericIdentifiers(content string) (functions, classes, variables []string) {
	// Generic patterns for unknown languages
	words := regexp.MustCompile(`\b[a-zA-Z_]\w*\b`).FindAllString(content, -1)
	return removeDuplicates(words), []string{}, []string{}
}

// CalculateComplexity calculates code complexity based on various metrics
func (cau *ContentAnalysisUtils) CalculateComplexity(content, language string) float64 {
	complexity := 0.0
	
	// Lines of code (basic metric)
	lines := strings.Split(content, "\n")
	nonEmptyLines := 0
	for _, line := range lines {
		if strings.TrimSpace(line) != "" && !strings.HasPrefix(strings.TrimSpace(line), "//") {
			nonEmptyLines++
		}
	}
	
	// Base complexity from lines of code
	complexity += float64(nonEmptyLines) * 0.1
	
	// Control flow complexity (if, for, while, switch, etc.)
	controlFlowPatterns := []*regexp.Regexp{
		regexp.MustCompile(`\b(?:if|for|while|switch|case)\b`),
		regexp.MustCompile(`\b(?:try|catch|finally)\b`),
		regexp.MustCompile(`\?\s*.*\s*:`), // ternary operator
	}
	
	for _, pattern := range controlFlowPatterns {
		matches := pattern.FindAllString(content, -1)
		complexity += float64(len(matches)) * 0.5
	}
	
	// Function complexity
	functions, _, _ := cau.ExtractIdentifiers(content, language)
	complexity += float64(len(functions)) * 0.3
	
	// Nesting level (simple approximation)
	maxNesting := 0
	currentNesting := 0
	for _, line := range lines {
		trimmed := strings.TrimSpace(line)
		openBraces := strings.Count(trimmed, "{")
		closeBraces := strings.Count(trimmed, "}")
		currentNesting += openBraces - closeBraces
		if currentNesting > maxNesting {
			maxNesting = currentNesting
		}
	}
	complexity += float64(maxNesting) * 0.2
	
	// Normalize to 0-10 scale
	return math.Min(10.0, complexity/10.0)
}

// DetectTechnologies detects technologies used in the content
func (cau *ContentAnalysisUtils) DetectTechnologies(content, filename string) []string {
	technologies := []string{}
	lowerContent := strings.ToLower(content)
	ext := strings.ToLower(filepath.Ext(filename))
	
	// Language detection
	languageMap := map[string][]string{
		".go":   {"go", "golang"},
		".py":   {"python"},
		".js":   {"javascript", "node.js"},
		".jsx":  {"javascript", "react", "jsx"},
		".ts":   {"typescript"},
		".tsx":  {"typescript", "react", "jsx"},
		".java": {"java"},
		".kt":   {"kotlin"},
		".rs":   {"rust"},
		".cpp":  {"c++"},
		".c":    {"c"},
		".cs":   {"c#", ".net"},
		".php":  {"php"},
		".rb":   {"ruby"},
		".swift": {"swift"},
		".scala": {"scala"},
		".clj":  {"clojure"},
		".hs":   {"haskell"},
		".ml":   {"ocaml"},
	}
	
	if langs, exists := languageMap[ext]; exists {
		technologies = append(technologies, langs...)
	}
	
	// Framework and library detection
	frameworkPatterns := map[string][]string{
		"react":          {"import.*react", "from [\"']react[\"']", "<.*/>", "jsx"},
		"vue":            {"import.*vue", "from [\"']vue[\"']", "<template>", "vue"},
		"angular":        {"import.*@angular", "from [\"']@angular", "ngmodule", "component"},
		"express":        {"import.*express", "require.*express", "app.get", "app.post"},
		"django":         {"from django", "import django", "django.db", "models.model"},
		"flask":          {"from flask", "import flask", "@app.route", "flask.request"},
		"spring":         {"@springboot", "@controller", "@service", "@repository"},
		"hibernate":      {"@entity", "@table", "@column", "hibernate"},
		"jquery":         {"$\\(", "jquery"},
		"bootstrap":      {"bootstrap", "btn-", "col-", "row"},
		"docker":         {"dockerfile", "docker-compose", "from.*:", "run.*"},
		"kubernetes":     {"apiversion:", "kind:", "metadata:", "spec:"},
		"terraform":      {"\\.tf$", "resource \"", "provider \"", "terraform"},
		"ansible":        {"\\.yml$", "hosts:", "tasks:", "playbook"},
		"jenkins":        {"jenkinsfile", "pipeline", "stage", "steps"},
		"git":            {"\\.git", "git add", "git commit", "git push"},
		"mysql":          {"mysql", "select.*from", "insert into", "create table"},
		"postgresql":     {"postgresql", "postgres", "psql"},
		"mongodb":        {"mongodb", "mongo", "find\\(", "insert\\("},
		"redis":          {"redis", "set.*", "get.*", "rpush"},
		"elasticsearch":  {"elasticsearch", "elastic", "query.*", "search.*"},
		"graphql":        {"graphql", "query.*{", "mutation.*{", "subscription.*{"},
		"grpc":           {"grpc", "proto", "service.*rpc", "\\.proto$"},
		"websocket":      {"websocket", "ws://", "wss://", "socket.io"},
		"jwt":            {"jwt", "jsonwebtoken", "bearer.*token"},
		"oauth":          {"oauth", "oauth2", "client_id", "client_secret"},
		"ssl":            {"ssl", "tls", "https", "certificate"},
		"encryption":     {"encrypt", "decrypt", "bcrypt", "sha256"},
	}
	
	for tech, patterns := range frameworkPatterns {
		for _, pattern := range patterns {
			if matched, _ := regexp.MatchString(pattern, lowerContent); matched {
				technologies = append(technologies, tech)
				break
			}
		}
	}
	
	return removeDuplicates(technologies)
}

// ScoreUtils provides utilities for scoring and metrics
type ScoreUtils struct{}

// NewScoreUtils creates new score utilities
func NewScoreUtils() *ScoreUtils {
	return &ScoreUtils{}
}

// NormalizeScore normalizes a score to a 0-1 range
func (su *ScoreUtils) NormalizeScore(score, min, max float64) float64 {
	if max == min {
		return 0.5 // Default middle value when range is zero
	}
	return math.Max(0, math.Min(1, (score-min)/(max-min)))
}

// CalculateWeightedScore calculates weighted score from multiple scores
func (su *ScoreUtils) CalculateWeightedScore(scores map[string]float64, weights map[string]float64) float64 {
	totalWeight := 0.0
	weightedSum := 0.0
	
	for dimension, score := range scores {
		weight := weights[dimension]
		if weight == 0 {
			weight = 1.0 // Default weight
		}
		weightedSum += score * weight
		totalWeight += weight
	}
	
	if totalWeight == 0 {
		return 0.0
	}
	
	return weightedSum / totalWeight
}

// CalculatePercentile calculates percentile from a slice of values
func (su *ScoreUtils) CalculatePercentile(values []float64, percentile int) float64 {
	if len(values) == 0 {
		return 0.0
	}
	
	sorted := make([]float64, len(values))
	copy(sorted, values)
	sort.Float64s(sorted)
	
	if percentile <= 0 {
		return sorted[0]
	}
	if percentile >= 100 {
		return sorted[len(sorted)-1]
	}
	
	index := float64(percentile) / 100.0 * float64(len(sorted)-1)
	lower := int(math.Floor(index))
	upper := int(math.Ceil(index))
	
	if lower == upper {
		return sorted[lower]
	}
	
	// Linear interpolation
	lowerValue := sorted[lower]
	upperValue := sorted[upper]
	weight := index - float64(lower)
	
	return lowerValue + weight*(upperValue-lowerValue)
}

// CalculateStandardDeviation calculates standard deviation
func (su *ScoreUtils) CalculateStandardDeviation(values []float64) float64 {
	if len(values) <= 1 {
		return 0.0
	}
	
	// Calculate mean
	sum := 0.0
	for _, value := range values {
		sum += value
	}
	mean := sum / float64(len(values))
	
	// Calculate variance
	variance := 0.0
	for _, value := range values {
		diff := value - mean
		variance += diff * diff
	}
	variance /= float64(len(values) - 1)
	
	return math.Sqrt(variance)
}

// FileUtils provides file system utilities
type FileUtils struct{}

// NewFileUtils creates new file utilities
func NewFileUtils() *FileUtils {
	return &FileUtils{}
}

// GetFileSize returns file size in bytes
func (fu *FileUtils) GetFileSize(filePath string) (int64, error) {
	info, err := os.Stat(filePath)
	if err != nil {
		return 0, err
	}
	return info.Size(), nil
}

// GetFileModTime returns file modification time
func (fu *FileUtils) GetFileModTime(filePath string) (time.Time, error) {
	info, err := os.Stat(filePath)
	if err != nil {
		return time.Time{}, err
	}
	return info.ModTime(), nil
}

// IsTextFile determines if a file is a text file
func (fu *FileUtils) IsTextFile(filePath string) bool {
	ext := strings.ToLower(filepath.Ext(filePath))
	textExtensions := map[string]bool{
		".txt": true, ".md": true, ".go": true, ".py": true, ".js": true,
		".jsx": true, ".ts": true, ".tsx": true, ".java": true, ".cpp": true,
		".c": true, ".cs": true, ".php": true, ".rb": true, ".rs": true,
		".swift": true, ".kt": true, ".scala": true, ".clj": true, ".hs": true,
		".ml": true, ".json": true, ".xml": true, ".yaml": true, ".yml": true,
		".toml": true, ".ini": true, ".cfg": true, ".conf": true, ".html": true,
		".css": true, ".scss": true, ".sass": true, ".less": true, ".sql": true,
		".sh": true, ".bat": true, ".ps1": true, ".dockerfile": true,
	}
	return textExtensions[ext]
}

// WalkDirectory recursively walks a directory
func (fu *FileUtils) WalkDirectory(rootPath string, handler func(path string, info os.FileInfo) error) error {
	return filepath.Walk(rootPath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		return handler(path, info)
	})
}

// StringUtils provides string manipulation utilities
type StringUtils struct{}

// NewStringUtils creates new string utilities
func NewStringUtils() *StringUtils {
	return &StringUtils{}
}

// Similarity calculates string similarity using Jaccard index
func (su *StringUtils) Similarity(s1, s2 string) float64 {
	if s1 == s2 {
		return 1.0
	}
	
	words1 := strings.Fields(strings.ToLower(s1))
	words2 := strings.Fields(strings.ToLower(s2))
	
	if len(words1) == 0 && len(words2) == 0 {
		return 1.0
	}
	
	if len(words1) == 0 || len(words2) == 0 {
		return 0.0
	}
	
	set1 := make(map[string]bool)
	set2 := make(map[string]bool)
	
	for _, word := range words1 {
		set1[word] = true
	}
	for _, word := range words2 {
		set2[word] = true
	}
	
	intersection := 0
	for word := range set1 {
		if set2[word] {
			intersection++
		}
	}
	
	union := len(set1) + len(set2) - intersection
	
	if union == 0 {
		return 1.0
	}
	
	return float64(intersection) / float64(union)
}

// ExtractKeywords extracts keywords from text
func (su *StringUtils) ExtractKeywords(text string, minLength int) []string {
	// Common stop words
	stopWords := map[string]bool{
		"a": true, "an": true, "and": true, "are": true, "as": true, "at": true,
		"be": true, "by": true, "for": true, "from": true, "has": true, "he": true,
		"in": true, "is": true, "it": true, "its": true, "of": true, "on": true,
		"that": true, "the": true, "to": true, "was": true, "will": true, "with": true,
		"this": true, "these": true, "they": true, "them": true, "their": true,
		"have": true, "had": true, "been": true, "were": true, "said": true,
		"what": true, "when": true, "where": true, "who": true, "which": true, "why": true,
		"how": true, "all": true, "any": true, "both": true, "each": true, "few": true,
		"more": true, "most": true, "other": true, "some": true, "such": true,
		"no": true, "nor": true, "not": true, "only": true, "own": true, "same": true,
		"so": true, "than": true, "too": true, "very": true, "can": true, "could": true,
		"should": true, "would": true, "use": true, "used": true, "using": true,
	}
	
	// Extract words
	wordRegex := regexp.MustCompile(`\b[a-zA-Z]+\b`)
	words := wordRegex.FindAllString(strings.ToLower(text), -1)
	
	keywords := []string{}
	wordFreq := make(map[string]int)
	
	for _, word := range words {
		if len(word) >= minLength && !stopWords[word] {
			wordFreq[word]++
		}
	}
	
	// Sort by frequency and return top keywords
	type wordCount struct {
		word  string
		count int
	}
	
	var sortedWords []wordCount
	for word, count := range wordFreq {
		sortedWords = append(sortedWords, wordCount{word, count})
	}
	
	sort.Slice(sortedWords, func(i, j int) bool {
		return sortedWords[i].count > sortedWords[j].count
	})
	
	maxKeywords := 20
	for i, wc := range sortedWords {
		if i >= maxKeywords {
			break
		}
		keywords = append(keywords, wc.word)
	}
	
	return keywords
}

// TruncateText truncates text to specified length with ellipsis
func (su *StringUtils) TruncateText(text string, maxLength int) string {
	if len(text) <= maxLength {
		return text
	}
	if maxLength <= 3 {
		return text[:maxLength]
	}
	return text[:maxLength-3] + "..."
}

// HashUtils provides hashing utilities
type HashUtils struct{}

// NewHashUtils creates new hash utilities
func NewHashUtils() *HashUtils {
	return &HashUtils{}
}

// MD5Hash calculates MD5 hash of string
func (hu *HashUtils) MD5Hash(text string) string {
	hasher := md5.New()
	hasher.Write([]byte(text))
	return hex.EncodeToString(hasher.Sum(nil))
}

// GenerateID generates a random ID
func (hu *HashUtils) GenerateID(prefix string) string {
	bytes := make([]byte, 8)
	rand.Read(bytes)
	return fmt.Sprintf("%s_%x_%d", prefix, bytes, time.Now().Unix())
}

// TimeUtils provides time-related utilities
type TimeUtils struct{}

// NewTimeUtils creates new time utilities
func NewTimeUtils() *TimeUtils {
	return &TimeUtils{}
}

// FormatDuration formats duration in human-readable format
func (tu *TimeUtils) FormatDuration(duration time.Duration) string {
	if duration < time.Microsecond {
		return fmt.Sprintf("%dns", duration.Nanoseconds())
	}
	if duration < time.Millisecond {
		return fmt.Sprintf("%.1fμs", float64(duration.Nanoseconds())/1000.0)
	}
	if duration < time.Second {
		return fmt.Sprintf("%.1fms", float64(duration.Nanoseconds())/1000000.0)
	}
	if duration < time.Minute {
		return fmt.Sprintf("%.1fs", duration.Seconds())
	}
	if duration < time.Hour {
		return fmt.Sprintf("%.1fm", duration.Minutes())
	}
	return fmt.Sprintf("%.1fh", duration.Hours())
}

// IsWithinTimeRange checks if time is within range
func (tu *TimeUtils) IsWithinTimeRange(t, start, end time.Time) bool {
	return (t.Equal(start) || t.After(start)) && (t.Equal(end) || t.Before(end))
}

// JSONUtils provides JSON utilities
type JSONUtils struct{}

// NewJSONUtils creates new JSON utilities
func NewJSONUtils() *JSONUtils {
	return &JSONUtils{}
}

// PrettyPrint formats JSON with indentation
func (ju *JSONUtils) PrettyPrint(data interface{}) (string, error) {
	bytes, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		return "", err
	}
	return string(bytes), nil
}

// DeepCopy creates a deep copy of a JSON-serializable object
func (ju *JSONUtils) DeepCopy(src, dst interface{}) error {
	bytes, err := json.Marshal(src)
	if err != nil {
		return err
	}
	return json.Unmarshal(bytes, dst)
}

// ValidationUtils provides validation utilities
type ValidationUtils struct{}

// NewValidationUtils creates new validation utilities
func NewValidationUtils() *ValidationUtils {
	return &ValidationUtils{}
}

// IsValidEmail validates email address
func (vu *ValidationUtils) IsValidEmail(email string) bool {
	emailRegex := regexp.MustCompile(`^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$`)
	return emailRegex.MatchString(email)
}

// IsValidURL validates URL
func (vu *ValidationUtils) IsValidURL(url string) bool {
	urlRegex := regexp.MustCompile(`^https?://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,}(/.*)?$`)
	return urlRegex.MatchString(url)
}

// IsValidPath validates file path
func (vu *ValidationUtils) IsValidPath(path string) bool {
	if path == "" {
		return false
	}
	// Check for invalid characters
	invalidChars := []string{"<", ">", ":", "\"", "|", "?", "*"}
	for _, char := range invalidChars {
		if strings.Contains(path, char) {
			return false
		}
	}
	return true
}

// Context utilities

// CloneContextNode creates a deep copy of a context node
func CloneContextNode(node *slurpContext.ContextNode) *slurpContext.ContextNode {
	if node == nil {
		return nil
	}

	clone := &slurpContext.ContextNode{
		Path:                  node.Path,
		Summary:               node.Summary,
		Purpose:               node.Purpose,
		Technologies:          make([]string, len(node.Technologies)),
		Tags:                  make([]string, len(node.Tags)),
		Insights:              make([]string, len(node.Insights)),
		CreatedAt:             node.CreatedAt,
		UpdatedAt:             node.UpdatedAt,
		ContextSpecificity:    node.ContextSpecificity,
		RAGConfidence:         node.RAGConfidence,
		ProcessedForRole:      node.ProcessedForRole,
	}

	copy(clone.Technologies, node.Technologies)
	copy(clone.Tags, node.Tags)
	copy(clone.Insights, node.Insights)

	if node.RoleSpecificInsights != nil {
		clone.RoleSpecificInsights = make([]*RoleSpecificInsight, len(node.RoleSpecificInsights))
		copy(clone.RoleSpecificInsights, node.RoleSpecificInsights)
	}

	if node.Metadata != nil {
		clone.Metadata = make(map[string]interface{})
		for k, v := range node.Metadata {
			clone.Metadata[k] = v
		}
	}

	return clone
}

// MergeContextNodes merges multiple context nodes into one
func MergeContextNodes(nodes ...*slurpContext.ContextNode) *slurpContext.ContextNode {
	if len(nodes) == 0 {
		return nil
	}
	if len(nodes) == 1 {
		return CloneContextNode(nodes[0])
	}

	merged := CloneContextNode(nodes[0])
	
	for i := 1; i < len(nodes); i++ {
		node := nodes[i]
		if node == nil {
			continue
		}

		// Merge technologies
		merged.Technologies = mergeStringSlices(merged.Technologies, node.Technologies)
		
		// Merge tags
		merged.Tags = mergeStringSlices(merged.Tags, node.Tags)
		
		// Merge insights
		merged.Insights = mergeStringSlices(merged.Insights, node.Insights)
		
		// Use most recent timestamps
		if node.CreatedAt.Before(merged.CreatedAt) {
			merged.CreatedAt = node.CreatedAt
		}
		if node.UpdatedAt.After(merged.UpdatedAt) {
			merged.UpdatedAt = node.UpdatedAt
		}
		
		// Average context specificity
		merged.ContextSpecificity = (merged.ContextSpecificity + node.ContextSpecificity) / 2
		
		// Average RAG confidence
		merged.RAGConfidence = (merged.RAGConfidence + node.RAGConfidence) / 2
		
		// Merge metadata
		if node.Metadata != nil {
			if merged.Metadata == nil {
				merged.Metadata = make(map[string]interface{})
			}
			for k, v := range node.Metadata {
				merged.Metadata[k] = v
			}
		}
	}

	return merged
}

// Helper functions

func removeDuplicates(slice []string) []string {
	seen := make(map[string]bool)
	result := []string{}
	for _, item := range slice {
		if !seen[item] {
			seen[item] = true
			result = append(result, item)
		}
	}
	return result
}

func mergeStringSlices(slice1, slice2 []string) []string {
	merged := make([]string, len(slice1))
	copy(merged, slice1)
	
	for _, item := range slice2 {
		found := false
		for _, existing := range merged {
			if existing == item {
				found = true
				break
			}
		}
		if !found {
			merged = append(merged, item)
		}
	}
	
	return merged
}

// MathUtils provides mathematical utilities
type MathUtils struct{}

// NewMathUtils creates new math utilities
func NewMathUtils() *MathUtils {
	return &MathUtils{}
}

// Clamp clamps value between min and max
func (mu *MathUtils) Clamp(value, min, max float64) float64 {
	return math.Max(min, math.Min(max, value))
}

// Lerp performs linear interpolation between a and b
func (mu *MathUtils) Lerp(a, b, t float64) float64 {
	return a + t*(b-a)
}

// RoundToDecimalPlaces rounds to specified decimal places
func (mu *MathUtils) RoundToDecimalPlaces(value float64, places int) float64 {
	multiplier := math.Pow(10, float64(places))
	return math.Round(value*multiplier) / multiplier
}

// SafeDivide performs division with zero-check
func (mu *MathUtils) SafeDivide(numerator, denominator float64) float64 {
	if math.Abs(denominator) < 1e-10 {
		return 0.0
	}
	return numerator / denominator
}

// InRange checks if value is in range (inclusive)
func (mu *MathUtils) InRange(value, min, max float64) bool {
	return value >= min && value <= max
}

// ParseUtils provides parsing utilities
type ParseUtils struct{}

// NewParseUtils creates new parse utilities
func NewParseUtils() *ParseUtils {
	return &ParseUtils{}
}

// ParseFloat safely parses float with default
func (pu *ParseUtils) ParseFloat(s string, defaultValue float64) float64 {
	if value, err := strconv.ParseFloat(s, 64); err == nil {
		return value
	}
	return defaultValue
}

// ParseInt safely parses int with default
func (pu *ParseUtils) ParseInt(s string, defaultValue int) int {
	if value, err := strconv.Atoi(s); err == nil {
		return value
	}
	return defaultValue
}

// ParseBool safely parses bool with default
func (pu *ParseUtils) ParseBool(s string, defaultValue bool) bool {
	if value, err := strconv.ParseBool(s); err == nil {
		return value
	}
	return defaultValue
}

// ParseDuration safely parses duration with default
func (pu *ParseUtils) ParseDuration(s string, defaultValue time.Duration) time.Duration {
	if value, err := time.ParseDuration(s); err == nil {
		return value
	}
	return defaultValue
}

// ParseTime safely parses time with default
func (pu *ParseUtils) ParseTime(s, layout string, defaultValue time.Time) time.Time {
	if value, err := time.Parse(layout, s); err == nil {
		return value
	}
	return defaultValue
}

// ConversionUtils provides type conversion utilities
type ConversionUtils struct{}

// NewConversionUtils creates new conversion utilities
func NewConversionUtils() *ConversionUtils {
	return &ConversionUtils{}
}

// ToString converts various types to string
func (cu *ConversionUtils) ToString(value interface{}) string {
	switch v := value.(type) {
	case string:
		return v
	case int, int8, int16, int32, int64:
		return fmt.Sprintf("%d", v)
	case uint, uint8, uint16, uint32, uint64:
		return fmt.Sprintf("%d", v)
	case float32, float64:
		return fmt.Sprintf("%g", v)
	case bool:
		return fmt.Sprintf("%t", v)
	case time.Time:
		return v.Format(time.RFC3339)
	case time.Duration:
		return v.String()
	default:
		return fmt.Sprintf("%v", v)
	}
}

// ToStringSlice converts interface{} to []string
func (cu *ConversionUtils) ToStringSlice(value interface{}) []string {
	switch v := value.(type) {
	case []string:
		return v
	case []interface{}:
		result := make([]string, len(v))
		for i, item := range v {
			result[i] = cu.ToString(item)
		}
		return result
	case string:
		return []string{v}
	default:
		return []string{cu.ToString(v)}
	}
}

// ByteUtils provides byte manipulation utilities
type ByteUtils struct{}

// NewByteUtils creates new byte utilities
func NewByteUtils() *ByteUtils {
	return &ByteUtils{}
}

// FormatBytes formats bytes in human-readable format
func (bu *ByteUtils) FormatBytes(bytes int64) string {
	const unit = 1024
	if bytes < unit {
		return fmt.Sprintf("%d B", bytes)
	}
	div, exp := int64(unit), 0
	for n := bytes / unit; n >= unit; n /= unit {
		div *= unit
		exp++
	}
	return fmt.Sprintf("%.1f %cB", float64(bytes)/float64(div), "KMGTPE"[exp])
}

// ReadFileWithLimit reads file with size limit
func (bu *ByteUtils) ReadFileWithLimit(filename string, maxSize int64) ([]byte, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	stat, err := file.Stat()
	if err != nil {
		return nil, err
	}

	if stat.Size() > maxSize {
		return nil, fmt.Errorf("file too large: %d bytes (limit: %d)", stat.Size(), maxSize)
	}

	return io.ReadAll(file)
}