//! Configuration types for the aurora-semantic engine.

use serde::{Deserialize, Serialize};
use std::path::PathBuf;

use crate::types::Language;

/// Main configuration for the semantic search engine.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EngineConfig {
    /// Directory where indexes are stored.
    pub index_dir: PathBuf,
    /// Chunking configuration.
    pub chunking: ChunkingConfig,
    /// Embedding configuration.
    pub embedding: EmbeddingConfig,
    /// Search configuration.
    pub search: SearchConfig,
    /// Ignore patterns configuration.
    pub ignore: IgnoreConfig,
    /// Performance tuning.
    pub performance: PerformanceConfig,
}

impl EngineConfig {
    /// Create a new configuration with the given index directory.
    pub fn new(index_dir: PathBuf) -> Self {
        Self {
            index_dir,
            chunking: ChunkingConfig::default(),
            embedding: EmbeddingConfig::default(),
            search: SearchConfig::default(),
            ignore: IgnoreConfig::default(),
            performance: PerformanceConfig::default(),
        }
    }

    /// Builder-style method to set chunking config.
    pub fn with_chunking(mut self, config: ChunkingConfig) -> Self {
        self.chunking = config;
        self
    }

    /// Builder-style method to set embedding config.
    pub fn with_embedding(mut self, config: EmbeddingConfig) -> Self {
        self.embedding = config;
        self
    }

    /// Builder-style method to set search config.
    pub fn with_search(mut self, config: SearchConfig) -> Self {
        self.search = config;
        self
    }

    /// Builder-style method to set ignore config.
    pub fn with_ignore(mut self, config: IgnoreConfig) -> Self {
        self.ignore = config;
        self
    }

    /// Builder-style method to set performance config.
    pub fn with_performance(mut self, config: PerformanceConfig) -> Self {
        self.performance = config;
        self
    }
}

impl Default for EngineConfig {
    fn default() -> Self {
        Self::new(PathBuf::from(".aurora"))
    }
}

/// Configuration for code chunking.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChunkingConfig {
    /// Maximum chunk size in characters.
    pub max_chunk_size: usize,
    /// Minimum chunk size in characters.
    pub min_chunk_size: usize,
    /// Whether to extract documentation comments.
    pub extract_comments: bool,
}

impl Default for ChunkingConfig {
    fn default() -> Self {
        Self {
            max_chunk_size: 2000,
            min_chunk_size: 50,
            extract_comments: true,
        }
    }
}

/// Configuration for embedding generation.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EmbeddingConfig {
    /// Embedding dimension.
    pub dimension: usize,
    /// Batch size for embedding generation.
    pub batch_size: usize,
    /// Maximum sequence length.
    pub max_length: usize,
    /// Whether to normalize embeddings.
    pub normalize: bool,
}

impl Default for EmbeddingConfig {
    fn default() -> Self {
        Self {
            dimension: 768, // Common for code models like jina-code
            batch_size: 32,
            max_length: 512,
            normalize: true,
        }
    }
}

/// Configuration for search behavior.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchConfig {
    /// Default number of results to return.
    pub default_limit: usize,
    /// Maximum number of results to return.
    pub max_limit: usize,
    /// Default search mode.
    pub default_mode: SearchMode,
    /// Weight for lexical results in hybrid search (0.0 to 1.0).
    pub lexical_weight: f32,
    /// Weight for semantic results in hybrid search (0.0 to 1.0).
    pub semantic_weight: f32,
    /// Minimum score threshold for results (0.0 to 1.0).
    pub min_score: f32,
    /// Enable fuzzy matching in lexical search.
    pub fuzzy_matching: bool,
    /// Fuzzy matching distance (edit distance).
    pub fuzzy_distance: u8,
}

impl Default for SearchConfig {
    fn default() -> Self {
        Self {
            default_limit: 20,
            max_limit: 100,
            default_mode: SearchMode::Hybrid,
            lexical_weight: 0.4,
            semantic_weight: 0.6,
            min_score: 0.1,
            fuzzy_matching: true,
            fuzzy_distance: 2,
        }
    }
}

/// Search mode selection.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum SearchMode {
    /// Keyword-based lexical search only.
    Lexical,
    /// Embedding-based semantic search only.
    Semantic,
    /// Combined lexical and semantic search.
    Hybrid,
}

