//! PageAggregate 构建器（Builder 模式）。
//!
//! 使用方法:
//! ```rust,ignore
//! let aggregate = PageAggregate::builder()
//!     .document_id("doc_1")
//!     .workspace_id("ws_demo")
//!     .title("我的页面")
//!     .build();
//! ```

use crate::page_aggregate::{
    PageAggregate, PageAggregateSource, PageBody, PageHead, PageIdentity, PageLayout, PageOptions,
    PagePermissions, PageStats, PageTree,
};
use serde_json::{to_value, Value};

/// PageAggregate 构建器。
///
/// 所有字段都有与当前 `build_page_aggregate_snapshot` 一致的默认值。
/// 使用 `build()` 方法消费 builder 并产出 `PageAggregate`。
#[derive(Debug)]
pub struct PageAggregateBuilder {
    document_id: String,
    workspace_id: String,
    source: PageAggregateSource,
    parent_id: Option<String>,
    path: Vec<String>,
    sidebar_tree_membership: Vec<String>,
    body_ref: Option<String>,
    title: String,
    updated_at: Value,
    read_only: bool,
    disable_download: bool,
    disable_copy: bool,
    wide_layout: bool,
    small_text: bool,
    layout_density: String,
    show_heading_numbers: bool,
    show_toc: bool,
    show_structure: bool,
    protect_editing: bool,
    show_word_count: bool,
    collapse_backlinks: bool,
    page_font: String,
    hide_child_pages: bool,
    show_block_ref_count: bool,
    embed_default_block_id: Value,
    content: Value,
    revision: Value,
    conflict_detection_key: Value,
    page_subtree: Value,
    word_count: u64,
    character_count: u64,
    block_count: u64,
    todo_total: u64,
    todo_done: u64,
}

impl PageAggregateBuilder {
    /// 创建新的构建器，所有字段使用与当前 `build_page_aggregate_snapshot` 一致的默认值。
    pub fn new() -> Self {
        Self {
            document_id: String::new(),
            workspace_id: "default".to_string(),
            source: PageAggregateSource::CompatMetaContentJoin,
            parent_id: None,
            path: Vec::new(),
            sidebar_tree_membership: vec!["page-tree".into(), "file-tree".into()],
            body_ref: None,
            title: "无标题".to_string(),
            updated_at: Value::Null,
            read_only: false,
            disable_download: false,
            disable_copy: false,
            wide_layout: false,
            small_text: false,
            layout_density: "normal".to_string(),
            show_heading_numbers: false,
            show_toc: false,
            show_structure: false,
            protect_editing: false,
            show_word_count: true,
            collapse_backlinks: false,
            page_font: "default".to_string(),
            hide_child_pages: false,
            show_block_ref_count: false,
            embed_default_block_id: Value::Null,
            content: Value::Null,
            revision: Value::Null,
            conflict_detection_key: Value::Null,
            page_subtree: Value::Null,
            word_count: 0,
            character_count: 0,
            block_count: 0,
            todo_total: 0,
            todo_done: 0,
        }
    }

    // ── Identity ──

    pub fn document_id(mut self, value: impl Into<String>) -> Self {
        self.document_id = value.into();
        self
    }

    pub fn workspace_id(mut self, value: impl Into<String>) -> Self {
        self.workspace_id = value.into();
        self
    }

    pub fn source(mut self, value: PageAggregateSource) -> Self {
        self.source = value;
        self
    }

    pub fn parent_id(mut self, value: Option<String>) -> Self {
        self.parent_id = value;
        self
    }

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

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

    pub fn body_ref(mut self, value: Option<String>) -> Self {
        self.body_ref = value;
        self
    }

    // ── Head ──

    pub fn title(mut self, value: impl Into<String>) -> Self {
        self.title = value.into();
        self
    }

    pub fn updated_at(mut self, value: Value) -> Self {
        self.updated_at = value;
        self
    }

    pub fn read_only(mut self, value: bool) -> Self {
        self.read_only = value;
        self
    }

    pub fn disable_download(mut self, value: bool) -> Self {
        self.disable_download = value;
        self
    }

    pub fn disable_copy(mut self, value: bool) -> Self {
        self.disable_copy = value;
        self
    }

    // ── Layout / PageOptions ──

    pub fn wide_layout(mut self, value: bool) -> Self {
        self.wide_layout = value;
        self
    }

    pub fn small_text(mut self, value: bool) -> Self {
        self.small_text = value;
        self
    }

