package intelligence

import (
	"context"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	"time"

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

// DefaultDirectoryAnalyzer provides comprehensive directory structure analysis
type DefaultDirectoryAnalyzer struct {
	config               *EngineConfig
	organizationDetector *OrganizationDetector
	conventionAnalyzer   *ConventionAnalyzer
	relationshipAnalyzer *RelationshipAnalyzer
}

// OrganizationDetector detects organizational patterns in directory structures
type OrganizationDetector struct {
	commonPatterns map[string]*OrganizationalPattern
}

// ConventionAnalyzer analyzes naming and organizational conventions
type ConventionAnalyzer struct {
	namingRegexes map[string]*regexp.Regexp
	standards     map[string]*CodingStandard
}

// RelationshipAnalyzer analyzes relationships between directories and files
type RelationshipAnalyzer struct {
	dependencyDetectors map[string]*DependencyDetector
}

// DependencyDetector detects dependencies for specific languages/frameworks
type DependencyDetector struct {
	importPatterns []*regexp.Regexp
	configFiles    []string
}

// CodingStandard represents a coding standard or convention
type CodingStandard struct {
	Name        string
	Rules       []*ConventionRule
	FileTypes   []string
	Description string
}

// ConventionRule represents a single convention rule
type ConventionRule struct {
	Type        string // naming, structure, organization
	Pattern     string
	Description string
	Severity    string // error, warning, info
}

// NewDefaultDirectoryAnalyzer creates a new directory analyzer
func NewDefaultDirectoryAnalyzer(config *EngineConfig) *DefaultDirectoryAnalyzer {
	return &DefaultDirectoryAnalyzer{
		config:               config,
		organizationDetector: NewOrganizationDetector(),
		conventionAnalyzer:   NewConventionAnalyzer(),
		relationshipAnalyzer: NewRelationshipAnalyzer(),
	}
}

// NewOrganizationDetector creates an organization pattern detector
func NewOrganizationDetector() *OrganizationDetector {
	detector := &OrganizationDetector{
		commonPatterns: make(map[string]*OrganizationalPattern),
	}

	// Define common organizational patterns
	patterns := []*OrganizationalPattern{
		{
			Pattern: Pattern{
				ID:          "mvc",
				Name:        "Model-View-Controller (MVC)",
				Type:        "architectural",
				Description: "Separates concerns into models, views, and controllers",
				Confidence:  0.9,
				Examples:    []string{"models/", "views/", "controllers/"},
				Benefits:    []string{"Clear separation of concerns", "Maintainable code structure"},
			},
			Structure:   "layered",
			Depth:       2,
			FanOut:      3,
			Modularity:  0.8,
			Scalability: "good",
		},
		{
			Pattern: Pattern{
				ID:          "clean_architecture",
				Name:        "Clean Architecture",
				Type:        "architectural",
				Description: "Dependency inversion with clear boundaries",
				Confidence:  0.85,
				Examples:    []string{"entities/", "usecases/", "adapters/", "frameworks/"},
				Benefits:    []string{"Testable", "Independent of frameworks", "Independent of UI"},
			},
			Structure:   "onion",
			Depth:       3,
			FanOut:      4,
			Modularity:  0.95,
			Scalability: "excellent",
		},
		{
			Pattern: Pattern{
				ID:          "domain_driven",
				Name:        "Domain-Driven Design (DDD)",
				Type:        "architectural",
				Description: "Organized around business domains",
				Confidence:  0.8,
				Examples:    []string{"domain/", "application/", "infrastructure/"},
				Benefits:    []string{"Business-focused", "Clear domain boundaries"},
			},
			Structure:   "domain-based",
			Depth:       3,
			FanOut:      5,
			Modularity:  0.9,
			Scalability: "excellent",
		},
		{
			Pattern: Pattern{
				ID:          "feature_based",
				Name:        "Feature-Based Organization",
				Type:        "organizational",
				Description: "Organized by features rather than technical layers",
				Confidence:  0.75,
				Examples:    []string{"user-management/", "payment/", "notifications/"},
				Benefits:    []string{"Feature-focused development", "Team autonomy"},
			},
			Structure:   "feature-vertical",
			Depth:       2,
			FanOut:      6,
			Modularity:  0.85,
			Scalability: "good",
		},
		{
			Pattern: Pattern{
				ID:          "microservices",
				Name:        "Microservices Pattern",
				Type:        "architectural",
				Description: "Independent services with their own data",
				Confidence:  0.8,
				Examples:    []string{"services/", "api-gateway/", "shared/"},
				Benefits:    []string{"Independent deployment", "Technology diversity", "Fault isolation"},
			},
			Structure:   "service-oriented",
			Depth:       2,
			FanOut:      8,
			Modularity:  0.95,
			Scalability: "excellent",
		},
	}

	for _, pattern := range patterns {
		detector.commonPatterns[pattern.ID] = pattern
	}

	return detector
}

// NewConventionAnalyzer creates a convention analyzer
func NewConventionAnalyzer() *ConventionAnalyzer {
	analyzer := &ConventionAnalyzer{
		namingRegexes: make(map[string]*regexp.Regexp),
		standards:     make(map[string]*CodingStandard),
	}

	// Define naming convention regexes
	analyzer.namingRegexes["camelCase"] = regexp.MustCompile(`^[a-z][a-zA-Z0-9]*$`)
	analyzer.namingRegexes["PascalCase"] = regexp.MustCompile(`^[A-Z][a-zA-Z0-9]*$`)
	analyzer.namingRegexes["snake_case"] = regexp.MustCompile(`^[a-z][a-z0-9_]*$`)
	analyzer.namingRegexes["kebab-case"] = regexp.MustCompile(`^[a-z][a-z0-9-]*$`)
	analyzer.namingRegexes["SCREAMING_SNAKE"] = regexp.MustCompile(`^[A-Z][A-Z0-9_]*$`)

	// Define coding standards
	goStandard := &CodingStandard{
		Name:        "Go Standard",
		FileTypes:   []string{".go"},
		Description: "Go language conventions",
		Rules: []*ConventionRule{
			{Type: "naming", Pattern: "^[A-Z][a-zA-Z0-9]*$", Description: "Exported functions/types use PascalCase"},
			{Type: "naming", Pattern: "^[a-z][a-zA-Z0-9]*$", Description: "Private functions/variables use camelCase"},
			{Type: "structure", Pattern: "package main", Description: "Executable packages use 'main'"},
		},
	}

	pythonStandard := &CodingStandard{
		Name:        "PEP 8",
		FileTypes:   []string{".py"},
		Description: "Python enhancement proposal 8 style guide",
		Rules: []*ConventionRule{
			{Type: "naming", Pattern: "^[a-z][a-z0-9_]*$", Description: "Functions and variables use snake_case"},
			{Type: "naming", Pattern: "^[A-Z][a-zA-Z0-9]*$", Description: "Classes use PascalCase"},
			{Type: "naming", Pattern: "^[A-Z][A-Z0-9_]*$", Description: "Constants use SCREAMING_SNAKE_CASE"},
		},
	}

	jsStandard := &CodingStandard{
		Name:        "JavaScript Standard",
		FileTypes:   []string{".js", ".jsx", ".ts", ".tsx"},
		Description: "JavaScript/TypeScript conventions",
		Rules: []*ConventionRule{
			{Type: "naming", Pattern: "^[a-z][a-zA-Z0-9]*$", Description: "Variables and functions use camelCase"},
			{Type: "naming", Pattern: "^[A-Z][a-zA-Z0-9]*$", Description: "Classes and components use PascalCase"},
			{Type: "naming", Pattern: "^[A-Z][A-Z0-9_]*$", Description: "Constants use SCREAMING_SNAKE_CASE"},
		},
	}

	analyzer.standards["go"] = goStandard
	analyzer.standards["python"] = pythonStandard
	analyzer.standards["javascript"] = jsStandard
	analyzer.standards["typescript"] = jsStandard

	return analyzer
}

// NewRelationshipAnalyzer creates a relationship analyzer
func NewRelationshipAnalyzer() *RelationshipAnalyzer {
	analyzer := &RelationshipAnalyzer{
		dependencyDetectors: make(map[string]*DependencyDetector),
	}

	// Go dependency detector
	goDetector := &DependencyDetector{
		importPatterns: []*regexp.Regexp{
			regexp.MustCompile(`import\s+"([^"]+)"`),
			regexp.MustCompile(`import\s+\w+\s+"([^"]+)"`),
		},
		configFiles: []string{"go.mod", "go.sum"},
	}

	// Python dependency detector
	pythonDetector := &DependencyDetector{
		importPatterns: []*regexp.Regexp{
			regexp.MustCompile(`from\s+([^\s]+)\s+import`),
			regexp.MustCompile(`import\s+([^\s]+)`),
		},
		configFiles: []string{"requirements.txt", "Pipfile", "pyproject.toml", "setup.py"},
	}

	// JavaScript dependency detector
	jsDetector := &DependencyDetector{
		importPatterns: []*regexp.Regexp{
			regexp.MustCompile(`import\s+.*from\s+['"]([^'"]+)['"]`),
			regexp.MustCompile(`require\s*\(\s*['"]([^'"]+)['"]`),
		},
		configFiles: []string{"package.json", "yarn.lock", "package-lock.json"},
	}

	analyzer.dependencyDetectors["go"] = goDetector
	analyzer.dependencyDetectors["python"] = pythonDetector
	analyzer.dependencyDetectors["javascript"] = jsDetector
	analyzer.dependencyDetectors["typescript"] = jsDetector

	return analyzer
}

// AnalyzeStructure analyzes directory organization patterns
func (da *DefaultDirectoryAnalyzer) AnalyzeStructure(ctx context.Context, dirPath string) (*DirectoryStructure, error) {
	structure := &DirectoryStructure{
		Path:           dirPath,
		FileTypes:      make(map[string]int),
		Languages:      make(map[string]int),
		Dependencies:   []string{},
		AnalyzedAt:     time.Now(),
	}

	// Walk the directory tree
	err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if info.IsDir() {
			structure.DirectoryCount++
		} else {
			structure.FileCount++
			structure.TotalSize += info.Size()

			// Track file types
			ext := strings.ToLower(filepath.Ext(path))
			if ext != "" {
				structure.FileTypes[ext]++

				// Map extensions to languages
				if lang := da.mapExtensionToLanguage(ext); lang != "" {
					structure.Languages[lang]++
				}
			}
		}

		return nil
	})

	if err != nil {
		return nil, fmt.Errorf("failed to walk directory: %w", err)
	}

	// Analyze organization patterns
	orgInfo, err := da.analyzeOrganization(dirPath)
	if err != nil {
		orgInfo = &OrganizationInfo{
			Pattern:     "unknown",
			Consistency: 0.5,
		}
	}
	structure.Organization = orgInfo

	// Analyze conventions
	convInfo, err := da.analyzeConventions(ctx, dirPath)
	if err != nil {
		convInfo = &ConventionInfo{
			NamingStyle: "mixed",
			Consistency: 0.5,
		}
	}
	structure.Conventions = convInfo

	// Determine purpose and architecture
	structure.Purpose = da.determinePurpose(structure)
	structure.Architecture = da.determineArchitecture(structure, orgInfo)

	return structure, nil
}