impl Default for SearchMode {
    fn default() -> Self {
        Self::Hybrid
    }
}

/// Configuration for ignore patterns.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IgnoreConfig {
    /// Respect .gitignore files.
    pub use_gitignore: bool,
    /// Respect .ignore files.
    pub use_ignore_files: bool,
    /// Additional patterns to ignore (glob patterns).
    pub patterns: Vec<String>,
    /// File extensions to ignore.
    pub ignored_extensions: Vec<String>,
    /// Directories to always ignore (by name, matches anywhere in path).
    pub ignored_directories: Vec<String>,
    /// Maximum file size to index (in bytes).
    pub max_file_size: u64,
    /// Specific file paths to exclude (relative to workspace root).
    pub excluded_files: Vec<PathBuf>,
    /// Specific directory paths to exclude (relative to workspace root).
    pub excluded_directories: Vec<PathBuf>,
}

impl Default for IgnoreConfig {
    fn default() -> Self {
        Self {
            use_gitignore: true,
            use_ignore_files: true,
            patterns: vec![],
            ignored_extensions: vec![
                // ============================================
                // BINARY / COMPILED
                // ============================================
                "exe".into(), "dll".into(), "so".into(), "dylib".into(), "a".into(),
                "lib".into(), "obj".into(), "o".into(), "ko".into(), "elf".into(),
                "bin".into(), "out".into(), "app".into(), "msi".into(), "dmg".into(),
                "deb".into(), "rpm".into(), "apk".into(), "ipa".into(), "aab".into(),
                "class".into(), "jar".into(), "war".into(), "ear".into(),
                "pyc".into(), "pyo".into(), "pyd".into(), "whl".into(),
                "wasm".into(), "wat".into(),
                "rlib".into(), "rmeta".into(), "d".into(),
                
                // ============================================
                // IMAGES / MEDIA
                // ============================================
                "png".into(), "jpg".into(), "jpeg".into(), "gif".into(), "bmp".into(),
                "ico".into(), "icns".into(), "svg".into(), "webp".into(), "avif".into(),
                "tiff".into(), "tif".into(), "psd".into(), "ai".into(), "eps".into(),
                "raw".into(), "cr2".into(), "nef".into(), "heic".into(), "heif".into(),
                // Video
                "mp4".into(), "avi".into(), "mov".into(), "wmv".into(), "flv".into(),
                "mkv".into(), "webm".into(), "m4v".into(), "mpeg".into(), "mpg".into(),
                "3gp".into(), "ogv".into(),
                // Audio
                "mp3".into(), "wav".into(), "ogg".into(), "flac".into(), "aac".into(),
                "wma".into(), "m4a".into(), "opus".into(), "aiff".into(),
                
                // ============================================
                // FONTS
                // ============================================
                "woff".into(), "woff2".into(), "ttf".into(), "otf".into(), "eot".into(),
                
                // ============================================
                // ARCHIVES / COMPRESSED
                // ============================================
                "zip".into(), "tar".into(), "gz".into(), "bz2".into(), "xz".into(),
                "rar".into(), "7z".into(), "tgz".into(), "tbz2".into(), "lz".into(),
                "lzma".into(), "cab".into(), "iso".into(), "dmg".into(), "pkg".into(),
                "zst".into(), "lz4".into(), "br".into(),
                
                // ============================================
                // DOCUMENTS / NON-CODE (CRITICAL FOR CODE SEARCH!)
                // ============================================
                // Markdown - creates too many chunks, dominates search results
                "md".into(), "markdown".into(), "mdx".into(),
                // reStructuredText
                "rst".into(), "rest".into(),
                // Plain text docs
                "txt".into(),
                // Office documents
                "pdf".into(), "doc".into(), "docx".into(), "xls".into(), "xlsx".into(),
                "ppt".into(), "pptx".into(), "odt".into(), "ods".into(), "odp".into(),
                "rtf".into(), "pages".into(), "numbers".into(), "key".into(),
                
                // ============================================
                // DATABASE FILES
                // ============================================
                "db".into(), "sqlite".into(), "sqlite3".into(), "mdb".into(),
                "accdb".into(), "frm".into(), "myd".into(), "myi".into(),
                "ibd".into(), "dbf".into(), "sav".into(),
                
                // ============================================
                // LOCK FILES (CRITICAL!)
                // ============================================
                "lock".into(), "lockb".into(),
                
                // ============================================
                // MAP / SOURCE MAP FILES
                // ============================================
                "map".into(),
                
                // ============================================
                // LOG FILES
                // ============================================
                "log".into(),
                
                // ============================================
                // BACKUP / TEMP FILES
                // ============================================
                "bak".into(), "backup".into(), "tmp".into(), "temp".into(),
                "swp".into(), "swo".into(), "swn".into(), // Vim swap files
                
                // ============================================
                // OS SPECIFIC
                // ============================================
                "DS_Store".into(), "Thumbs.db".into(), "desktop.ini".into(),
                
                // ============================================
                // CERTIFICATES / KEYS (Security)
                // ============================================
                "pem".into(), "crt".into(), "cer".into(), "der".into(),
                "p12".into(), "pfx".into(), "jks".into(), "keystore".into(),
            ],
            ignored_directories: vec![
                // ============================================
                // VERSION CONTROL
                // ============================================
                ".git".into(), ".svn".into(), ".hg".into(), ".bzr".into(),
                "_darcs".into(), ".fossil".into(),
                
                // ============================================
                // JAVASCRIPT / NODE.JS / WEB
                // ============================================
                "node_modules".into(),
                ".npm".into(), ".pnpm".into(), ".pnpm-store".into(),
                ".yarn".into(), ".yarnrc".into(), ".yarn-cache".into(),
                "bower_components".into(),
                ".parcel-cache".into(), ".cache".into(),
                ".turbo".into(), ".vercel".into(), ".netlify".into(),
                ".next".into(), ".nuxt".into(), ".output".into(),
                ".svelte-kit".into(), ".astro".into(),
                ".docusaurus".into(), ".vuepress".into(), ".vitepress".into(),
                "storybook-static".into(), ".storybook".into(),
                
                // ============================================
                // PYTHON
                // ============================================
                "__pycache__".into(), ".pytest_cache".into(), ".mypy_cache".into(),
                ".ruff_cache".into(), ".pytype".into(),
                "venv".into(), ".venv".into(), "env".into(), ".env".into(),
                "virtualenv".into(), ".virtualenv".into(),
                ".conda".into(), "conda-meta".into(), "envs".into(),
                ".tox".into(), ".nox".into(),
                "*.egg-info".into(), ".eggs".into(), "eggs".into(),
                "site-packages".into(), "dist-packages".into(),
                ".ipynb_checkpoints".into(),
                "htmlcov".into(), ".coverage".into(),
                ".hypothesis".into(),
                
                // ============================================
                // RUST
                // ============================================
                "target".into(),
                ".cargo".into(),
                
                // ============================================
                // GO
                // ============================================
                "vendor".into(),
                "pkg".into(),
                
                // ============================================
                // JAVA / KOTLIN / GRADLE / MAVEN
                // ============================================
                ".gradle".into(), "gradle".into(),
                ".m2".into(), ".mvn".into(),
                "bin".into(), "out".into(),
                ".apt_generated".into(), ".apt_generated_tests".into(),
                "generated-sources".into(), "generated-test-sources".into(),
                
                // ============================================
                // .NET / C#
                // ============================================
                "obj".into(), "bin".into(),
                "packages".into(), ".nuget".into(),
                "Debug".into(), "Release".into(),
                "x64".into(), "x86".into(), "ARM".into(), "ARM64".into(),
                "TestResults".into(),
                
                // ============================================
                // C / C++
                // ============================================
                "CMakeFiles".into(), "cmake-build-debug".into(), "cmake-build-release".into(),
                ".ccache".into(), ".sccache".into(),
                "Debug".into(), "Release".into(), "MinSizeRel".into(), "RelWithDebInfo".into(),
                
                // ============================================
                // RUBY
                // ============================================
                ".bundle".into(), "vendor/bundle".into(),
                ".gem".into(), "gems".into(),
                
                // ============================================
                // PHP
                // ============================================
                "vendor".into(),
                ".phpunit.cache".into(), ".php-cs-fixer.cache".into(),
                
                // ============================================
                // SWIFT / IOS / MACOS
                // ============================================
                ".build".into(), "Build".into(),
                "DerivedData".into(), "Pods".into(),
                ".swiftpm".into(), "Carthage".into(),
                "xcuserdata".into(), "*.xcworkspace".into(),
                
                // ============================================
                // ANDROID
                // ============================================
                ".gradle".into(), "gradle".into(),
                "build".into(), "app/build".into(),
                ".cxx".into(), ".externalNativeBuild".into(),
                "captures".into(), ".navigation".into(),
                "local.properties".into(),
                
                // ============================================
                // FLUTTER / DART
                // ============================================
                ".dart_tool".into(), ".pub-cache".into(), ".pub".into(),
                "build".into(), ".flutter-plugins".into(),
                "ephemeral".into(),
                
                // ============================================
                // ELECTRON / TAURI
                // ============================================
                "release".into(), "src-tauri/target".into(),
                ".webpack".into(), ".electron".into(),
                
                // ============================================
                // UNITY / GAME DEV
                // ============================================
                "Library".into(), "Temp".into(), "Obj".into(),
                "Build".into(), "Builds".into(), "Logs".into(),
                "UserSettings".into(), "MemoryCaptures".into(),
                "Recordings".into(), "Asset Store-5.x".into(),
                
                // ============================================
                // UNREAL ENGINE
                // ============================================
                "Binaries".into(), "Intermediate".into(), "Saved".into(),
                "DerivedDataCache".into(),
                
                // ============================================
                // JUCE (Audio Development)
                // ============================================
                "Builds".into(), "JuceLibraryCode".into(),
                
                // ============================================
                // TIZEN
                // ============================================
                ".sign".into(), ".build".into(), "Debug-Tizen".into(),
                "Release-Tizen".into(),
                
                // ============================================
                // IDE / EDITOR CONFIGS
                // ============================================
                ".idea".into(), ".vscode".into(), ".vs".into(),
                ".cursor".into(), ".atom".into(), ".sublime".into(),
                ".eclipse".into(), ".settings".into(), ".project".into(),
                ".classpath".into(), ".factorypath".into(),
                "*.xcodeproj".into(), "*.xcworkspace".into(),
                ".metals".into(), ".bloop".into(), ".bsp".into(),
                
                // ============================================
                // BUILD OUTPUTS (GENERIC)
                // ============================================
                "dist".into(), "build".into(), "out".into(), "output".into(),
                "_build".into(), ".build".into(),
                "public".into(), "static".into(), // Often generated
                "generated".into(), "gen".into(), "auto-generated".into(),
                
                // ============================================
                // TESTING / COVERAGE
                // ============================================
                "coverage".into(), ".nyc_output".into(),
                "test-results".into(), "test-output".into(),
                "__tests__".into(), "__mocks__".into(),
                ".jest".into(), "jest-cache".into(),
                "cypress/videos".into(), "cypress/screenshots".into(),
                "playwright-report".into(), "test-results".into(),
                
                // ============================================
                // DOCUMENTATION (Generated and Source - CRITICAL!)
                // ============================================
                // Documentation directories pollute code search results
                "docs".into(), "doc".into(), "DOCS".into(), "DOC".into(),
                "documentation".into(), "Documentation".into(),
                "docs/_build".into(), "site".into(), "_site".into(),
                "javadoc".into(), "apidoc".into(), "doxygen".into(),
                "typedoc".into(), "rustdoc".into(),
                // Spec/planning directories
                "specs".into(), "spec".into(), "SPECS".into(),
                ".specify".into(), ".windsurf".into(),
                "resources".into(), // Often contains non-code docs
                
                // ============================================
                // LOGS / TEMP
                // ============================================
                "logs".into(), "log".into(),
                "tmp".into(), "temp".into(), ".tmp".into(), ".temp".into(),
                
                // ============================================
                // AURORA / PROJECT SPECIFIC
                // ============================================
                ".aurora".into(),
                
                // ============================================
                // MISC / OTHER
                // ============================================
                ".terraform".into(), ".pulumi".into(),
                ".serverless".into(), ".amplify".into(),
                "cdk.out".into(), ".aws-sam".into(),
                ".docker".into(), ".vagrant".into(),
                "helm-charts".into(),
            ],
            max_file_size: 512 * 1024, // 512KB - reduced from 1MB
            // Explicit path exclusions (empty by default, users can add specific paths)
            excluded_files: vec![],
            // Always exclude the Aurora index directory by default
            excluded_directories: vec![PathBuf::from(".aurora")],
        }
    }
}