    pub fn layout_density(mut self, value: impl Into<String>) -> Self {
        self.layout_density = value.into();
        self
    }

    pub fn show_heading_numbers(mut self, value: bool) -> Self {
        self.show_heading_numbers = value;
        self
    }

    pub fn show_toc(mut self, value: bool) -> Self {
        self.show_toc = value;
        self
    }

    pub fn show_structure(mut self, value: bool) -> Self {
        self.show_structure = value;
        self
    }

    pub fn protect_editing(mut self, value: bool) -> Self {
        self.protect_editing = value;
        self
    }

    pub fn show_word_count(mut self, value: bool) -> Self {
        self.show_word_count = value;
        self
    }

    pub fn collapse_backlinks(mut self, value: bool) -> Self {
        self.collapse_backlinks = value;
        self
    }

    pub fn page_font(mut self, value: impl Into<String>) -> Self {
        self.page_font = value.into();
        self
    }

    pub fn hide_child_pages(mut self, value: bool) -> Self {
        self.hide_child_pages = value;
        self
    }

    pub fn show_block_ref_count(mut self, value: bool) -> Self {
        self.show_block_ref_count = value;
        self
    }

    pub fn embed_default_block_id(mut self, value: Value) -> Self {
        self.embed_default_block_id = value;
        self
    }

    // ── Body ──

    pub fn content(mut self, value: Value) -> Self {
        self.content = value;
        self
    }

    pub fn revision(mut self, value: Value) -> Self {
        self.revision = value;
        self
    }

    pub fn conflict_detection_key(mut self, value: Value) -> Self {
        self.conflict_detection_key = value;
        self
    }

    // ── Tree ──

    pub fn page_subtree(mut self, value: Value) -> Self {
        self.page_subtree = value;
        self
    }

    // ── Stats ──

    pub fn word_count(mut self, value: u64) -> Self {
        self.word_count = value;
        self
    }

    pub fn character_count(mut self, value: u64) -> Self {
        self.character_count = value;
        self
    }

    pub fn block_count(mut self, value: u64) -> Self {
        self.block_count = value;
        self
    }

    pub fn todo_total(mut self, value: u64) -> Self {
        self.todo_total = value;
        self
    }

    pub fn todo_done(mut self, value: u64) -> Self {
        self.todo_done = value;
        self
    }

    // ── Build ──

    /// 消费 builder 并产出 `PageAggregate`。
    pub fn build(self) -> PageAggregate {
        let page_options = PageOptions {
            wide_layout: self.wide_layout,
            small_text: self.small_text,
            layout_density: self.layout_density,
            show_heading_numbers: self.show_heading_numbers,
            show_toc: self.show_toc,
            show_structure: self.show_structure,
            protect_editing: self.protect_editing,
            show_word_count: self.show_word_count,
            collapse_backlinks: self.collapse_backlinks,
            page_font: self.page_font,
            hide_child_pages: self.hide_child_pages,
            show_block_ref_count: self.show_block_ref_count,
            embed_default_block_id: self.embed_default_block_id,
        };
        let layout_options = to_value(&page_options).expect("PageOptions 序列化不应失败");
        let updated_at_text = self.updated_at.as_str().map(ToOwned::to_owned);
        let page_id = self.document_id.clone();
        PageAggregate {
            schema: "mnote.page_aggregate.v1".to_string(),
            projection_version: PageAggregate::VERSION,
            source: self.source,
            page_id,
            parent_id: self.parent_id,
            title: self.title.clone(),
            path: if self.path.is_empty() {
                vec![self.document_id.clone()]
            } else {
                self.path
            },
            sidebar_tree_membership: self.sidebar_tree_membership,
            body_ref: self.body_ref,
            layout_options,
            updated_at: updated_at_text,
            identity: PageIdentity {
                document_id: self.document_id,
                workspace_id: self.workspace_id,
            },
            head: PageHead {
                title: self.title,
                updated_at: self.updated_at,
                permissions: PagePermissions {
                    read_only: self.read_only,
                    disable_download: self.disable_download,
                    disable_copy: self.disable_copy,
                },
            },
            layout: PageLayout { page_options },
            body: PageBody {
                content: self.content,
                revision: self.revision,
                conflict_detection_key: self.conflict_detection_key,
            },
            tree: PageTree {
                page_subtree: self.page_subtree,
            },
            stats: PageStats {
                word_count: self.word_count,
                character_count: self.character_count,
                block_count: self.block_count,
                todo_total: self.todo_total,
                todo_done: self.todo_done,
            },
        }
    }
}

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