use zeroize::Zeroizing;

/// Maximum number of message IDs to retain per session for replay detection.
///
/// Bounded to 1024 to cap per-session memory. Old entries are evicted FIFO
/// when the buffer is full (CHAT-002).
pub(crate) const MAX_SEEN_MESSAGE_IDS: usize = 1024;

/// Per-peer session state maintained by `ChatManager`.
///
/// All sensitive material (`shared_secret`) is wrapped in `Zeroizing` so it
/// is erased from memory when the session is dropped.
#[derive(Debug)]
pub struct PeerSession {
    /// The remote peer's sr25519 account ID (32 bytes).
    pub peer_account_id: [u8; 32],

    /// Symmetric session secret derived from ECDH + HKDF.
    ///
    /// Used as the AES-256-GCM key for all messages in this session.
    pub shared_secret: Zeroizing<[u8; 32]>,

    /// Session ID for messages we send (local → peer).
    pub out_session_id: [u8; 32],

    /// Session ID for messages the peer sends (peer → local).
    pub in_session_id: [u8; 32],

    /// Statement Store channel we post outbound messages on.
    pub request_channel: [u8; 32],

    /// Statement Store channel we post response/ack messages on.
    pub response_channel: [u8; 32],

    /// Statement Store channel the peer posts their messages on (we subscribe).
    pub peer_request_channel: [u8; 32],

    /// Statement Store channel the peer posts their acks on (we subscribe).
    pub peer_response_channel: [u8; 32],

    /// Ring buffer of recently seen message IDs for replay detection (CHAT-002).
    ///
    /// Bounded to `MAX_SEEN_MESSAGE_IDS` to prevent unbounded memory growth.
    /// Old entries are evicted FIFO when the buffer is full.
    /// Note: evicted IDs become re-acceptable — this is a known trade-off
    /// to prevent unbounded memory growth. The 1024 window covers ~17 minutes
    /// at 1 msg/sec, well beyond the Statement Store's 7-day TTL for any
    /// realistic message rate.
    pub(crate) seen_ids_order: std::collections::VecDeque<String>,
    /// O(1) lookup companion to `seen_ids_order`.
    pub(crate) seen_ids_set: std::collections::HashSet<String>,

    /// Current state of this conversation.
    pub state: ConversationState,

    /// Correlation ID of a pending outbound chat-request, if any.
    pub pending_request_id: Option<String>,
}

/// Lifecycle state of a peer conversation.
#[derive(Debug, Clone, PartialEq)]
pub enum ConversationState {
    /// No session has been established with this peer.
    None,
    /// We have sent a chat-request and are waiting for the peer to accept.
    RequestSent,
    /// We have received a chat-request from the peer and have not yet accepted.
    RequestReceived,
    /// Both sides have accepted — messages can flow freely.
    Active,
}