// DetectConventions identifies naming and organizational conventions
func (da *DefaultDirectoryAnalyzer) DetectConventions(ctx context.Context, dirPath string) (*ConventionAnalysis, error) {
	analysis := &ConventionAnalysis{
		NamingPatterns:         []*NamingPattern{},
		OrganizationalPatterns: []*OrganizationalPattern{},
		Consistency:            0.0,
		Violations:             []*Violation{},
		Recommendations:        []*Recommendation{},
		AppliedStandards:       []string{},
		AnalyzedAt:            time.Now(),
	}

	// Collect all files and directories
	files, dirs, err := da.collectFilesAndDirs(dirPath)
	if err != nil {
		return nil, fmt.Errorf("failed to collect files and directories: %w", err)
	}

	// Detect naming patterns
	namingPatterns := da.detectNamingPatterns(files, dirs)
	analysis.NamingPatterns = namingPatterns

	// Detect organizational patterns
	orgPatterns := da.detectOrganizationalPatterns(ctx, dirPath, dirs)
	analysis.OrganizationalPatterns = orgPatterns

	// Calculate consistency
	analysis.Consistency = da.calculateConventionConsistency(files, dirs, namingPatterns)

	// Find violations
	violations := da.findConventionViolations(files, dirs, namingPatterns)
	analysis.Violations = violations

	// Generate recommendations
	recommendations := da.generateConventionRecommendations(analysis)
	analysis.Recommendations = recommendations

	return analysis, nil
}

