package quality

import (
	"context"
	"path/filepath"
)

// Detector interface defines the contract for code quality detectors
type Detector interface {
	// Name returns the detector name
	Name() string
	
	// Detect runs the detector on the given path
	Detect(ctx context.Context, path string, config *Config) ([]Finding, error)
	
	// Severity returns the default severity for findings from this detector
	Severity() Severity
}

// LanguageDetector interface extends Detector for language-specific detectors
type LanguageDetector interface {
	Detector
	
	// SupportedLanguages returns the languages this detector supports
	SupportedLanguages() []string
	
	// ExtractFunctions extracts function information from source files
	ExtractFunctions(ctx context.Context, files []string) ([]FunctionInfo, error)
	
	// ExtractClasses extracts class information from source files
	ExtractClasses(ctx context.Context, files []string) ([]ClassInfo, error)
}

// FileFinder interface for finding files of a specific language
type FileFinder interface {
	// FindFiles returns source files for the given path and language
	FindFiles(path string, language string) ([]string, error)
	
	// IsSourceFile checks if a file is a source file for the language
	IsSourceFile(path string, language string) bool
}

// BaseDetector provides common functionality for detectors
type BaseDetector struct {
	name     string
	severity Severity
	finder   FileFinder
}

// NewBaseDetector creates a new base detector
func NewBaseDetector(name string, severity Severity, finder FileFinder) *BaseDetector {
	return &BaseDetector{
		name:     name,
		severity: severity,
		finder:   finder,
	}
}

// Name returns the detector name
func (d *BaseDetector) Name() string {
	return d.name
}

// Severity returns the default severity
func (d *BaseDetector) Severity() Severity {
	return d.severity
}

// FindFiles finds source files using the file finder
func (d *BaseDetector) FindFiles(path string, language string) ([]string, error) {
	if d.finder != nil {
		return d.finder.FindFiles(path, language)
	}
	return nil, nil
}

// ShouldExclude checks if a path should be excluded based on config
func ShouldExclude(path string, excludes []string) bool {
	if len(excludes) == 0 {
		return false
	}
	
	for _, pattern := range excludes {
		matched, err := filepath.Match(pattern, path)
		if err == nil && matched {
			return true
		}
		
		// Check directory exclusion
		matched, err = filepath.Match(pattern, filepath.Base(path))
		if err == nil && matched {
			return true
		}
	}
	
	return false
}
