//! Traits for Rustelo framework components

use std::path::Path;

use async_trait::async_trait;
use serde::{Deserialize, Serialize};

use crate::error::Result;

/// Trait for components that can be initialized
#[async_trait]
pub trait Initialize {
    /// Initialize the component with configuration
    async fn initialize(&mut self) -> Result<()>;

    /// Check if the component is initialized
    fn is_initialized(&self) -> bool;
}

/// Trait for asset resolution
#[async_trait]
pub trait AssetResolver {
    /// Resolve an asset path using fallback strategy
    async fn resolve(&self, path: &Path) -> Result<Option<std::path::PathBuf>>;

    /// Check if an asset exists at the given path
    async fn exists(&self, path: &Path) -> Result<bool>;

    /// List all available assets matching a pattern
    async fn list(&self, pattern: &str) -> Result<Vec<std::path::PathBuf>>;
}

/// Trait for configuration merging
pub trait ConfigMerge<T> {
    /// Merge this configuration with another, with self taking precedence
    fn merge_with(&self, other: &T) -> T;
}

/// Trait for framework components
#[async_trait]
pub trait Component: Initialize + Send + Sync {
    /// Component name
    fn name(&self) -> &str;

    /// Component dependencies
    fn dependencies(&self) -> Vec<String> {
        Vec::new()
    }

    /// Start the component
    async fn start(&mut self) -> Result<()>;

    /// Stop the component
    async fn stop(&mut self) -> Result<()>;

    /// Get component status
    fn status(&self) -> ComponentStatus;
}

/// Status of a framework component
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ComponentStatus {
    Uninitialized,
    Initialized,
    Running,
    Stopped,
    Error(String),
}

/// Trait for buildable assets
pub trait Buildable {
    type Output;

    /// Build the asset
    fn build(&self) -> Result<Self::Output>;

    /// Check if the asset needs rebuilding
    fn needs_rebuild(&self) -> bool {
        true
    }
}