// IdentifyPurpose determines the primary purpose of a directory
func (da *DefaultDirectoryAnalyzer) IdentifyPurpose(ctx context.Context, structure *DirectoryStructure) (string, float64, error) {
	purpose := "General purpose directory"
	confidence := 0.5

	dirName := strings.ToLower(filepath.Base(structure.Path))

	// Common directory purposes
	purposes := map[string]struct {
		purpose    string
		confidence float64
	}{
		"src":           {"Source code repository", 0.9},
		"source":        {"Source code repository", 0.9},
		"lib":           {"Library code", 0.8},
		"libs":          {"Library code", 0.8},
		"vendor":        {"Third-party dependencies", 0.9},
		"node_modules":  {"Node.js dependencies", 0.95},
		"build":         {"Build artifacts", 0.9},
		"dist":          {"Distribution files", 0.9},
		"bin":           {"Binary executables", 0.9},
		"test":          {"Test code", 0.9},
		"tests":         {"Test code", 0.9},
		"docs":          {"Documentation", 0.9},
		"doc":           {"Documentation", 0.9},
		"config":        {"Configuration files", 0.9},
		"configs":       {"Configuration files", 0.9},
		"scripts":       {"Utility scripts", 0.8},
		"tools":         {"Development tools", 0.8},
		"assets":        {"Static assets", 0.8},
		"public":        {"Public web assets", 0.8},
		"static":        {"Static files", 0.8},
		"templates":     {"Template files", 0.8},
		"migrations":    {"Database migrations", 0.9},
		"models":        {"Data models", 0.8},
		"views":         {"View layer", 0.8},
		"controllers":   {"Controller layer", 0.8},
		"services":      {"Service layer", 0.8},
		"components":    {"Reusable components", 0.8},
		"modules":       {"Modular components", 0.8},
		"packages":      {"Package organization", 0.7},
		"internal":      {"Internal implementation", 0.8},
		"cmd":           {"Command-line applications", 0.9},
		"api":           {"API implementation", 0.8},
		"pkg":           {"Go package directory", 0.8},
	}

	if p, exists := purposes[dirName]; exists {
		purpose = p.purpose
		confidence = p.confidence
	} else {
		// Analyze content to determine purpose
		if structure.Languages != nil {
			totalFiles := 0
			for _, count := range structure.Languages {
				totalFiles += count
			}

			if totalFiles > 0 {
				// Determine purpose based on file types
				if structure.Languages["javascript"] > totalFiles/2 || structure.Languages["typescript"] > totalFiles/2 {
					purpose = "Frontend application code"
					confidence = 0.7
				} else if structure.Languages["go"] > totalFiles/2 {
					purpose = "Go application or service"
					confidence = 0.7
				} else if structure.Languages["python"] > totalFiles/2 {
					purpose = "Python application or library"
					confidence = 0.7
				} else if structure.FileTypes[".html"] > 0 || structure.FileTypes[".css"] > 0 {
					purpose = "Web frontend resources"
					confidence = 0.7
				} else if structure.FileTypes[".sql"] > 0 {
					purpose = "Database schema and queries"
					confidence = 0.8
				}
			}
		}
	}

	return purpose, confidence, nil
}

// AnalyzeRelationships analyzes relationships between subdirectories
func (da *DefaultDirectoryAnalyzer) AnalyzeRelationships(ctx context.Context, dirPath string) (*RelationshipAnalysis, error) {
	analysis := &RelationshipAnalysis{
		Dependencies:      []*DirectoryDependency{},
		Relationships:     []*DirectoryRelation{},
		CouplingMetrics:   &CouplingMetrics{},
		ModularityScore:   0.0,
		ArchitecturalStyle: "unknown",
		AnalyzedAt:        time.Now(),
	}

	// Find subdirectories
	subdirs, err := da.findSubdirectories(dirPath)
	if err != nil {
		return nil, fmt.Errorf("failed to find subdirectories: %w", err)
	}

	// Analyze dependencies between directories
	dependencies, err := da.analyzeDependencies(ctx, subdirs)
	if err != nil {
		return nil, fmt.Errorf("failed to analyze dependencies: %w", err)
	}
	analysis.Dependencies = dependencies

	// Analyze relationships
	relationships := da.analyzeDirectoryRelationships(subdirs, dependencies)
	analysis.Relationships = relationships

	// Calculate coupling metrics
	couplingMetrics := da.calculateCouplingMetrics(subdirs, dependencies)
	analysis.CouplingMetrics = couplingMetrics

	// Calculate modularity score
	analysis.ModularityScore = da.calculateModularityScore(relationships, couplingMetrics)

	// Determine architectural style
	analysis.ArchitecturalStyle = da.determineArchitecturalStyle(subdirs, dependencies)

	return analysis, nil
}

