use async_trait::async_trait;
use anyhow::Result;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::domain::entity::FileComment;
use crate::infrastructure::persistence::FileCommentRepository;
use super::CommandHandler;
#[deprecated(since = "0.2.0", note = "Use CommandHandler<C> trait instead")]
#[async_trait]
pub trait FileCommentCommand: Send + Sync {
type Output;
async fn execute(&self) -> Result<Self::Output>;
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateFileCommentCommand {
pub file_id: Uuid,
pub user_id: Uuid,
pub parent_id: Option<Uuid>,
pub content: String,
pub annotation_region: Option<serde_json::Value>,
pub mentions: Vec<Uuid>,
pub resolved: bool,
pub resolved_by: Option<Uuid>,
pub resolved_at: Option<DateTime<Utc>>,
pub status: CommentStatus,
pub metadata: serde_json::Value,
}
pub struct CreateFileCommentHandler<R: FileCommentRepository> {
repository: std::sync::Arc<R>,
}
impl<R: FileCommentRepository> CreateFileCommentHandler<R> {
pub fn new(repository: std::sync::Arc<R>) -> Self {
Self { repository }
}
}
#[async_trait]
impl<R: FileCommentRepository + 'static> CommandHandler<CreateFileCommentCommand> for CreateFileCommentHandler<R> {
type Output = FileComment;
async fn handle(&self, cmd: CreateFileCommentCommand) -> Result<Self::Output> {
let entity = FileComment::builder()
.id(Uuid::new_v4().to_string())
.file_id(cmd.file_id)
.user_id(cmd.user_id)
.parent_id(cmd.parent_id)
.content(cmd.content)
.annotation_region(cmd.annotation_region)
.mentions(cmd.mentions)
.resolved(cmd.resolved)
.resolved_by(cmd.resolved_by)
.resolved_at(cmd.resolved_at)
.status(cmd.status)
.metadata(cmd.metadata)
.build()?;
self.repository.save(&entity).await
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateFileCommentCommand {
pub id: String,
pub file_id: Option<Uuid>,
pub user_id: Option<Uuid>,
pub parent_id: Option<Uuid>,
pub content: Option<String>,
pub annotation_region: Option<serde_json::Value>,
pub mentions: Option<Vec<Uuid>>,
pub resolved: Option<bool>,
pub resolved_by: Option<Uuid>,
pub resolved_at: Option<DateTime<Utc>>,
pub status: Option<CommentStatus>,
pub metadata: Option<serde_json::Value>,
}
pub struct UpdateFileCommentHandler<R: FileCommentRepository> {
repository: std::sync::Arc<R>,
}
impl<R: FileCommentRepository> UpdateFileCommentHandler<R> {
pub fn new(repository: std::sync::Arc<R>) -> Self {
Self { repository }
}
}
#[async_trait]
impl<R: FileCommentRepository + 'static> CommandHandler<UpdateFileCommentCommand> for UpdateFileCommentHandler<R> {
type Output = Option<FileComment>;
async fn handle(&self, cmd: UpdateFileCommentCommand) -> Result<Self::Output> {
let existing = self.repository.find_by_id(&cmd.id).await?;
let Some(mut entity) = existing else {
return Ok(None);
};
if let Some(value) = cmd.file_id {
entity.file_id = value;
}
if let Some(value) = cmd.user_id {
entity.user_id = value;
}
entity.parent_id = cmd.parent_id;
if let Some(value) = cmd.content {
entity.content = value;
}
entity.annotation_region = cmd.annotation_region;
if let Some(value) = cmd.mentions {
entity.mentions = value;
}
if let Some(value) = cmd.resolved {
entity.resolved = value;
}
entity.resolved_by = cmd.resolved_by;
entity.resolved_at = cmd.resolved_at;
if let Some(value) = cmd.status {
entity.status = value;
}
if let Some(value) = cmd.metadata {
entity.metadata = value;
}
self.repository.update(&cmd.id, &entity).await
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeleteFileCommentCommand {
pub id: String,
pub hard_delete: bool,
}
pub struct DeleteFileCommentHandler<R: FileCommentRepository> {
repository: std::sync::Arc<R>,
}
impl<R: FileCommentRepository> DeleteFileCommentHandler<R> {
pub fn new(repository: std::sync::Arc<R>) -> Self {
Self { repository }
}
}
#[async_trait]
impl<R: FileCommentRepository + 'static> CommandHandler<DeleteFileCommentCommand> for DeleteFileCommentHandler<R> {
type Output = bool;
async fn handle(&self, cmd: DeleteFileCommentCommand) -> Result<Self::Output> {
if cmd.hard_delete {
self.repository.delete(&cmd.id).await
} else {
self.repository.soft_delete(&cmd.id).await
}
}
}