package quality

import (
	"os"
	"path/filepath"
	"strings"
)

// LanguageConfig represents configuration for a programming language
type LanguageConfig struct {
	Name        string   `json:"name"`
	Extensions  []string `json:"extensions"`
	MarkerFiles []string `json:"marker_files"`
	DefaultSrc  string   `json:"default_src"`
}

// GetSupportedLanguages returns all supported languages
func GetSupportedLanguages() []LanguageConfig {
	return []LanguageConfig{
		{
			Name:        "go",
			Extensions:  []string{".go"},
			MarkerFiles: []string{"go.mod", "go.sum"},
			DefaultSrc:  ".",
		},
		{
			Name:        "typescript",
			Extensions:  []string{".ts", ".tsx"},
			MarkerFiles: []string{"package.json", "tsconfig.json"},
			DefaultSrc:  "src",
		},
		{
			Name:        "python",
			Extensions:  []string{".py"},
			MarkerFiles: []string{"requirements.txt", "setup.py", "pyproject.toml"},
			DefaultSrc:  ".",
		},
		{
			Name:        "java",
			Extensions:  []string{".java"},
			MarkerFiles: []string{"pom.xml", "build.gradle"},
			DefaultSrc:  "src/main/java",
		},
		{
			Name:        "rust",
			Extensions:  []string{".rs"},
			MarkerFiles: []string{"Cargo.toml"},
			DefaultSrc:  "src",
		},
		{
			Name:        "javascript",
			Extensions:  []string{".js", ".jsx"},
			MarkerFiles: []string{"package.json"},
			DefaultSrc:  "src",
		},
		{
			Name:        "csharp",
			Extensions:  []string{".cs"},
			MarkerFiles: []string{"*.csproj", "*.sln"},
			DefaultSrc:  ".",
		},
		{
			Name:        "dart",
			Extensions:  []string{".dart"},
			MarkerFiles: []string{"pubspec.yaml"},
			DefaultSrc:  "lib",
		},
	}
}

// DefaultFileFinder implements FileFinder interface
type DefaultFileFinder struct{}

// NewDefaultFileFinder creates a new default file finder
func NewDefaultFileFinder() *DefaultFileFinder {
	return &DefaultFileFinder{}
}

// FindFiles returns source files for the given path and language
func (f *DefaultFileFinder) FindFiles(path string, language string) ([]string, error) {
	languages := GetSupportedLanguages()
	var extensions []string

	// Find language config
	for _, lang := range languages {
		if lang.Name == language {
			extensions = lang.Extensions
			break
		}
	}

	// Default to Go extensions if not found
	if len(extensions) == 0 {
		extensions = []string{".go"}
	}

	var files []string
	err := filepath.Walk(path, func(filePath string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// Skip directories
		if info.IsDir() {
			// Skip hidden directories and common exclude dirs
			base := filepath.Base(filePath)
			if filePath != path && (strings.HasPrefix(base, ".") || base == "node_modules" || base == "vendor") {
				return filepath.SkipDir
			}
			return nil
		}

		// Check file extension
		ext := filepath.Ext(filePath)
		for _, langExt := range extensions {
			if ext == langExt {
				files = append(files, filePath)
				break
			}
		}

		return nil
	})

	return files, err
}

// IsSourceFile checks if a file is a source file for the language
func (f *DefaultFileFinder) IsSourceFile(path string, language string) bool {
	languages := GetSupportedLanguages()
	var extensions []string

	// Find language config
	for _, lang := range languages {
		if lang.Name == language {
			extensions = lang.Extensions
			break
		}
	}

	// Default to Go extensions if not found
	if len(extensions) == 0 {
		extensions = []string{".go"}
	}

	ext := filepath.Ext(path)
	for _, langExt := range extensions {
		if ext == langExt {
			return true
		}
	}

	return false
}

// DetectLanguage attempts to auto-detect the project language from marker files
func DetectLanguage(path string) string {
	languages := GetSupportedLanguages()

	// Check for marker files in order of specificity
	for _, lang := range languages {
		for _, marker := range lang.MarkerFiles {
			markerPath := filepath.Join(path, marker)
			if _, err := filepath.Glob(markerPath); err == nil {
				// Check if any files match the pattern
				matches, _ := filepath.Glob(markerPath)
				if len(matches) > 0 {
					return lang.Name
				}
			}
		}
	}

	// Default to Go if no markers found
	return "go"
}