// GenerateHierarchy generates context hierarchy for directory tree
func (da *DefaultDirectoryAnalyzer) GenerateHierarchy(ctx context.Context, rootPath string, maxDepth int) ([]*slurpContext.ContextNode, error) {
	nodes := []*slurpContext.ContextNode{}

	err := da.walkDirectoryHierarchy(rootPath, 0, maxDepth, func(path string, depth int) error {
		// Analyze this directory
		structure, err := da.AnalyzeStructure(ctx, path)
		if err != nil {
			return err
		}

		// Generate UCXL address
		ucxlAddr, err := da.generateUCXLAddress(path)
		if err != nil {
			return fmt.Errorf("failed to generate UCXL address: %w", err)
		}

		// Determine purpose
		purpose, purposeConf, err := da.IdentifyPurpose(ctx, structure)
		if err != nil {
			purpose = "Directory"
			purposeConf = 0.5
		}

		// Generate summary
		summary := da.generateDirectorySummary(structure)

		// Generate tags
		tags := da.generateDirectoryTags(structure, path)

		// Generate technologies list
		technologies := da.extractTechnologiesFromStructure(structure)

		// Create context node
		contextNode := &slurpContext.ContextNode{
			Path:               path,
			UCXLAddress:        *ucxlAddr,
			Summary:            summary,
			Purpose:            purpose,
			Technologies:       technologies,
			Tags:               tags,
			Insights:           []string{},
			OverridesParent:    false,
			ContextSpecificity: da.calculateDirectorySpecificity(structure),
			AppliesToChildren:  depth < maxDepth-1,
			GeneratedAt:        time.Now(),
			RAGConfidence:      purposeConf,
			EncryptedFor:       []string{"*"}, // Default access
			AccessLevel:        slurpContext.AccessLow,
			Metadata:           make(map[string]interface{}),
		}

		// Add structure metadata
		contextNode.Metadata["structure"] = structure
		contextNode.Metadata["depth"] = depth

		nodes = append(nodes, contextNode)
		return nil
	})

	if err != nil {
		return nil, fmt.Errorf("failed to walk directory hierarchy: %w", err)
	}

	return nodes, nil
}

// Helper methods

func (da *DefaultDirectoryAnalyzer) mapExtensionToLanguage(ext string) string {
	langMap := map[string]string{
		".go":   "go",
		".py":   "python",
		".js":   "javascript",
		".jsx":  "javascript",
		".ts":   "typescript",
		".tsx":  "typescript",
		".java": "java",
		".c":    "c",
		".cpp":  "cpp",
		".cs":   "csharp",
		".php":  "php",
		".rb":   "ruby",
		".rs":   "rust",
		".kt":   "kotlin",
		".swift": "swift",
	}

	return langMap[ext]
}

func (da *DefaultDirectoryAnalyzer) analyzeOrganization(dirPath string) (*OrganizationInfo, error) {
	// Get immediate subdirectories
	files, err := ioutil.ReadDir(dirPath)
	if err != nil {
		return nil, fmt.Errorf("failed to read directory: %w", err)
	}

	subdirs := []string{}
	for _, file := range files {
		if file.IsDir() {
			subdirs = append(subdirs, file.Name())
		}
	}

	// Detect organizational pattern
	pattern := da.detectOrganizationalPattern(subdirs)
	
	// Calculate metrics
	fanOut := len(subdirs)
	consistency := da.calculateOrganizationalConsistency(subdirs)

	return &OrganizationInfo{
		Pattern:     pattern,
		Consistency: consistency,
		Depth:       da.calculateMaxDepth(dirPath),
		FanOut:      fanOut,
		Modularity:  da.calculateModularity(subdirs),
		Cohesion:    0.7, // Default cohesion score
		Coupling:    0.3, // Default coupling score
		Metadata:    make(map[string]interface{}),
	}, nil
}

func (da *DefaultDirectoryAnalyzer) detectOrganizationalPattern(subdirs []string) string {
	// Check for common patterns
	subdirSet := make(map[string]bool)
	for _, dir := range subdirs {
		subdirSet[strings.ToLower(dir)] = true
	}

	// MVC pattern
	if subdirSet["models"] && subdirSet["views"] && subdirSet["controllers"] {
		return "MVC"
	}

	// Clean Architecture
	if subdirSet["entities"] && subdirSet["usecases"] && subdirSet["adapters"] {
		return "Clean Architecture"
	}

	// Domain-Driven Design
	if subdirSet["domain"] && subdirSet["application"] && subdirSet["infrastructure"] {
		return "Domain-Driven Design"
	}

	// Layered architecture
	if subdirSet["presentation"] && subdirSet["business"] && subdirSet["data"] {
		return "Layered Architecture"
	}

	// Feature-based
	if len(subdirs) > 3 && da.allAreDomainLike(subdirs) {
		return "Feature-Based"
	}

	// Package by layer (technical)
	technicalDirs := []string{"api", "service", "repository", "model", "dto", "util"}
	technicalCount := 0
	for _, tech := range technicalDirs {
		if subdirSet[tech] {
			technicalCount++
		}
	}
	if technicalCount >= 3 {
		return "Package by Layer"
	}

	return "Custom"
}

func (da *DefaultDirectoryAnalyzer) allAreDomainLike(subdirs []string) bool {
	// Simple heuristic: if directories don't look like technical layers,
	// they might be domain/feature based
	technicalTerms := []string{"api", "service", "repository", "model", "dto", "util", "config", "test", "lib"}
	
	for _, subdir := range subdirs {
		lowerDir := strings.ToLower(subdir)
		for _, term := range technicalTerms {
			if strings.Contains(lowerDir, term) {
				return false
			}
		}
	}
	return true
}

