use crate::audit::{ActorRef, AuditInfo, ChangeReason, RefLink, SourceKind};
use crate::ids::{
    AgentSessionId, AssetId, AssetVersionId, BlockId, CommandLogId, EventId, PageId, ReferenceId,
    TaskId, WorkspaceId,
};
use crate::time::Timestamp;
use crate::types::{Locale, Revision};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Workspace {
    pub workspace_id: WorkspaceId,
    pub slug: String,
    pub title: String,
    pub owner_actor_id: String,
    pub default_locale: Locale,
    pub storage_policy: String,
    pub sync_policy: String,
    pub feature_flags: Vec<String>,
    pub archived_at: Option<Timestamp>,
    pub audit: AuditInfo,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PageType {
    Note,
    Doc,
    DatabaseRecord,
    Inbox,
    Template,
    System,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PageStatus {
    Active,
    Archived,
    Deleted,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Page {
    pub page_id: PageId,
    pub workspace_id: WorkspaceId,
    pub parent_page_id: Option<PageId>,
    pub title: String,
    pub slug: String,
    pub icon: Option<String>,
    pub cover_asset_id: Option<AssetId>,
    pub body_root_block_id: Option<BlockId>,
    pub page_type: PageType,
    pub status: PageStatus,
    pub last_edited_at: Option<Timestamp>,
    pub last_edited_by: Option<ActorRef>,
    pub current_revision: Revision,
    pub audit: AuditInfo,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum BlockType {
    Paragraph,
    Heading,
    BulletedListItem,
    NumberedListItem,
    Todo,
    Quote,
    CodeBlock,
    Divider,
    Callout,
    PageReference,
    BlockReference,
    EmbedAsset,
    EmbedView,
    EmbedOnlyoffice,
    EmbedMindmap,
    EmbedTable,
    Custom(String),
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Block {
    pub block_id: BlockId,
    pub workspace_id: WorkspaceId,
    pub page_id: PageId,
    pub parent_block_id: Option<BlockId>,
    pub prev_block_id: Option<BlockId>,
    pub next_block_id: Option<BlockId>,
    pub sort_key: String,
    pub block_type: BlockType,
    pub content: String,
    pub props: Vec<(String, String)>,
    pub annotations: Vec<String>,
    pub status: String,
    pub revision: Revision,
    pub deleted_at: Option<Timestamp>,
    pub audit: AuditInfo,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AssetKind {
    Image,
    Office,
    Pdf,
    Audio,
    Video,
    Export,
    OcrDerived,
    Other(String),
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AssetStatus {
    Active,
    Archived,
    Deleted,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Asset {
    pub asset_id: AssetId,
    pub workspace_id: WorkspaceId,
    pub storage_key: String,
    pub original_name: String,
    pub mime_type: String,
    pub size_bytes: u64,
    pub checksum: Option<String>,
    pub origin: String,
    pub asset_kind: AssetKind,
    pub status: AssetStatus,
    pub latest_version_id: Option<AssetVersionId>,
    pub audit: AuditInfo,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AssetVersion {
    pub asset_version_id: AssetVersionId,
    pub asset_id: AssetId,
    pub version_no: u32,
    pub storage_key: String,
    pub checksum: Option<String>,
    pub derived_from_version_id: Option<AssetVersionId>,
    pub change_reason: Option<ChangeReason>,
    pub created_at: Timestamp,
    pub created_by: Option<ActorRef>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ReferenceKind {
    PageToPage,
    BlockToBlock,
    BlockToPage,
    BlockToAssetFragment,
    TaskToObject,
    External,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Reference {
    pub reference_id: ReferenceId,
    pub workspace_id: WorkspaceId,
    pub source_object_type: String,
    pub source_object_id: String,
    pub target_object_type: String,
    pub target_object_id: String,
    pub anchor: String,
    pub label: Option<String>,
    pub snippet: Option<String>,
    pub confidence: Option<String>,
    pub ref_kind: ReferenceKind,
    pub created_at: Timestamp,
    pub created_by: Option<ActorRef>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TaskType {
    Import,
    Ocr,
    Summary,
    Reindex,
    Sync,
    Transform,
    Other(String),
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TaskStatus {
    Pending,
    Running,
    Succeeded,
    Failed,
    Cancelled,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TaskPriority {
    Low,
    Normal,
    High,
    Critical,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Task {
    pub task_id: TaskId,
    pub workspace_id: WorkspaceId,
    pub title: String,
    pub description: Option<String>,
    pub task_type: TaskType,
    pub status: TaskStatus,
    pub priority: TaskPriority,
    pub assignee_actor_id: Option<String>,
    pub source_page_id: Option<PageId>,
    pub source_block_id: Option<BlockId>,
    pub input_payload: Option<String>,
    pub output_payload: Option<String>,
    pub due_at: Option<Timestamp>,
    pub completed_at: Option<Timestamp>,
    pub audit: AuditInfo,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AgentSession {
    pub agent_session_id: AgentSessionId,
    pub workspace_id: WorkspaceId,
    pub provider: String,
    pub model: String,
    pub initiator_actor_id: Option<String>,
    pub status: String,
    pub started_at: Timestamp,
    pub updated_at: Timestamp,
    pub ended_at: Option<Timestamp>,
    pub tool_policy: Option<String>,
    pub confirmation_policy: Option<String>,
    pub summary: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CommandStatus {
    Pending,
    Succeeded,
    Failed,
    Cancelled,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CommandLog {
    pub command_log_id: CommandLogId,
    pub workspace_id: WorkspaceId,
    pub command_name: String,
    pub actor: ActorRef,
    pub source: SourceKind,
    pub target_objects: Vec<RefLink>,
    pub payload_summary: String,
    pub refs: Vec<RefLink>,
    pub idempotency_key: Option<String>,
    pub dry_run: bool,
    pub status: CommandStatus,
    pub created_at: Timestamp,
    pub finished_at: Option<Timestamp>,
    pub error_code: Option<String>,
    pub error_message: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EventType {
    PageCreated,
    PageUpdated,
    BlockInserted,
    BlockMoved,
    BlockUpdated,
    BlockDeleted,
    AssetVersionAdded,
    ReferenceCreated,
    TaskUpdated,
    Other(String),
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DomainEvent {
    pub event_id: EventId,
    pub workspace_id: WorkspaceId,
    pub command_log_id: CommandLogId,
    pub aggregate_type: String,
    pub aggregate_id: String,
    pub event_type: EventType,
    pub before_revision: Option<Revision>,
    pub after_revision: Option<Revision>,
    pub payload_json: String,
    pub created_at: Timestamp,
}
