//! # Build Traits
//!
//! Zero-dependency traits for build-time concerns in Rustelo framework.
//!
//! This crate defines pure trait interfaces that replace build.rs file
//! dependencies, allowing for trait-based dependency injection and eliminating
//! circular dependencies in the foundation crates.

#![deny(missing_docs)]
#![deny(unsafe_code)]

use core::fmt;

/// Result type for build operations
pub type BuildResult<T> = Result<T, BuildError>;

/// Error type for build operations
#[derive(Debug)]
pub enum BuildError {
    /// Configuration error
    Configuration(String),
    /// I/O error during build
    Io(String),
    /// Generation error
    Generation(String),
    /// Cache error
    Cache(String),
    /// Generic build error
    Other(String),
}

impl fmt::Display for BuildError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            BuildError::Configuration(msg) => write!(f, "Configuration error: {}", msg),
            BuildError::Io(msg) => write!(f, "I/O error: {}", msg),
            BuildError::Generation(msg) => write!(f, "Generation error: {}", msg),
            BuildError::Cache(msg) => write!(f, "Cache error: {}", msg),
            BuildError::Other(msg) => write!(f, "Build error: {}", msg),
        }
    }
}

impl core::error::Error for BuildError {}

/// Trait for component documentation generation
///
/// Replaces the component build.rs functionality with runtime trait resolution
pub trait ComponentDocumentationProvider {
    /// Generate comprehensive component documentation
    fn generate_components_documentation(
        &self,
        workspace_root: &str,
        info_path: &str,
    ) -> BuildResult<String>;

    /// Check if documentation needs to be regenerated
    fn needs_regeneration(&self, workspace_root: &str, info_path: &str) -> BuildResult<bool>;

    /// Get component dependencies for cache invalidation
    fn get_component_dependencies(&self, workspace_root: &str) -> BuildResult<Vec<String>>;
}

/// Trait for page scaffolding and documentation
///
/// Replaces the pages build.rs functionality with runtime trait resolution
pub trait PageScaffoldingProvider {
    /// Generate page components
    fn generate_page_components(&self, workspace_root: &str) -> BuildResult<()>;

    /// Run page scaffolding process
    fn run_pages_scaffolding(&self, workspace_root: &str) -> BuildResult<()>;

    /// Generate pages documentation
    fn generate_pages_documentation(
        &self,
        workspace_root: &str,
        content_path: &str,
        info_path: &str,
    ) -> BuildResult<String>;
}

/// Trait for server route documentation
///
/// Replaces the server build.rs functionality with runtime trait resolution
pub trait ServerDocumentationProvider {
    /// Generate server route documentation
    fn generate_server_documentation(
        &self,
        workspace_root: &str,
        info_path: &str,
    ) -> BuildResult<String>;

    /// Analyze server route definitions
    fn analyze_routes(&self, workspace_root: &str) -> BuildResult<Vec<RouteInfo>>;

    /// Generate route configuration TOML
    fn generate_route_config(&self, routes: &[RouteInfo]) -> BuildResult<String>;
}

/// Information about a discovered route
#[derive(Debug, Clone)]
pub struct RouteInfo {
    /// Route path pattern
    pub path: String,
    /// HTTP methods supported
    pub methods: Vec<String>,
    /// Handler function name
    pub handler: String,
    /// Route description/documentation
    pub description: Option<String>,
}

/// Trait for smart caching functionality
///
/// Replaces the smart caching logic from components build.rs
pub trait SmartCacheProvider {
    /// Check cache status for a file
    fn check_cache_status(&self, key: &str, content_hash: &str) -> BuildResult<CacheStatus>;

    /// Update cache with new content
    fn update_cache(
        &self,
        key: &str,
        content: &str,
        content_hash: &str,
        dependencies: Vec<String>,
    ) -> BuildResult<()>;

    /// Copy content from cache to target location
    fn copy_from_cache(&self, key: &str, target_path: &str) -> BuildResult<()>;

    /// Clear cache for a specific key
    fn clear_cache(&self, key: &str) -> BuildResult<()>;

    /// Check if caching is available
    fn is_available(&self) -> bool;
}