func (da *DefaultDirectoryAnalyzer) calculateOrganizationalConsistency(subdirs []string) float64 {
	if len(subdirs) < 2 {
		return 1.0
	}

	// Simple consistency check: naming convention consistency
	camelCaseCount := 0
	kebabCaseCount := 0
	snakeCaseCount := 0

	for _, dir := range subdirs {
		if da.isCamelCase(dir) {
			camelCaseCount++
		} else if da.isKebabCase(dir) {
			kebabCaseCount++
		} else if da.isSnakeCase(dir) {
			snakeCaseCount++
		}
	}

	total := len(subdirs)
	maxConsistent := camelCaseCount
	if kebabCaseCount > maxConsistent {
		maxConsistent = kebabCaseCount
	}
	if snakeCaseCount > maxConsistent {
		maxConsistent = snakeCaseCount
	}

	return float64(maxConsistent) / float64(total)
}

func (da *DefaultDirectoryAnalyzer) isCamelCase(s string) bool {
	matched, _ := regexp.MatchString(`^[a-z][a-zA-Z0-9]*$`, s)
	return matched
}

func (da *DefaultDirectoryAnalyzer) isKebabCase(s string) bool {
	matched, _ := regexp.MatchString(`^[a-z][a-z0-9-]*$`, s)
	return matched
}

func (da *DefaultDirectoryAnalyzer) isSnakeCase(s string) bool {
	matched, _ := regexp.MatchString(`^[a-z][a-z0-9_]*$`, s)
	return matched
}

func (da *DefaultDirectoryAnalyzer) calculateMaxDepth(dirPath string) int {
	maxDepth := 0
	
	filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return nil
		}
		if info.IsDir() {
			relativePath, _ := filepath.Rel(dirPath, path)
			depth := strings.Count(relativePath, string(os.PathSeparator))
			if depth > maxDepth {
				maxDepth = depth
			}
		}
		return nil
	})
	
	return maxDepth
}

func (da *DefaultDirectoryAnalyzer) calculateModularity(subdirs []string) float64 {
	// Simple modularity heuristic based on directory count and naming
	if len(subdirs) == 0 {
		return 0.0
	}
	
	// More subdirectories with clear separation indicates higher modularity
	if len(subdirs) > 5 {
		return 0.8
	} else if len(subdirs) > 2 {
		return 0.6
	} else {
		return 0.4
	}
}

func (da *DefaultDirectoryAnalyzer) analyzeConventions(ctx context.Context, dirPath string) (*ConventionInfo, error) {
	files, err := ioutil.ReadDir(dirPath)
	if err != nil {
		return nil, fmt.Errorf("failed to read directory: %w", err)
	}

	fileNames := []string{}
	dirNames := []string{}

	for _, file := range files {
		if file.IsDir() {
			dirNames = append(dirNames, file.Name())
		} else {
			fileNames = append(fileNames, file.Name())
		}
	}

	// Detect dominant naming style
	namingStyle := da.detectDominantNamingStyle(append(fileNames, dirNames...))
	
	// Calculate consistency
	consistency := da.calculateNamingConsistency(append(fileNames, dirNames...), namingStyle)

	return &ConventionInfo{
		NamingStyle:     namingStyle,
		FileNaming:      da.detectFileNamingPattern(fileNames),
		DirectoryNaming: da.detectDirectoryNamingPattern(dirNames),
		Consistency:     consistency,
		Violations:      []*Violation{},
		Standards:       []string{},
	}, nil
}

func (da *DefaultDirectoryAnalyzer) detectDominantNamingStyle(names []string) string {
	styles := map[string]int{
		"camelCase":  0,
		"kebab-case": 0,
		"snake_case": 0,
		"PascalCase": 0,
	}

	for _, name := range names {
		if da.isCamelCase(name) {
			styles["camelCase"]++
		} else if da.isKebabCase(name) {
			styles["kebab-case"]++
		} else if da.isSnakeCase(name) {
			styles["snake_case"]++
		} else if da.isPascalCase(name) {
			styles["PascalCase"]++
		}
	}

	maxCount := 0
	dominantStyle := "mixed"
	for style, count := range styles {
		if count > maxCount {
			maxCount = count
			dominantStyle = style
		}
	}

	return dominantStyle
}

func (da *DefaultDirectoryAnalyzer) isPascalCase(s string) bool {
	matched, _ := regexp.MatchString(`^[A-Z][a-zA-Z0-9]*$`, s)
	return matched
}

func (da *DefaultDirectoryAnalyzer) detectFileNamingPattern(fileNames []string) string {
	// Analyze file naming patterns
	if len(fileNames) == 0 {
		return "none"
	}

	return da.detectDominantNamingStyle(fileNames)
}

func (da *DefaultDirectoryAnalyzer) detectDirectoryNamingPattern(dirNames []string) string {
	if len(dirNames) == 0 {
		return "none"
	}

	return da.detectDominantNamingStyle(dirNames)
}

func (da *DefaultDirectoryAnalyzer) calculateNamingConsistency(names []string, expectedStyle string) float64 {
	if len(names) == 0 {
		return 1.0
	}

	consistentCount := 0
	for _, name := range names {
		if da.matchesNamingStyle(name, expectedStyle) {
			consistentCount++
		}
	}

	return float64(consistentCount) / float64(len(names))
}

func (da *DefaultDirectoryAnalyzer) matchesNamingStyle(name, style string) bool {
	switch style {
	case "camelCase":
		return da.isCamelCase(name)
	case "kebab-case":
		return da.isKebabCase(name)
	case "snake_case":
		return da.isSnakeCase(name)
	case "PascalCase":
		return da.isPascalCase(name)
	default:
		return true // Mixed style always matches
	}
}

func (da *DefaultDirectoryAnalyzer) determinePurpose(structure *DirectoryStructure) string {
	// Determine purpose based on directory structure analysis
	if structure.Languages["javascript"] > 0 || structure.Languages["typescript"] > 0 {
		if structure.FileTypes[".html"] > 0 || structure.FileTypes[".css"] > 0 {
			return "Frontend web application"
		} else {
			return "JavaScript/TypeScript application"
		}
	}

	if structure.Languages["go"] > 0 {
		return "Go application or service"
	}

	if structure.Languages["python"] > 0 {
		return "Python application or library"
	}

	if structure.Languages["java"] > 0 {
		return "Java application"
	}

	if structure.FileTypes[".md"] > 0 {
		return "Documentation repository"
	}

	return "General purpose directory"
}

