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

use super::{BlockId, ChangeId};

/// A tracked change extracted from the DOCX review layer.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct TrackedChange {
    /// Stable identifier for this change in the normalized model.
    pub id: ChangeId,
    /// Semantic kind of tracked change.
    pub kind: TrackedChangeKind,
    /// Change author.
    pub author: Option<String>,
    /// Change timestamp.
    pub date: Option<DateTime<Utc>>,
    /// Blocks affected by this change.
    pub block_ids: Vec<BlockId>,
    /// Human-friendly excerpt of the change when available.
    pub excerpt: Option<String>,
    /// Shared move identifier linking move-from and move-to changes.
    pub move_pair_id: Option<String>,
    /// Raw OOXML revision ids preserved from the source document.
    pub raw_revision_ids: RawRevisionIds,
}

/// Semantic kind of tracked change.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub enum TrackedChangeKind {
    /// Inserted text visible in the current document view.
    Insert { text: String },
    /// Deleted text not visible in the current document view.
    Delete { text: String },
    /// A paired delete/insert replacement.
    Replacement { old_text: String, new_text: String },
    /// Text moved from its original location.
    MoveFrom { text: String },
    /// Text moved to its new location.
    MoveTo { text: String },
    /// A formatting-only change without textual insertion or deletion.
    Format { previous_props_summary: String },
}

/// Raw OOXML revision ids attached to a tracked change.
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct RawRevisionIds {
    /// Raw id of an insert revision.
    pub insert: Option<String>,
    /// Raw id of a delete revision.
    pub delete: Option<String>,
    /// Raw id of a move-from revision.
    pub move_from: Option<String>,
    /// Raw id of a move-to revision.
    pub move_to: Option<String>,
    /// Raw id of a formatting revision.
    pub format: Option<String>,
}