impl IgnoreConfig {
    /// Builder-style method to exclude a specific file path (relative to workspace root).
    ///
    /// # Example
    /// ```rust,ignore
    /// let config = IgnoreConfig::default()
    ///     .with_excluded_file("src/generated/types.rs");
    /// ```
    pub fn with_excluded_file(mut self, path: impl Into<PathBuf>) -> Self {
        self.excluded_files.push(path.into());
        self
    }

    /// Builder-style method to exclude multiple file paths (relative to workspace root).
    ///
    /// # Example
    /// ```rust,ignore
    /// let config = IgnoreConfig::default()
    ///     .with_excluded_files(vec![
    ///         "src/proto/generated.rs".into(),
    ///         "src/bindings/ffi.rs".into(),
    ///     ]);
    /// ```
    pub fn with_excluded_files(mut self, paths: Vec<PathBuf>) -> Self {
        self.excluded_files.extend(paths);
        self
    }

    /// Builder-style method to exclude a specific directory path (relative to workspace root).
    ///
    /// # Example
    /// ```rust,ignore
    /// let config = IgnoreConfig::default()
    ///     .with_excluded_directory("vendor/third-party");
    /// ```
    pub fn with_excluded_directory(mut self, path: impl Into<PathBuf>) -> Self {
        self.excluded_directories.push(path.into());
        self
    }