func (da *DefaultDirectoryAnalyzer) determineArchitecture(structure *DirectoryStructure, orgInfo *OrganizationInfo) string {
	if orgInfo.Pattern != "Custom" && orgInfo.Pattern != "unknown" {
		return orgInfo.Pattern
	}

	// Infer architecture from structure
	if structure.Languages["go"] > 0 {
		return "Go service architecture"
	}

	if structure.Languages["javascript"] > 0 || structure.Languages["typescript"] > 0 {
		if structure.FileTypes[".json"] > 0 {
			return "Node.js application"
		} else {
			return "Frontend application"
		}
	}

	return "Unknown architecture"
}

// Additional helper methods for comprehensive analysis

func (da *DefaultDirectoryAnalyzer) collectFilesAndDirs(rootPath string) ([]string, []string, error) {
	files := []string{}
	dirs := []string{}

	err := filepath.Walk(rootPath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if info.IsDir() {
			dirs = append(dirs, path)
		} else {
			files = append(files, path)
		}

		return nil
	})

	return files, dirs, err
}

func (da *DefaultDirectoryAnalyzer) detectNamingPatterns(files, dirs []string) []*NamingPattern {
	patterns := []*NamingPattern{}

	// Analyze file naming patterns
	filePattern := da.analyzeNamingPattern(files, "file")
	if filePattern != nil {
		patterns = append(patterns, filePattern)
	}

	// Analyze directory naming patterns
	dirPattern := da.analyzeNamingPattern(dirs, "directory")
	if dirPattern != nil {
		patterns = append(patterns, dirPattern)
	}

	return patterns
}

func (da *DefaultDirectoryAnalyzer) analyzeNamingPattern(paths []string, scope string) *NamingPattern {
	if len(paths) == 0 {
		return nil
	}

	// Extract just the names
	names := make([]string, len(paths))
	for i, path := range paths {
		names[i] = filepath.Base(path)
	}

	// Detect the dominant convention
	convention := da.detectDominantNamingStyle(names)
	
	return &NamingPattern{
		Pattern: Pattern{
			ID:          fmt.Sprintf("%s_naming", scope),
			Name:        fmt.Sprintf("%s Naming Convention", strings.Title(scope)),
			Type:        "naming",
			Description: fmt.Sprintf("Naming convention for %ss", scope),
			Confidence:  da.calculateNamingConsistency(names, convention),
			Examples:    names[:min(5, len(names))],
		},
		Convention: convention,
		Scope:      scope,
		CaseStyle:  convention,
	}
}

func (da *DefaultDirectoryAnalyzer) detectOrganizationalPatterns(ctx context.Context, rootPath string, dirs []string) []*OrganizationalPattern {
	patterns := []*OrganizationalPattern{}

	// Check against known organizational patterns
	for _, pattern := range da.organizationDetector.commonPatterns {
		if da.matchesOrganizationalPattern(dirs, pattern) {
			patterns = append(patterns, pattern)
		}
	}

	return patterns
}

func (da *DefaultDirectoryAnalyzer) matchesOrganizationalPattern(dirs []string, pattern *OrganizationalPattern) bool {
	dirSet := make(map[string]bool)
	for _, dir := range dirs {
		dirSet[strings.ToLower(filepath.Base(dir))] = true
	}

	matchCount := 0
	for _, example := range pattern.Examples {
		exampleName := strings.TrimSuffix(strings.ToLower(example), "/")
		if dirSet[exampleName] {
			matchCount++
		}
	}

	// Require at least half of the examples to match
	return matchCount >= len(pattern.Examples)/2
}

func (da *DefaultDirectoryAnalyzer) calculateConventionConsistency(files, dirs []string, patterns []*NamingPattern) float64 {
	if len(patterns) == 0 {
		return 0.5
	}

	totalConsistency := 0.0
	for _, pattern := range patterns {
		totalConsistency += pattern.Confidence
	}

	return totalConsistency / float64(len(patterns))
}

func (da *DefaultDirectoryAnalyzer) findConventionViolations(files, dirs []string, patterns []*NamingPattern) []*Violation {
	violations := []*Violation{}

	// Check for naming violations
	for _, pattern := range patterns {
		if pattern.Scope == "file" {
			for _, file := range files {
				name := filepath.Base(file)
				if !da.matchesNamingStyle(name, pattern.Convention) {
					violations = append(violations, &Violation{
						Type:       "naming",
						Path:       file,
						Expected:   pattern.Convention,
						Actual:     da.detectNamingStyle(name),
						Severity:   "warning",
						Suggestion: fmt.Sprintf("Rename to follow %s convention", pattern.Convention),
					})
				}
			}
		} else if pattern.Scope == "directory" {
			for _, dir := range dirs {
				name := filepath.Base(dir)
				if !da.matchesNamingStyle(name, pattern.Convention) {
					violations = append(violations, &Violation{
						Type:       "naming",
						Path:       dir,
						Expected:   pattern.Convention,
						Actual:     da.detectNamingStyle(name),
						Severity:   "info",
						Suggestion: fmt.Sprintf("Rename to follow %s convention", pattern.Convention),
					})
				}
			}
		}
	}

	return violations
}

func (da *DefaultDirectoryAnalyzer) detectNamingStyle(name string) string {
	if da.isCamelCase(name) {
		return "camelCase"
	} else if da.isKebabCase(name) {
		return "kebab-case"
	} else if da.isSnakeCase(name) {
		return "snake_case"
	} else if da.isPascalCase(name) {
		return "PascalCase"
	}
	return "unknown"
}

