// SPDX-License-Identifier: Apache-2.0

//! Delta push / ack / reject / collection-purged messages.

use serde::{Deserialize, Serialize};

use crate::sync::compensation::CompensationHint;

/// Delta push message (client → server, 0x10).
#[derive(
    Debug, Clone, Serialize, Deserialize, zerompk::ToMessagePack, zerompk::FromMessagePack,
)]
pub struct DeltaPushMsg {
    /// Collection the delta applies to.
    pub collection: String,
    /// Document ID.
    pub document_id: String,
    /// Loro CRDT delta bytes.
    pub delta: Vec<u8>,
    /// Client's peer ID (for CRDT identity).
    pub peer_id: u64,
    /// Per-mutation unique ID for dedup.
    pub mutation_id: u64,
    /// CRC32C checksum of `delta` bytes for integrity verification.
    /// Computed by sender, validated by receiver. 0 for legacy clients.
    #[serde(default)]
    pub checksum: u32,
    /// Device-assigned valid-time for the mutation (ms since Unix epoch).
    ///
    /// Populated by offline-capable clients so Origin can preserve the
    /// application's notion of "when did this fact take effect" independently
    /// of the Origin-assigned `system_from_ms`. `None` means the client did
    /// not supply a valid-time — Origin will use `system_from_ms` as the
    /// default valid-from.
    #[serde(default)]
    pub device_valid_time_ms: Option<i64>,
}

/// Delta acknowledgment (server → client, 0x11).
#[derive(
    Debug, Clone, Serialize, Deserialize, zerompk::ToMessagePack, zerompk::FromMessagePack,
)]
pub struct DeltaAckMsg {
    /// Mutation ID being acknowledged.
    pub mutation_id: u64,
    /// Server-assigned LSN for this mutation.
    pub lsn: u64,
    /// Absolute clock-skew between `device_valid_time_ms` and the Origin
    /// wall clock at commit, in milliseconds. `None` when the client did
    /// not supply a device valid-time, or when skew was within tolerance
    /// (≤ 24h). Populated so clients can surface a warning UX.
    #[serde(default)]
    pub clock_skew_warning_ms: Option<i64>,
}

/// Delta rejection (server → client, 0x12).
#[derive(
    Debug, Clone, Serialize, Deserialize, zerompk::ToMessagePack, zerompk::FromMessagePack,
)]
pub struct DeltaRejectMsg {
    /// Mutation ID being rejected.
    pub mutation_id: u64,
    /// Reason for rejection.
    pub reason: String,
    /// Compensation hints for the client.
    pub compensation: Option<CompensationHint>,
}

/// Collection purged notification (server → client, 0x14).
///
/// Emitted when Origin hard-deletes a collection (retention window
/// expired after `DROP COLLECTION` or explicit `DROP COLLECTION ... PURGE`).
/// The receiving Lite client must:
///
/// 1. Drop all local Loro CRDT state for the collection.
/// 2. Remove the collection's redb record.
/// 3. Terminate any active shape subscriptions or streaming consumers
///    sourced from the collection.
/// 4. Fire the `on_collection_purged` client-trait callback.
///
/// `purge_lsn` is the Origin WAL LSN at which the hard-delete committed.
/// Clients persist it so that on reconnect they can replay any purge
/// events that landed while they were offline by querying
/// `_system.dropped_collections` / purge event log at LSN > last_seen.
#[derive(
    Debug, Clone, Serialize, Deserialize, zerompk::ToMessagePack, zerompk::FromMessagePack,
)]
pub struct CollectionPurgedMsg {
    /// Numeric tenant ID the collection belonged to.
    pub tenant_id: u64,
    /// Collection name.
    pub name: String,
    /// Origin WAL LSN at which the hard-delete was committed.
    pub purge_lsn: u64,
}