    /// Builder-style method to exclude multiple directory paths (relative to workspace root).
    ///
    /// # Example
    /// ```rust,ignore
    /// let config = IgnoreConfig::default()
    ///     .with_excluded_directories(vec![
    ///         "generated".into(),
    ///         "vendor/libs".into(),
    ///     ]);
    /// ```
    pub fn with_excluded_directories(mut self, paths: Vec<PathBuf>) -> Self {
        self.excluded_directories.extend(paths);
        self
    }

    /// Builder-style method to add an additional ignore pattern (glob format).
    pub fn with_pattern(mut self, pattern: impl Into<String>) -> Self {
        self.patterns.push(pattern.into());
        self
    }

    /// Builder-style method to add an ignored file extension.
    pub fn with_ignored_extension(mut self, ext: impl Into<String>) -> Self {
        self.ignored_extensions.push(ext.into());
        self
    }

    /// Builder-style method to add an ignored directory name.
    pub fn with_ignored_directory(mut self, dir: impl Into<String>) -> Self {
        self.ignored_directories.push(dir.into());
        self
    }

    /// Builder-style method to set the maximum file size.
    pub fn with_max_file_size(mut self, size: u64) -> Self {
        self.max_file_size = size;
        self
    }
}

/// Performance tuning configuration.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PerformanceConfig {
    /// Number of threads for parallel processing.
    pub num_threads: usize,
    /// Memory limit for indexing (in bytes).
    pub memory_limit: usize,
    /// Enable incremental indexing.
    pub incremental: bool,
}