func (da *DefaultDirectoryAnalyzer) generateConventionRecommendations(analysis *ConventionAnalysis) []*Recommendation {
	recommendations := []*Recommendation{}

	// Recommend consistency improvements
	if analysis.Consistency < 0.8 {
		recommendations = append(recommendations, &Recommendation{
			Type:        "consistency",
			Title:       "Improve naming consistency",
			Description: "Consider standardizing naming conventions across the project",
			Priority:    2,
			Effort:      "medium",
			Impact:      "high",
			Steps:       []string{"Choose a consistent naming style", "Rename files/directories", "Update style guide"},
		})
	}

	// Recommend architectural improvements
	if len(analysis.OrganizationalPatterns) == 0 {
		recommendations = append(recommendations, &Recommendation{
			Type:        "architecture",
			Title:       "Consider architectural patterns",
			Description: "Project structure could benefit from established architectural patterns",
			Priority:    3,
			Effort:      "high",
			Impact:      "high",
			Steps:       []string{"Evaluate current structure", "Choose appropriate pattern", "Refactor gradually"},
		})
	}

	return recommendations
}

// More helper methods for relationship analysis

func (da *DefaultDirectoryAnalyzer) findSubdirectories(dirPath string) ([]string, error) {
	files, err := ioutil.ReadDir(dirPath)
	if err != nil {
		return nil, err
	}

	subdirs := []string{}
	for _, file := range files {
		if file.IsDir() {
			subdirs = append(subdirs, filepath.Join(dirPath, file.Name()))
		}
	}

	return subdirs, nil
}

func (da *DefaultDirectoryAnalyzer) analyzeDependencies(ctx context.Context, subdirs []string) ([]*DirectoryDependency, error) {
	dependencies := []*DirectoryDependency{}

	for _, dir := range subdirs {
		deps, err := da.findDirectoryDependencies(ctx, dir, subdirs)
		if err != nil {
			continue // Skip directories we can't analyze
		}
		dependencies = append(dependencies, deps...)
	}

	return dependencies, nil
}

func (da *DefaultDirectoryAnalyzer) findDirectoryDependencies(ctx context.Context, dir string, allDirs []string) ([]*DirectoryDependency, error) {
	dependencies := []*DirectoryDependency{}

	// Walk through files in the directory
	err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if err != nil || info.IsDir() {
			return nil
		}

		// Read file content to find imports
		content, err := ioutil.ReadFile(path)
		if err != nil {
			return nil
		}

		// Detect language and find imports
		ext := strings.ToLower(filepath.Ext(path))
		language := da.mapExtensionToLanguage(ext)

		if detector, exists := da.relationshipAnalyzer.dependencyDetectors[language]; exists {
			imports := da.extractImports(string(content), detector.importPatterns)
			
			// Check which imports refer to other directories
			for _, imp := range imports {
				for _, otherDir := range allDirs {
					if otherDir != dir && da.isLocalDependency(imp, dir, otherDir) {
						dependencies = append(dependencies, &DirectoryDependency{
							From:     dir,
							To:       otherDir,
							Type:     "import",
							Strength: 1.0,
							Reason:   fmt.Sprintf("Import: %s", imp),
						})
					}
				}
			}
		}

		return nil
	})

	return dependencies, err
}

func (da *DefaultDirectoryAnalyzer) extractImports(content string, patterns []*regexp.Regexp) []string {
	imports := []string{}
	
	for _, pattern := range patterns {
		matches := pattern.FindAllStringSubmatch(content, -1)
		for _, match := range matches {
			if len(match) > 1 {
				imports = append(imports, match[1])
			}
		}
	}

	return imports
}

func (da *DefaultDirectoryAnalyzer) isLocalDependency(importPath, fromDir, toDir string) bool {
	// Simple heuristic: check if import path references the target directory
	fromBase := filepath.Base(fromDir)
	toBase := filepath.Base(toDir)
	
	return strings.Contains(importPath, toBase) || 
		   strings.Contains(importPath, "../"+toBase) ||
		   strings.Contains(importPath, "./"+toBase)
}

func (da *DefaultDirectoryAnalyzer) analyzeDirectoryRelationships(subdirs []string, dependencies []*DirectoryDependency) []*DirectoryRelation {
	relationships := []*DirectoryRelation{}

	// Create relationship map
	depMap := make(map[string]map[string]int)
	for _, dep := range dependencies {
		if depMap[dep.From] == nil {
			depMap[dep.From] = make(map[string]int)
		}
		depMap[dep.From][dep.To]++
	}

	// Create bidirectional relationships
	processed := make(map[string]bool)
	for _, dir1 := range subdirs {
		for _, dir2 := range subdirs {
			if dir1 >= dir2 {
				continue
			}

			key := dir1 + ":" + dir2
			if processed[key] {
				continue
			}
			processed[key] = true

			// Check for relationships
			deps1to2 := depMap[dir1][dir2]
			deps2to1 := depMap[dir2][dir1]

			if deps1to2 > 0 || deps2to1 > 0 {
				relType := "depends"
				strength := float64(deps1to2 + deps2to1)
				bidirectional := deps1to2 > 0 && deps2to1 > 0

				if bidirectional {
					relType = "mutual"
				}

				relationships = append(relationships, &DirectoryRelation{
					Directory1:    dir1,
					Directory2:    dir2,
					Type:          relType,
					Strength:      strength,
					Description:   fmt.Sprintf("%d dependencies between directories", deps1to2+deps2to1),
					Bidirectional: bidirectional,
				})
			}
		}
	}

	return relationships
}

