use std::collections::HashMap;
use async_trait::async_trait;
use modkit_db::secure::DBRunner;
use modkit_macros::domain_model;
use modkit_security::AccessScope;
use time::OffsetDateTime;
use uuid::Uuid;
use crate::domain::error::DomainError;
use crate::domain::models::AttachmentSummary;
use crate::infra::db::entity::message::Model as MessageModel;
#[domain_model]
#[derive(Debug, Clone, Copy)]
pub struct SnapshotBoundary {
pub created_at: OffsetDateTime,
pub id: Uuid,
}
#[domain_model]
pub struct InsertUserMessageParams {
pub id: Uuid,
pub tenant_id: Uuid,
pub chat_id: Uuid,
pub request_id: Uuid,
pub content: String,
}
#[domain_model]
pub struct InsertAssistantMessageParams {
pub id: Uuid,
pub tenant_id: Uuid,
pub chat_id: Uuid,
pub request_id: Uuid,
pub content: String,
pub input_tokens: Option<i64>,
pub output_tokens: Option<i64>,
pub cache_read_input_tokens: Option<i64>,
pub cache_write_input_tokens: Option<i64>,
pub reasoning_tokens: Option<i64>,
pub model: Option<String>,
pub provider_response_id: Option<String>,
}
#[async_trait]
#[allow(dead_code, clippy::too_many_arguments)]
pub trait MessageRepository: Send + Sync {
async fn insert_user_message<C: DBRunner>(
&self,
runner: &C,
scope: &AccessScope,
params: InsertUserMessageParams,
) -> Result<MessageModel, DomainError>;
async fn insert_assistant_message<C: DBRunner>(
&self,
runner: &C,
scope: &AccessScope,
params: InsertAssistantMessageParams,
) -> Result<MessageModel, DomainError>;
async fn find_user_message_by_request_id<C: DBRunner>(
&self,
runner: &C,
scope: &AccessScope,
chat_id: Uuid,
request_id: Uuid,
) -> Result<Option<MessageModel>, DomainError>;
async fn find_by_chat_and_request_id<C: DBRunner>(
&self,
runner: &C,
scope: &AccessScope,
chat_id: Uuid,
request_id: Uuid,
) -> Result<Vec<MessageModel>, DomainError>;
async fn get_by_chat<C: DBRunner>(
&self,
runner: &C,
scope: &AccessScope,
msg_id: Uuid,
chat_id: Uuid,
) -> Result<Option<MessageModel>, DomainError>;
async fn list_by_chat<C: DBRunner>(
&self,
runner: &C,
scope: &AccessScope,
chat_id: Uuid,
query: &modkit_odata::ODataQuery,
) -> Result<modkit_odata::Page<MessageModel>, DomainError>;
async fn batch_attachment_summaries<C: DBRunner>(
&self,
runner: &C,
scope: &AccessScope,
chat_id: Uuid,
message_ids: &[Uuid],
) -> Result<HashMap<Uuid, Vec<AttachmentSummary>>, DomainError>;
async fn snapshot_boundary<C: DBRunner>(
&self,
runner: &C,
scope: &AccessScope,
chat_id: Uuid,
) -> Result<Option<SnapshotBoundary>, DomainError>;
async fn recent_for_context<C: DBRunner>(
&self,
runner: &C,
scope: &AccessScope,
chat_id: Uuid,
limit: u32,
boundary: Option<SnapshotBoundary>,
) -> Result<Vec<MessageModel>, DomainError>;
async fn soft_delete_by_request_id<C: DBRunner>(
&self,
runner: &C,
scope: &AccessScope,
chat_id: Uuid,
request_id: Uuid,
) -> Result<u64, DomainError>;
async fn last_assistant_token_counts<C: DBRunner>(
&self,
runner: &C,
scope: &AccessScope,
chat_id: Uuid,
) -> Result<Option<(i64, i64)>, DomainError>;
async fn find_latest_message<C: DBRunner>(
&self,
runner: &C,
scope: &AccessScope,
chat_id: Uuid,
) -> Result<Option<crate::domain::repos::SummaryFrontier>, DomainError>;
async fn fetch_messages_in_range<C: DBRunner>(
&self,
runner: &C,
scope: &AccessScope,
chat_id: Uuid,
base_frontier: Option<&crate::domain::repos::SummaryFrontier>,
target_frontier: &crate::domain::repos::SummaryFrontier,
) -> Result<Vec<MessageModel>, DomainError>;
async fn mark_messages_compressed<C: DBRunner>(
&self,
runner: &C,
scope: &AccessScope,
chat_id: Uuid,
base_frontier: Option<&crate::domain::repos::SummaryFrontier>,
target_frontier: &crate::domain::repos::SummaryFrontier,
) -> Result<u64, DomainError>;
async fn recent_after_boundary<C: DBRunner>(
&self,
runner: &C,
scope: &AccessScope,
chat_id: Uuid,
lower_created_at: time::OffsetDateTime,
lower_id: Uuid,
limit: u32,
boundary: Option<SnapshotBoundary>,
) -> Result<Vec<MessageModel>, DomainError>;
}