//! Content metadata and template structures

use std::collections::HashMap;

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;

use super::types::{ContentFormat, ContentState, ContentType};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContentQuery {
    pub content_type: Option<ContentType>,
    pub state: Option<ContentState>,
    pub author_id: Option<Uuid>,
    pub category: Option<String>,
    pub tags: Option<Vec<String>>,
    pub require_login: Option<bool>,
    pub date_from: Option<DateTime<Utc>>,
    pub date_to: Option<DateTime<Utc>>,
    pub search: Option<String>,
    pub limit: Option<i64>,
    pub offset: Option<i64>,
    pub sort_by: Option<String>,
    pub sort_order: Option<String>,
}

impl ContentQuery {
    pub fn new() -> Self {
        Self {
            content_type: None,
            state: None,
            author_id: None,
            category: None,
            tags: None,
            require_login: None,
            date_from: None,
            date_to: None,
            search: None,
            limit: None,
            offset: None,
            sort_by: None,
            sort_order: None,
        }
    }

    pub fn with_content_type(mut self, content_type: ContentType) -> Self {
        self.content_type = Some(content_type);
        self
    }

    pub fn with_state(mut self, state: ContentState) -> Self {
        self.state = Some(state);
        self
    }

    pub fn with_author(mut self, author_id: Uuid) -> Self {
        self.author_id = Some(author_id);
        self
    }

    pub fn with_category(mut self, category: String) -> Self {
        self.category = Some(category);
        self
    }

    pub fn with_tags(mut self, tags: Vec<String>) -> Self {
        self.tags = Some(tags);
        self
    }

    pub fn with_pagination(mut self, limit: i64, offset: i64) -> Self {
        self.limit = Some(limit);
        self.offset = Some(offset);
        self
    }

    pub fn with_search(mut self, search: String) -> Self {
        self.search = Some(search);
        self
    }

    pub fn published_only(mut self) -> Self {
        self.state = Some(ContentState::Published);
        self
    }

    pub fn public_only(mut self) -> Self {
        self.require_login = Some(false);
        self
    }
}

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

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContentMetadata {
    pub title: String,
    pub description: Option<String>,
    pub author: Option<String>,
    pub keywords: Vec<String>,
    pub canonical_url: Option<String>,
    pub og_title: Option<String>,
    pub og_description: Option<String>,
    pub og_image: Option<String>,
    pub twitter_title: Option<String>,
    pub twitter_description: Option<String>,
    pub twitter_image: Option<String>,
    pub schema_type: Option<String>,
    pub reading_time: Option<i32>,
    pub word_count: Option<i32>,
}

impl ContentMetadata {
    pub fn new(title: String) -> Self {
        Self {
            title,
            description: None,
            author: None,
            keywords: Vec::new(),
            canonical_url: None,
            og_title: None,
            og_description: None,
            og_image: None,
            twitter_title: None,
            twitter_description: None,
            twitter_image: None,
            schema_type: None,
            reading_time: None,
            word_count: None,
        }
    }

    pub fn with_description(mut self, description: String) -> Self {
        self.description = Some(description);
        self
    }

    pub fn with_author(mut self, author: String) -> Self {
        self.author = Some(author);
        self
    }

    pub fn with_keywords(mut self, keywords: Vec<String>) -> Self {
        self.keywords = keywords;
        self
    }

    pub fn with_og_data(
        mut self,
        title: String,
        description: String,
        image: Option<String>,
    ) -> Self {
        self.og_title = Some(title);
        self.og_description = Some(description);
        self.og_image = image;
        self
    }

    pub fn with_twitter_data(
        mut self,
        title: String,
        description: String,
        image: Option<String>,
    ) -> Self {
        self.twitter_title = Some(title);
        self.twitter_description = Some(description);
        self.twitter_image = image;
        self
    }

