use serde::{Deserialize, Serialize};

use super::{default_cc_compiler, default_cxx_compiler};

/// Configuration for the C/C++ dependency analyzer (`cpp`) — uses compiler -MM scanning.
/// External analyzer: runs gcc/g++ -MM and optional pkg-config/include_path_commands.
#[derive(Debug, Deserialize, Serialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct CppAnalyzerConfig {
    /// Additional include paths for header search
    #[serde(default)]
    pub include_paths: Vec<String>,
    /// pkg-config packages to query for include paths
    #[serde(default)]
    pub pkg_config: Vec<String>,
    /// Commands that output include paths (e.g., ["gcc -print-file-name=plugin"])
    #[serde(default)]
    pub include_path_commands: Vec<String>,
    /// Directory path segments to exclude from analysis (e.g., ["/kernel/", "/vendor/"])
    #[serde(default)]
    pub src_exclude_dirs: Vec<String>,
    /// C compiler (for -MM scanning)
    #[serde(default = "default_cc_compiler")]
    pub cc: String,
    /// C++ compiler (for -MM scanning)
    #[serde(default = "default_cxx_compiler")]
    pub cxx: String,
    /// C compiler flags (for -MM scanning)
    #[serde(default)]
    pub cflags: Vec<String>,
    /// C++ compiler flags (for -MM scanning)
    #[serde(default)]
    pub cxxflags: Vec<String>,
}

impl Default for CppAnalyzerConfig {
    fn default() -> Self {
        Self {
            include_paths: Vec::new(),
            pkg_config: Vec::new(),
            include_path_commands: Vec::new(),
            src_exclude_dirs: Vec::new(),
            cc: default_cc_compiler(),
            cxx: default_cxx_compiler(),
            cflags: Vec::new(),
            cxxflags: Vec::new(),
        }
    }
}

/// Configuration for the in-process C/C++ dependency analyzer (`icpp`) — native regex scanner.
/// Native analyzer by default: pure Rust, no external commands.
/// Setting `pkg_config` or `include_path_commands` will invoke external tools once at
/// startup to discover additional include paths, but dependency scanning itself
/// remains in-process.
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
#[serde(deny_unknown_fields)]
pub struct IcppAnalyzerConfig {
    /// Additional include paths for header search
    #[serde(default)]
    pub include_paths: Vec<String>,
    /// pkg-config packages to query for include paths (optional; invokes pkg-config if set)
    #[serde(default)]
    pub pkg_config: Vec<String>,
    /// Commands that output include paths (e.g., ["gcc -print-file-name=plugin"])
    /// Each command is run via `sh -c` and its stdout is added to the include search paths.
    #[serde(default)]
    pub include_path_commands: Vec<String>,
    /// Directory path segments to exclude from analysis
    #[serde(default)]
    pub src_exclude_dirs: Vec<String>,
    /// Whether to follow angle-bracket includes (`#include <foo.h>`).
    /// When false (default), `<angle>` includes are skipped entirely — even if they
    /// resolve through configured include paths — so system headers do not bloat
    /// the dependency graph. When true, angle-bracket includes are resolved and
    /// followed like quoted includes, but missing ones are still tolerated.
    #[serde(default)]
    pub follow_angle_brackets: bool,
    /// Whether to silently skip includes that cannot be resolved.
    /// When false (default), a quoted include (`#include "foo.h"`) that does not
    /// resolve produces a hard error. When true, unresolved includes of any kind
    /// are skipped without error.
    #[serde(default)]
    pub skip_not_found: bool,
}