impl Default for PerformanceConfig {
    fn default() -> Self {
        Self {
            num_threads: std::thread::available_parallelism()
                .map(|p| p.get())
                .unwrap_or(4),
            memory_limit: 512 * 1024 * 1024, // 512MB
            incremental: true,
        }
    }
}

/// Configuration for a specific workspace.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkspaceConfig {
    /// Root path of the workspace.
    pub root_path: PathBuf,
    /// Workspace-specific ignore patterns (in addition to global).
    pub additional_ignores: Vec<String>,
    /// Languages to index (None = all).
    pub languages: Option<Vec<Language>>,
    /// Watch for file changes.
    pub watch_changes: bool,
}

impl WorkspaceConfig {
    /// Create a new workspace configuration.
    pub fn new(root_path: PathBuf) -> Self {
        Self {
            root_path,
            additional_ignores: vec![],
            languages: None,
            watch_changes: false,
        }
    }

    /// Builder-style method to add ignore patterns.
    pub fn with_ignores(mut self, patterns: Vec<String>) -> Self {
        self.additional_ignores = patterns;
        self
    }

    /// Builder-style method to set languages.
    pub fn with_languages(mut self, languages: Vec<Language>) -> Self {
        self.languages = Some(languages);
        self
    }

    /// Builder-style method to enable file watching.
    pub fn with_watch(mut self) -> Self {
        self.watch_changes = true;
        self
    }
}