    pub fn estimate_reading_time(&mut self, content: &str) {
        let words = content.split_whitespace().count();
        self.word_count = Some(words as i32);
        // Average reading speed: 200 words per minute
        self.reading_time = Some(((words as f32 / 200.0).ceil() as i32).max(1));
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContentTemplate {
    pub name: String,
    pub description: Option<String>,
    pub container: String,
    pub default_content_type: ContentType,
    pub default_format: ContentFormat,
    pub required_fields: Vec<String>,
    pub optional_fields: Vec<String>,
    pub default_metadata: HashMap<String, String>,
    pub supports_comments: bool,
    pub supports_tags: bool,
    pub supports_categories: bool,
    pub require_login_default: bool,
}

impl ContentTemplate {
    pub fn new(name: String, container: String) -> Self {
        Self {
            name,
            description: None,
            container,
            default_content_type: ContentType::Page,
            default_format: ContentFormat::Markdown,
            required_fields: vec!["title".to_string(), "content".to_string()],
            optional_fields: Vec::new(),
            default_metadata: HashMap::new(),
            supports_comments: true,
            supports_tags: true,
            supports_categories: true,
            require_login_default: false,
        }
    }

    pub fn for_content_type(content_type_name: &str) -> Self {
        Self {
            name: format!("{} Content", content_type_name),
            description: Some(format!("Template for {} content", content_type_name)),
            container: format!("{}-container", content_type_name),
            default_content_type: ContentType::Article, // Generic content type
            default_format: ContentFormat::Markdown,
            required_fields: vec![
                "title".to_string(),
                "content".to_string(),
                "author".to_string(),
            ],
            optional_fields: vec!["excerpt".to_string(), "featured_image".to_string()],
            default_metadata: HashMap::new(),
            supports_comments: true,
            supports_tags: true,
            supports_categories: true,
            require_login_default: false,
        }
    }

    pub fn page_template() -> Self {
        Self {
            name: "Static Page".to_string(),
            description: Some("Template for static pages".to_string()),
            container: "page-container".to_string(),
            default_content_type: ContentType::Page,
            default_format: ContentFormat::Markdown,
            required_fields: vec!["title".to_string(), "content".to_string()],
            optional_fields: vec!["seo_title".to_string(), "seo_description".to_string()],
            default_metadata: HashMap::new(),
            supports_comments: false,
            supports_tags: false,
            supports_categories: false,
            require_login_default: false,
        }
    }

    pub fn blog_template() -> Self {
        Self {
            name: "Blog Post".to_string(),
            description: Some("Template for blog posts".to_string()),
            container: "blog-container".to_string(),
            default_content_type: ContentType::Blog,
            default_format: ContentFormat::Markdown,
            required_fields: vec![
                "title".to_string(),
                "content".to_string(),
                "author".to_string(),
            ],
            optional_fields: vec!["excerpt".to_string(), "featured_image".to_string()],
            default_metadata: HashMap::new(),
            supports_comments: true,
            supports_tags: true,
            supports_categories: true,
            require_login_default: false,
        }
    }

    pub fn documentation_template() -> Self {
        Self {
            name: "Documentation".to_string(),
            description: Some("Template for documentation pages".to_string()),
            container: "docs-container".to_string(),
            default_content_type: ContentType::Documentation,
            default_format: ContentFormat::Markdown,
            required_fields: vec!["title".to_string(), "content".to_string()],
            optional_fields: vec!["category".to_string()],
            default_metadata: HashMap::new(),
            supports_comments: false,
            supports_tags: true,
            supports_categories: true,
            require_login_default: false,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct MarkdownMetadata {
    pub title: Option<String>,
    pub subtitle: Option<String>,
    pub description: Option<String>,
    pub author: Option<String>,
    pub date: Option<String>,
    pub tags: Vec<String>,
    pub featured: bool,
    pub published: bool,
    pub language: String,
    pub slug: Option<String>,
    pub excerpt: Option<String>,
    pub read_time: Option<String>,
    pub category: Option<String>,
    pub difficulty: Option<String>,
}

impl Default for MarkdownMetadata {
    fn default() -> Self {
        Self {
            title: None,
            subtitle: None,
            description: None,
            author: None,
            date: None,
            tags: Vec::new(),
            featured: false,
            published: false,
            language: "en".to_string(),
            slug: None,
            excerpt: None,
            read_time: None,
            category: None,
            difficulty: None,
        }
    }
}
