use std::collections::HashMap;

#[cfg(any(target_arch = "wasm32", feature = "leptos-hydration"))]
use leptos::prelude::*;
use serde::{Deserialize, Serialize};

use crate::content::item::UnifiedContentItem;

/// Content configuration loaded from content-kinds.toml
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContentConfig {
    pub name: String,
    pub directory: String,
    pub enabled: bool,
    pub is_default: Option<bool>,
    pub specialized: Option<bool>,
    pub features: ContentFeatures,
}

impl Default for ContentConfig {
    fn default() -> Self {
        Self {
            name: "content".to_string(),
            directory: "content".to_string(),
            enabled: true,
            is_default: Some(true),
            specialized: None,
            features: ContentFeatures::default(),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContentFeatures {
    pub style_mode: String,
    pub style_css: String,
    pub use_feature: bool,
    pub use_categories: bool,
    pub use_tags: bool,
    pub use_emojis: bool,
    pub cta_view: String,
    // Pagination features
    pub default_page_size: Option<u32>,
    pub page_size_options: Option<Vec<u32>>,
    pub show_page_info: Option<bool>,
    pub pagination_style: Option<String>,
    // Optional specialized features
    pub show_difficulty: Option<bool>,
    pub show_duration: Option<bool>,
    pub show_prerequisites: Option<bool>,
}

impl Default for ContentFeatures {
    fn default() -> Self {
        Self {
            style_mode: "grid".to_string(),
            style_css: "content-default".to_string(),
            use_feature: false,
            use_categories: true,
            use_tags: true,
            use_emojis: false,
            cta_view: "DefaultCTAView".to_string(),
            default_page_size: Some(12),
            page_size_options: Some(vec![6, 12, 24, 48]),
            show_page_info: Some(true),
            pagination_style: Some("numbered".to_string()),
            show_difficulty: None,
            show_duration: None,
            show_prerequisites: None,
        }
    }
}

/// Metadata for content items
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContentMetadata {
    pub id: String,
    pub title: String,
    pub slug: String,
    pub language: String,
    pub content_kind: String,
    pub categories: Vec<String>,
    pub tags: Vec<String>,
    pub emoji: Option<String>,
    pub featured: bool,
    pub created_at: String,
    pub updated_at: Option<String>,
}

/// Validation errors for content
#[derive(Debug, Clone)]
pub struct ValidationError {
    pub field: String,
    pub message: String,
}

/// Interaction types for content behavior
#[derive(Debug, Clone)]
pub enum InteractionType {
    Click,
    View,
    Share,
    Bookmark,
    Custom(String),
}

/// Content actions available for specific content
#[derive(Debug, Clone)]
pub struct ContentAction {
    pub id: String,
    pub label: String,
    pub action_type: String,
    pub enabled: bool,
}

/// Load modes for content resolution
#[derive(Debug, Clone, PartialEq)]
pub enum LoadMode {
    Direct, // Direct URL access
    SPA,    // SPA navigation
}

/// Content resolution result
#[derive(Debug, Clone)]
pub struct ContentResolution {
    pub content_type: String,
    pub language: String,
    pub path: String,
    pub metadata: Option<ContentMetadata>,
}

/// Core trait that all content items must implement
///
/// This trait provides the essential interface for all content types,
/// supporting the configuration-driven, language-agnostic architecture.
pub trait ContentItemTrait {
    /// Unique identifier for the content item
    fn id(&self) -> &str;

    /// Display title of the content
    fn title(&self) -> &str;

    /// Content type (blog, recipes, etc.) - matches content-kinds.toml
    fn content_type(&self) -> &str;

    /// Language code (en, es, etc.)
    fn language(&self) -> &str;

    /// URL-safe slug for routing
    fn slug(&self) -> &str;

    /// Main content body
    fn content(&self) -> &str;

    /// Categories this content belongs to
    fn categories(&self) -> &[String];

    /// Tags associated with this content
    fn tags(&self) -> &[String];

    /// Whether this content is featured
    fn featured(&self) -> bool;

    /// Whether this content is published
    fn published(&self) -> bool;

    /// Creation timestamp
    fn created_at(&self) -> &str;

    /// Optional excerpt for display
    fn excerpt(&self) -> Option<&str> {
        None
    }

    /// Optional emoji for display
    fn emoji(&self) -> Option<&str> {
        None
    }

    /// Optional read time estimate
    fn read_time(&self) -> Option<&str> {
        None
    }

    /// Optional author information
    fn author(&self) -> Option<&str> {
        None
    }

    /// Optional update timestamp
    fn updated_at(&self) -> Option<&str> {
        None
    }
}

/// Base trait for content card items (for backward compatibility)
pub trait ContentCardItem {
    fn get_id(&self) -> &str;
    fn get_title(&self) -> &str;
    fn get_slug(&self) -> &str;
    fn get_categories(&self) -> &[String];
    fn get_tags(&self) -> &[String];
    fn get_emoji(&self) -> Option<&str>;
    fn is_featured(&self) -> bool;
}

/// Base trait for all content types
pub trait UnifiedContentItemTrait: ContentCardItem {
    #[cfg(any(target_arch = "wasm32", feature = "leptos-hydration"))]
    fn render(&self, config: &ContentConfig, language: &str) -> AnyView;
    fn validate(&self) -> Result<(), ValidationError>;
    fn get_metadata(&self) -> ContentMetadata;
}

/// Trait for specialized content with custom behavior
pub trait SpecializedContent: UnifiedContentItemTrait + std::fmt::Debug + Send + Sync {
    #[cfg(any(target_arch = "wasm32", feature = "leptos-hydration"))]
    fn custom_render(&self, config: &ContentConfig) -> AnyView;
    fn custom_behavior(&self) -> Box<dyn ContentBehavior>;
    fn supports_feature(&self, feature: &str) -> bool;

    // Add clone support for specialized content
    fn box_clone(&self) -> Box<dyn SpecializedContent>;
}

/// Trait for content-specific behavior
pub trait ContentBehavior {
    fn on_load(&self);
    fn on_interact(&self, interaction: InteractionType);
    fn get_actions(&self) -> Vec<ContentAction>;
}

// Custom Clone implementation for SpecializedContent
impl Clone for Box<dyn SpecializedContent> {
    fn clone(&self) -> Self {
        self.box_clone()
    }
}

/// Content kind registry
pub struct ContentKindRegistry {
    pub kinds: HashMap<String, ContentConfig>,
}

impl Default for ContentKindRegistry {
    fn default() -> Self {
        Self::new()
    }
}

impl ContentKindRegistry {
    pub fn new() -> Self {
        Self {
            kinds: HashMap::new(),
        }
    }

    pub fn register(&mut self, config: ContentConfig) {
        self.kinds.insert(config.name.clone(), config);
    }

    pub fn get(&self, name: &str) -> Option<&ContentConfig> {
        self.kinds.get(name)
    }

    pub fn get_config(&self, name: &str) -> Option<&ContentConfig> {
        self.kinds.get(name)
    }

    pub fn get_enabled(&self) -> Vec<&ContentConfig> {
        self.kinds.values().filter(|k| k.enabled).collect()
    }

    pub fn get_default(&self) -> Option<&ContentConfig> {
        self.kinds.values().find(|k| k.is_default.unwrap_or(false))
    }

    pub fn get_all_names(&self) -> Vec<&String> {
        self.kinds.keys().collect()
    }
}

// Using unified content system for default content
pub use crate::content::UnifiedContentItem as DefaultContent;

impl ContentCardItem for DefaultContent {
    fn get_id(&self) -> &str {
        self.id()
    }
    fn get_title(&self) -> &str {
        self.title()
    }
    fn get_slug(&self) -> &str {
        self.slug()
    }
    fn get_categories(&self) -> &[String] {
        self.categories()
    }
    fn get_tags(&self) -> &[String] {
        self.tags()
    }
    fn get_emoji(&self) -> Option<&str> {
        self.emoji()
    }
    fn is_featured(&self) -> bool {
        self.featured()
    }
}

impl UnifiedContentItemTrait for DefaultContent {
    #[cfg(any(target_arch = "wasm32", feature = "leptos-hydration"))]
    fn render(&self, _config: &ContentConfig, _language: &str) -> AnyView {
        let title = self.title().to_string();
        let content = self.content().to_string();
        view! {
            <article class="default-content">
                <h1>{title}</h1>
                <div class="content" inner_html=content></div>
            </article>
        }
        .into_any()
    }

    fn validate(&self) -> Result<(), ValidationError> {
        if self.title().is_empty() {
            return Err(ValidationError {
                field: "title".to_string(),
                message: "Title cannot be empty".to_string(),
            });
        }
        if self.slug().is_empty() {
            return Err(ValidationError {
                field: "slug".to_string(),
                message: "Slug cannot be empty".to_string(),
            });
        }
        Ok(())
    }

    fn get_metadata(&self) -> ContentMetadata {
        ContentMetadata {
            id: self.id().to_string(),
            title: self.title().to_string(),
            slug: self.slug().to_string(),
            language: self.language().to_string(),
            content_kind: "content".to_string(),
            categories: self.categories().to_vec(),
            tags: self.tags().to_vec(),
            emoji: self.emoji().map(|s| s.to_string()),
            featured: self.featured(),
            created_at: self.created_at().to_string(),
            updated_at: self.updated_at().map(|s| s.to_string()),
        }
    }
}