/// Cache status information
#[derive(Debug, Clone)]
pub enum CacheStatus {
    /// Cache is fresh and up to date
    Fresh(String),
    /// Cache exists but is stale
    Stale(String),
    /// No cache entry exists
    Missing(String),
}

/// Trait for path resolution
///
/// Replaces rustelo_tools::build::PathResolver functionality
pub trait PathResolver {
    /// Get site paths configuration
    fn get_site_paths(&self) -> BuildResult<SitePaths>;

    /// Get workspace root directory
    fn workspace_root(&self) -> BuildResult<String>;

    /// Resolve relative path to absolute
    fn resolve_path(&self, relative_path: &str) -> BuildResult<String>;
}

/// Site paths configuration
#[derive(Debug, Clone)]
pub struct SitePaths {
    /// Content directory path
    pub content: String,
    /// Info/documentation output path
    pub info: Option<String>,
    /// Public assets path
    pub public: Option<String>,
    /// Configuration files path
    pub config: Option<String>,
}

/// Registry for build trait implementations
///
/// Allows external crates to provide implementations of build traits
pub trait BuildTraitRegistry {
    /// Register a component documentation provider
    fn register_component_docs(&mut self, provider: Box<dyn ComponentDocumentationProvider>);

    /// Register a page scaffolding provider
    fn register_page_scaffolding(&mut self, provider: Box<dyn PageScaffoldingProvider>);

    /// Register a server documentation provider
    fn register_server_docs(&mut self, provider: Box<dyn ServerDocumentationProvider>);

    /// Register a smart cache provider
    fn register_smart_cache(&mut self, provider: Box<dyn SmartCacheProvider>);

    /// Register a path resolver
    fn register_path_resolver(&mut self, resolver: Box<dyn PathResolver>);

    /// Get registered component documentation provider
    fn get_component_docs(&self) -> Option<&dyn ComponentDocumentationProvider>;

    /// Get registered page scaffolding provider
    fn get_page_scaffolding(&self) -> Option<&dyn PageScaffoldingProvider>;

    /// Get registered server documentation provider
    fn get_server_docs(&self) -> Option<&dyn ServerDocumentationProvider>;

    /// Get registered smart cache provider
    fn get_smart_cache(&self) -> Option<&dyn SmartCacheProvider>;

    /// Get registered path resolver
    fn get_path_resolver(&self) -> Option<&dyn PathResolver>;
}

/// Default no-op implementations for when external providers are not available
pub mod defaults {
    use super::*;

    /// Default component documentation provider (no-op)
    pub struct NoOpComponentDocs;

    impl ComponentDocumentationProvider for NoOpComponentDocs {
        fn generate_components_documentation(&self, _: &str, _: &str) -> BuildResult<String> {
            Ok("# No component documentation provider registered".to_string())
        }

        fn needs_regeneration(&self, _: &str, _: &str) -> BuildResult<bool> {
            Ok(false)
        }

        fn get_component_dependencies(&self, _: &str) -> BuildResult<Vec<String>> {
            Ok(Vec::new())
        }
    }

    /// Default page scaffolding provider (no-op)
    pub struct NoOpPageScaffolding;

    impl PageScaffoldingProvider for NoOpPageScaffolding {
        fn generate_page_components(&self, _: &str) -> BuildResult<()> {
            Ok(())
        }

        fn run_pages_scaffolding(&self, _: &str) -> BuildResult<()> {
            Ok(())
        }

        fn generate_pages_documentation(&self, _: &str, _: &str, _: &str) -> BuildResult<String> {
            Ok("# No page scaffolding provider registered".to_string())
        }
    }

    /// Default server documentation provider (no-op)
    pub struct NoOpServerDocs;

    impl ServerDocumentationProvider for NoOpServerDocs {
        fn generate_server_documentation(&self, _: &str, _: &str) -> BuildResult<String> {
            Ok("# No server documentation provider registered".to_string())
        }

        fn analyze_routes(&self, _: &str) -> BuildResult<Vec<RouteInfo>> {
            Ok(Vec::new())
        }

        fn generate_route_config(&self, _: &[RouteInfo]) -> BuildResult<String> {
            Ok("# No routes found".to_string())
        }
    }
}