func (da *DefaultDirectoryAnalyzer) calculateCouplingMetrics(subdirs []string, dependencies []*DirectoryDependency) *CouplingMetrics {
	if len(subdirs) == 0 {
		return &CouplingMetrics{}
	}

	// Calculate afferent and efferent coupling
	afferent := make(map[string]int)
	efferent := make(map[string]int)

	for _, dep := range dependencies {
		efferent[dep.From]++
		afferent[dep.To]++
	}

	// Calculate averages
	totalAfferent := 0
	totalEfferent := 0
	for _, dir := range subdirs {
		totalAfferent += afferent[dir]
		totalEfferent += efferent[dir]
	}

	avgAfferent := float64(totalAfferent) / float64(len(subdirs))
	avgEfferent := float64(totalEfferent) / float64(len(subdirs))

	// Calculate instability (efferent / (afferent + efferent))
	instability := 0.0
	if avgAfferent+avgEfferent > 0 {
		instability = avgEfferent / (avgAfferent + avgEfferent)
	}

	return &CouplingMetrics{
		AfferentCoupling: avgAfferent,
		EfferentCoupling: avgEfferent,
		Instability:      instability,
		Abstractness:     0.5, // Would need more analysis to determine
		DistanceFromMain: 0.0, // Would need to calculate distance from main sequence
	}
}

func (da *DefaultDirectoryAnalyzer) calculateModularityScore(relationships []*DirectoryRelation, coupling *CouplingMetrics) float64 {
	// Simple modularity score based on coupling metrics
	if coupling.Instability < 0.3 {
		return 0.8 // High modularity
	} else if coupling.Instability < 0.7 {
		return 0.6 // Medium modularity
	} else {
		return 0.4 // Low modularity
	}
}

func (da *DefaultDirectoryAnalyzer) determineArchitecturalStyle(subdirs []string, dependencies []*DirectoryDependency) string {
	if len(subdirs) == 0 {
		return "unknown"
	}

	// Analyze dependency patterns
	if len(dependencies) == 0 {
		return "independent"
	}

	// Check for layered architecture (unidirectional dependencies)
	bidirectionalCount := 0
	for _, dep := range dependencies {
		// Check if there's a reverse dependency
		for _, otherDep := range dependencies {
			if dep.From == otherDep.To && dep.To == otherDep.From {
				bidirectionalCount++
				break
			}
		}
	}

	if float64(bidirectionalCount)/float64(len(dependencies)) < 0.2 {
		return "layered"
	} else {
		return "interconnected"
	}
}

// Additional utility methods

func (da *DefaultDirectoryAnalyzer) walkDirectoryHierarchy(rootPath string, currentDepth, maxDepth int, fn func(string, int) error) error {
	if currentDepth > maxDepth {
		return nil
	}

	// Process current directory
	if err := fn(rootPath, currentDepth); err != nil {
		return err
	}

	// Process subdirectories
	files, err := ioutil.ReadDir(rootPath)
	if err != nil {
		return err
	}

	for _, file := range files {
		if file.IsDir() && !strings.HasPrefix(file.Name(), ".") {
			subPath := filepath.Join(rootPath, file.Name())
			if err := da.walkDirectoryHierarchy(subPath, currentDepth+1, maxDepth, fn); err != nil {
				return err
			}
		}
	}

	return nil
}

func (da *DefaultDirectoryAnalyzer) generateUCXLAddress(path string) (*ucxl.Address, error) {
	cleanPath := filepath.Clean(path)
	addr, err := ucxl.ParseAddress(fmt.Sprintf("dir://%s", cleanPath))
	if err != nil {
		return nil, fmt.Errorf("failed to generate UCXL address: %w", err)
	}
	return addr, nil
}

func (da *DefaultDirectoryAnalyzer) generateDirectorySummary(structure *DirectoryStructure) string {
	summary := fmt.Sprintf("Directory with %d files and %d subdirectories", 
		structure.FileCount, structure.DirectoryCount)

	// Add language information
	if len(structure.Languages) > 0 {
		var langs []string
		for lang, count := range structure.Languages {
			langs = append(langs, fmt.Sprintf("%s (%d)", lang, count))
		}
		sort.Strings(langs)
		summary += fmt.Sprintf(", containing: %s", strings.Join(langs[:min(3, len(langs))], ", "))
	}

	return summary
}

func (da *DefaultDirectoryAnalyzer) generateDirectoryTags(structure *DirectoryStructure, path string) []string {
	tags := []string{}

	// Add directory name as tag
	dirName := filepath.Base(path)
	if dirName != "." && dirName != "/" {
		tags = append(tags, "dir:"+dirName)
	}

	// Add language tags
	for lang := range structure.Languages {
		tags = append(tags, lang)
	}

	// Add size category
	if structure.FileCount > 100 {
		tags = append(tags, "large-project")
	} else if structure.FileCount > 20 {
		tags = append(tags, "medium-project")
	} else {
		tags = append(tags, "small-project")
	}

	// Add architecture tags
	if structure.Architecture != "unknown" && structure.Architecture != "" {
		tags = append(tags, strings.ToLower(strings.ReplaceAll(structure.Architecture, " ", "-")))
	}

	return tags
}

func (da *DefaultDirectoryAnalyzer) extractTechnologiesFromStructure(structure *DirectoryStructure) []string {
	technologies := []string{}

	// Add languages as technologies
	for lang := range structure.Languages {
		technologies = append(technologies, lang)
	}

	// Add framework detection based on file types and structure
	if structure.FileTypes[".json"] > 0 && (structure.Languages["javascript"] > 0 || structure.Languages["typescript"] > 0) {
		technologies = append(technologies, "Node.js")
	}

	if structure.FileTypes[".py"] > 0 && structure.FileTypes[".txt"] > 0 {
		technologies = append(technologies, "Python")
	}

	return technologies
}

func (da *DefaultDirectoryAnalyzer) calculateDirectorySpecificity(structure *DirectoryStructure) int {
	specificity := 1

	// More specific if it has many files
	if structure.FileCount > 50 {
		specificity += 2
	} else if structure.FileCount > 10 {
		specificity += 1
	}

	// More specific if it uses specific technologies
	if len(structure.Languages) > 2 {
		specificity += 1
	}

	// More specific if it has clear purpose
	if structure.Purpose != "General purpose directory" {
		specificity += 1
	}

	return specificity
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}