use sea_orm::{
    ActiveModelTrait, ColumnTrait, DatabaseConnection, EntityTrait, PaginatorTrait, QueryFilter,
    QueryOrder, Set,
};
use serde_json::json;
use std::sync::Arc;
use tokio::sync::mpsc;
use tokio::time::{Duration, interval};
use tracing::{error, info, warn};
use uuid::Uuid;

use crate::entity::sea_orm_active_enums::{ChannelType, NotificationStatus, TargetType};
use crate::entity::{
    delivery_log, notification, recurrence_rule, reminder_offset, reminder_task, todo, user,
};
use crate::timer::recurrence::calculate_next_due;
use crate::timer::{SharedTimeWheel, TimerTask};

/// 重试退避时间（毫秒）
const BACKOFF_STEPS_MS: [i64; 5] = [
    60_000,          // 1 分钟
    5 * 60_000,      // 5 分钟
    15 * 60_000,     // 15 分钟
    60 * 60_000,     // 1 小时
    4 * 60 * 60_000, // 4 小时
];

/// 最大重试次数
const MAX_RETRY_ATTEMPTS: i32 = 5;

/// 锁超时时间（5 分钟）
const LOCK_TIMEOUT_MS: i64 = 5 * 60 * 1000;

/// 计算退避时间
fn calc_backoff_ms(attempt_no: i32) -> i64 {
    let index = (attempt_no - 1)
        .min(BACKOFF_STEPS_MS.len() as i32 - 1)
        .max(0) as usize;
    BACKOFF_STEPS_MS[index]
}

/// 默认的提醒偏移配置
struct DefaultOffset {
    offset_minutes: i32,
    channel_inapp: bool,
    channel_bark: bool,
}

impl Default for DefaultOffset {
    fn default() -> Self {
        Self {
            offset_minutes: 0,
            channel_inapp: true,
            channel_bark: false,
        }
    }
}

/// 通知推送 Worker
pub struct NotificationWorker {
    db: DatabaseConnection,
    time_wheel: SharedTimeWheel,
    bark_client: reqwest::Client,
}

impl NotificationWorker {
    pub fn new(db: DatabaseConnection, time_wheel: SharedTimeWheel) -> Self {
        Self {
            db,
            time_wheel,
            bark_client: reqwest::Client::new(),
        }
    }

    /// 启动 Worker
    /// 返回一个用于发送命令的 channel
    pub async fn start(self) -> mpsc::Sender<WorkerCommand> {
        let (tx, mut rx) = mpsc::channel::<WorkerCommand>(1000);

        let worker = Arc::new(self);

        // 时间轮 tick 任务
        let tick_worker = Arc::clone(&worker);
        tokio::spawn(async move {
            let mut ticker = interval(Duration::from_secs(1));
            loop {
                ticker.tick().await;
                let tasks = tick_worker.time_wheel.tick().await;
                for task in tasks {
                    if let Err(e) = tick_worker.execute_notification(task.notification_id).await {
                        error!(
                            "Failed to execute notification {}: {}",
                            task.notification_id, e
                        );
                    }
                }
            }
        });

        // 定期从数据库加载待处理通知
        let load_worker = Arc::clone(&worker);
        tokio::spawn(async move {
            let mut ticker = interval(Duration::from_secs(60)); // 每分钟检查一次
            loop {
                ticker.tick().await;
                if let Err(e) = load_worker.load_pending_notifications().await {
                    error!("Failed to load pending notifications: {}", e);
                }
            }
        });

        // 命令处理
        let cmd_worker = Arc::clone(&worker);
        tokio::spawn(async move {
            while let Some(cmd) = rx.recv().await {
                match cmd {
                    WorkerCommand::ScheduleNotification {
                        notification_id,
                        trigger_at,
                    } => {
                        let task = TimerTask {
                            id: Uuid::new_v4(),
                            notification_id,
                            trigger_at,
                        };
                        cmd_worker.time_wheel.add_task(task).await;
                    }
                    WorkerCommand::CancelNotification { notification_id } => {
                        // 标记数据库中的通知为取消状态
                        if let Err(e) = cmd_worker.cancel_notification(notification_id).await {
                            error!("Failed to cancel notification {}: {}", notification_id, e);
                        }
                    }
                    WorkerCommand::GenerateNotifications {
                        target_type,
                        target_id,
                    } => {
                        if let Err(e) = cmd_worker
                            .generate_notifications(target_type.clone(), target_id)
                            .await
                        {
                            error!(
                                "Failed to generate notifications for {:?}/{}: {}",
                                target_type, target_id, e
                            );
                        }
                    }
                }
            }
        });

        tx
    }

    /// 从数据库加载待处理的通知到时间轮
    async fn load_pending_notifications(
        &self,
    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        let now = chrono::Utc::now().fixed_offset();
        let future_limit = now + chrono::Duration::hours(25); // 加载未来25小时的通知
        let expired_lock = now - chrono::Duration::milliseconds(LOCK_TIMEOUT_MS);

        // 查找待处理的通知（包括锁超时的）
        let notifications = notification::Entity::find()
            .filter(notification::Column::Status.eq(NotificationStatus::Pending))
            .filter(notification::Column::TriggerAt.lte(future_limit))
            .filter(
                sea_orm::Condition::any()
                    .add(notification::Column::LockedAt.is_null())
                    .add(notification::Column::LockedAt.lt(expired_lock)),
            )
            .order_by_asc(notification::Column::TriggerAt)
            .all(&self.db)
            .await?;

        info!(
            "Loading {} pending notifications into time wheel",
            notifications.len()
        );

        for notif in notifications {
            let trigger_at = notif.trigger_at.timestamp();
            let task = TimerTask {
                id: Uuid::new_v4(),
                notification_id: notif.id,
                trigger_at,
            };
            self.time_wheel.add_task(task).await;
        }

        Ok(())
    }

    /// 执行通知推送
    async fn execute_notification(
        &self,
        notification_id: Uuid,
    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        // 获取通知
        let notif = notification::Entity::find_by_id(notification_id)
            .one(&self.db)
            .await?
            .ok_or("Notification not found")?;

        // 检查状态
        if notif.status != NotificationStatus::Pending {
            warn!("Notification {} is not pending, skipping", notification_id);
            return Ok(());
        }

        let now = chrono::Utc::now().fixed_offset();

        // 锁定通知（防止重复处理）
        let mut active: notification::ActiveModel = notif.clone().into();
        active.status = Set(NotificationStatus::Queued);
        active.locked_at = Set(Some(now));
        active.updated_at = Set(now);
        active.update(&self.db).await?;

        // 获取当前尝试次数
        let last_log = delivery_log::Entity::find()
            .filter(delivery_log::Column::NotificationId.eq(notification_id))
            .order_by_desc(delivery_log::Column::AttemptNo)
            .one(&self.db)
            .await?;
        let attempt_no = last_log.map(|l| l.attempt_no + 1).unwrap_or(1);

        // 获取接收者信息
        let recipient = user::Entity::find_by_id(notif.recipient_id)
            .one(&self.db)
            .await?
            .ok_or("Recipient not found")?;

        // 根据渠道发送通知
        let result: Result<(), String> = match notif.channel {
            ChannelType::Inapp => {
                // 应用内通知：只需要更新状态即可
                Ok(())
            }
            ChannelType::Bark => {
                if !recipient.bark_enabled {
                    Err("bark_disabled".to_string())
                } else if let Some(bark_url) = &recipient.bark_url {
                    // 获取 offset 配置（如果有）
                    let offset = if let Some(offset_id) = notif.offset_id {
                        reminder_offset::Entity::find_by_id(offset_id)
                            .one(&self.db)
                            .await
                            .ok()
                            .flatten()
                    } else {
                        None
                    };

                    // 获取目标详情
                    match self.get_notification_content(&notif).await {
                        Ok((default_title, default_body)) => {
                            // 使用 offset 中的自定义参数，如果没有则使用默认值
                            let title = offset
                                .as_ref()
                                .and_then(|o| o.bark_title.clone())
                                .unwrap_or(default_title);
                            let subtitle = offset.as_ref().and_then(|o| o.bark_subtitle.clone());
                            let body_or_markdown = offset
                                .as_ref()
                                .and_then(|o| o.bark_body_markdown.clone())
                                .or(Some(default_body));
                            let level = offset.as_ref().and_then(|o| o.bark_level.clone());
                            let icon = offset
                                .as_ref()
                                .and_then(|o| o.bark_icon.clone())
                                .or_else(|| recipient.avatar.clone());
                            tracing::info!("Sending Bark notification with icon: {:?}", icon);
                            self.send_bark_notification(
                                bark_url,
                                &title,
                                subtitle.as_deref(),
                                body_or_markdown.as_deref(),
                                level.as_deref(),
                                icon.as_deref(),
                                offset
                                    .as_ref()
                                    .and_then(|o| o.bark_body_markdown.as_ref())
                                    .is_some(),
                            )
                            .await
                            .map_err(|e| e.to_string())
                        }
                        Err(e) => Err(e.to_string()),
                    }
                } else {
                    Err("no_bark_url".to_string())
                }
            }
        };

        // 根据结果更新状态
        let target_type = notif.target_type.clone();
        let target_id = notif.target_id;
        let channel = notif.channel.clone();
        let original_trigger_at = notif.trigger_at;

        match &result {
            Ok(_) => {
                // 发送成功
                let mut active: notification::ActiveModel = notif.into();
                active.status = Set(NotificationStatus::Sent);
                active.sent_at = Set(Some(now));
                active.locked_at = Set(None);
                active.updated_at = Set(now);
                active.update(&self.db).await?;

                // 记录成功日志
                self.create_delivery_log(
                    notification_id,
                    attempt_no,
                    channel,
                    NotificationStatus::Sent,
                    None,
                )
                .await?;

                // 检查是否需要推进周期
                self.check_and_advance_recurrence(target_type, target_id)
                    .await?;
            }
            Err(error_msg) => {
                // 发送失败，检查是否需要重试
                let should_retry = attempt_no < MAX_RETRY_ATTEMPTS;

                if should_retry {
                    // 计算重试时间
                    let backoff_ms = calc_backoff_ms(attempt_no);
                    let retry_at = now + chrono::Duration::milliseconds(backoff_ms);

                    let mut active: notification::ActiveModel = notif.into();
                    active.status = Set(NotificationStatus::Pending);
                    active.trigger_at = Set(retry_at);
                    active.locked_at = Set(None);
                    active.updated_at = Set(now);
                    active.update(&self.db).await?;

                    // 重新添加到时间轮
                    let task = TimerTask {
                        id: Uuid::new_v4(),
                        notification_id,
                        trigger_at: retry_at.timestamp(),
                    };
                    self.time_wheel.add_task(task).await;

                    info!(
                        "Notification {} scheduled for retry at {} (attempt {})",
                        notification_id, retry_at, attempt_no
                    );

                    // 记录重试日志
                    self.create_delivery_log(
                        notification_id,
                        attempt_no,
                        channel,
                        NotificationStatus::Pending,
                        Some(json!({ "message": error_msg })),
                    )
                    .await?;
                } else {
                    // 超过最大重试次数，标记失败
                    let mut active: notification::ActiveModel = notif.into();
                    active.status = Set(NotificationStatus::Failed);
                    active.trigger_at = Set(original_trigger_at); // 恢复原始 trigger_at
                    active.locked_at = Set(None);
                    active.updated_at = Set(now);
                    active.update(&self.db).await?;

                    error!(
                        "Notification {} failed after {} attempts: {}",
                        notification_id, attempt_no, error_msg
                    );

                    // 记录失败日志
                    self.create_delivery_log(
                        notification_id,
                        attempt_no,
                        channel,
                        NotificationStatus::Failed,
                        Some(json!({ "message": error_msg })),
                    )
                    .await?;
                }
            }
        }

        Ok(())
    }

    /// 创建投递日志
    async fn create_delivery_log(
        &self,
        notification_id: Uuid,
        attempt_no: i32,
        channel: ChannelType,
        status: NotificationStatus,
        response_meta: Option<serde_json::Value>,
    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        let log = delivery_log::ActiveModel {
            id: Set(Uuid::new_v4()),
            notification_id: Set(notification_id),
            attempt_no: Set(attempt_no),
            channel: Set(channel),
            status: Set(status),
            response_meta: Set(response_meta),
            created_at: Set(chrono::Utc::now().fixed_offset()),
        };
        log.insert(&self.db).await?;
        Ok(())
    }

    /// 检查目标是否有周期性规则，如果所有当前周期的通知都已处理，则推进到下一周期
    async fn check_and_advance_recurrence(
        &self,
        target_type: TargetType,
        target_id: Uuid,
    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        // 检查是否还有该目标的待处理通知
        let pending_count = notification::Entity::find()
            .filter(notification::Column::TargetType.eq(target_type.clone()))
            .filter(notification::Column::TargetId.eq(target_id))
            .filter(notification::Column::Status.eq(NotificationStatus::Pending))
            .count(&self.db)
            .await?;

        if pending_count > 0 {
            // 还有未处理的通知，不需要推进周期
            return Ok(());
        }

        // 获取目标及其循环规则
        match target_type {
            TargetType::Todo => {
                self.advance_todo_recurrence(target_id).await?;
            }
            TargetType::ReminderTask => {
                self.advance_reminder_task_recurrence(target_id).await?;
            }
        }

        Ok(())
    }

    /// 推进 Todo 到下一周期
    async fn advance_todo_recurrence(
        &self,
        todo_id: Uuid,
    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        let todo_item = todo::Entity::find_by_id(todo_id).one(&self.db).await?;

        let todo_item = match todo_item {
            Some(t) => t,
            None => return Ok(()), // Todo 已被删除
        };

        // 检查是否有循环规则
        let rule_id = match todo_item.recurrence_rule_id {
            Some(id) => id,
            None => return Ok(()), // 非周期性任务
        };

        let rule = recurrence_rule::Entity::find_by_id(rule_id)
            .one(&self.db)
            .await?;

        let rule = match rule {
            Some(r) => r,
            None => return Ok(()), // 规则已被删除
        };

        // 计算下一个 due_at
        let next_due = match calculate_next_due(&rule, todo_item.due_at) {
            Some(d) => d,
            None => {
                warn!("Failed to calculate next due for todo {}", todo_id);
                return Ok(());
            }
        };

        info!(
            "Advancing todo {} from {} to {}",
            todo_id, todo_item.due_at, next_due
        );

        // 更新 Todo 的 due_at 并重置打卡状态
        let mut active: todo::ActiveModel = todo_item.into();
        active.due_at = Set(next_due);
        active.is_checked_in = Set(false); // 重置打卡状态，开启下一周期的打卡
        active.updated_at = Set(chrono::Utc::now().fixed_offset());
        active.update(&self.db).await?;

        // 为下一周期生成通知
        self.generate_notifications(TargetType::Todo, todo_id)
            .await?;

        Ok(())
    }

    /// 推进 ReminderTask 到下一周期
    async fn advance_reminder_task_recurrence(
        &self,
        task_id: Uuid,
    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        let task = reminder_task::Entity::find_by_id(task_id)
            .one(&self.db)
            .await?;

        let task = match task {
            Some(t) => t,
            None => return Ok(()), // Task 已被删除
        };

        // 检查是否有循环规则
        let rule_id = match task.recurrence_rule_id {
            Some(id) => id,
            None => return Ok(()), // 非周期性任务
        };

        let rule = recurrence_rule::Entity::find_by_id(rule_id)
            .one(&self.db)
            .await?;

        let rule = match rule {
            Some(r) => r,
            None => return Ok(()), // 规则已被删除
        };

        // 计算下一个 due_at
        let next_due = match calculate_next_due(&rule, task.due_at) {
            Some(d) => d,
            None => {
                warn!("Failed to calculate next due for reminder_task {}", task_id);
                return Ok(());
            }
        };

        info!(
            "Advancing reminder_task {} from {} to {}",
            task_id, task.due_at, next_due
        );

        // 更新 ReminderTask 的 due_at
        let mut active: reminder_task::ActiveModel = task.into();
        active.due_at = Set(next_due);
        active.updated_at = Set(chrono::Utc::now().fixed_offset());
        active.update(&self.db).await?;

        // 为下一周期生成通知
        self.generate_notifications(TargetType::ReminderTask, task_id)
            .await?;

        Ok(())
    }

    /// 获取通知内容
    async fn get_notification_content(
        &self,
        notif: &notification::Model,
    ) -> Result<(String, String), Box<dyn std::error::Error + Send + Sync>> {
        match notif.target_type {
            TargetType::Todo => {
                let todo = todo::Entity::find_by_id(notif.target_id)
                    .one(&self.db)
                    .await?
                    .ok_or("Todo not found")?;
                Ok((todo.title, todo.description.unwrap_or_default()))
            }
            TargetType::ReminderTask => {
                let task = reminder_task::Entity::find_by_id(notif.target_id)
                    .one(&self.db)
                    .await?
                    .ok_or("ReminderTask not found")?;
                Ok((task.title, task.description.unwrap_or_default()))
            }
        }
    }

    /// 发送 Bark 通知
    async fn send_bark_notification(
        &self,
        bark_url: &str,
        title: &str,
        subtitle: Option<&str>,
        body: Option<&str>,
        level: Option<&str>,
        icon: Option<&str>,
        is_markdown: bool,
    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        // 构建 Bark 推送参数
        let mut payload = json!({
            "title": title,
            "group": "notify",
        });

        // 添加可选参数
        if let Some(sub) = subtitle {
            payload["subtitle"] = json!(sub);
        }

        // 如果是 markdown 格式，使用 markdown 字段；否则使用 body 字段
        if is_markdown {
            if let Some(content) = body {
                payload["markdown"] = json!(content);
            }
        } else if let Some(content) = body {
            payload["body"] = json!(content);
        }

        // 添加推送级别
        if let Some(lvl) = level {
            payload["level"] = json!(lvl);
        }

        // 添加图标
        if let Some(ic) = icon {
            payload["icon"] = json!(ic);
        }

        let response = self
            .bark_client
            .post(bark_url)
            .header("Content-Type", "application/json")
            .json(&payload)
            .timeout(Duration::from_secs(10))
            .send()
            .await?;

        if !response.status().is_success() {
            let status = response.status();
            let text = response.text().await.unwrap_or_default();
            return Err(format!("Bark API error: {} - {}", status, text).into());
        }

        info!("Bark notification sent successfully");
        Ok(())
    }

    /// 取消通知
    async fn cancel_notification(
        &self,
        notification_id: Uuid,
    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        let notif = notification::Entity::find_by_id(notification_id)
            .one(&self.db)
            .await?;

        if let Some(notif) = notif {
            if notif.status == NotificationStatus::Pending {
                let mut active: notification::ActiveModel = notif.into();
                active.status = Set(NotificationStatus::Failed);
                active.updated_at = Set(chrono::Utc::now().fixed_offset());
                active.update(&self.db).await?;
            }
        }

        Ok(())
    }

    /// 为目标生成通知
    /// 当创建或更新 Todo/ReminderTask 时调用
    pub async fn generate_notifications(
        &self,
        target_type: TargetType,
        target_id: Uuid,
    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        // 删除旧的 pending 通知
        notification::Entity::delete_many()
            .filter(notification::Column::TargetType.eq(target_type.clone()))
            .filter(notification::Column::TargetId.eq(target_id))
            .filter(notification::Column::Status.eq(NotificationStatus::Pending))
            .exec(&self.db)
            .await?;

        // 获取目标的截止时间和接收者
        let (due_at, recipient_ids) = match target_type {
            TargetType::Todo => {
                let todo = todo::Entity::find_by_id(target_id)
                    .one(&self.db)
                    .await?
                    .ok_or("Todo not found")?;
                (todo.due_at, vec![todo.owner_id])
            }
            TargetType::ReminderTask => {
                let task = reminder_task::Entity::find_by_id(target_id)
                    .one(&self.db)
                    .await?
                    .ok_or("ReminderTask not found")?;

                // 获取所有接收者
                use crate::entity::reminder_task_recipient;
                let recipients = reminder_task_recipient::Entity::find()
                    .filter(reminder_task_recipient::Column::TaskId.eq(target_id))
                    .all(&self.db)
                    .await?;

                let recipient_ids: Vec<Uuid> = recipients.into_iter().map(|r| r.user_id).collect();
                (task.due_at, recipient_ids)
            }
        };

        // 获取提醒偏移配置
        let db_offsets = reminder_offset::Entity::find()
            .filter(reminder_offset::Column::TargetType.eq(target_type.clone()))
            .filter(reminder_offset::Column::TargetId.eq(target_id))
            .all(&self.db)
            .await?;

        // 如果没有配置偏移，使用默认偏移
        // (offset_minutes, channel_inapp, channel_bark, offset_id)
        let offsets: Vec<(i32, bool, bool, Option<Uuid>)> = if db_offsets.is_empty() {
            let default = DefaultOffset::default();
            vec![(
                default.offset_minutes,
                default.channel_inapp,
                default.channel_bark,
                None, // No offset_id for default offset
            )]
        } else {
            db_offsets
                .iter()
                .map(|o| {
                    (
                        o.offset_minutes,
                        o.channel_inapp,
                        o.channel_bark,
                        Some(o.id),
                    )
                })
                .collect()
        };

        let now = chrono::Utc::now().fixed_offset();

        // 为每个接收者和每个偏移生成通知
        for recipient_id in &recipient_ids {
            // 获取接收者的通知偏好
            let user = user::Entity::find_by_id(*recipient_id)
                .one(&self.db)
                .await?;

            let (inapp_enabled, bark_enabled, has_bark_url) = match &user {
                Some(u) => (u.inapp_enabled, u.bark_enabled, u.bark_url.is_some()),
                None => continue, // 用户不存在，跳过
            };

            for (offset_minutes, channel_inapp, channel_bark, offset_id) in &offsets {
                let trigger_at = due_at - chrono::Duration::minutes(*offset_minutes as i64);

                // 跳过已过期的通知
                if trigger_at <= now {
                    continue;
                }

                // 生成 inapp 通知（检查用户是否启用）
                if *channel_inapp && inapp_enabled {
                    let notif = notification::ActiveModel {
                        id: Set(Uuid::new_v4()),
                        recipient_id: Set(*recipient_id),
                        target_type: Set(target_type.clone()),
                        target_id: Set(target_id),
                        trigger_at: Set(trigger_at),
                        channel: Set(ChannelType::Inapp),
                        status: Set(NotificationStatus::Pending),
                        locked_at: Set(None),
                        sent_at: Set(None),
                        read_at: Set(None),
                        created_at: Set(now),
                        updated_at: Set(now),
                        offset_id: Set(*offset_id),
                    };

                    if let Ok(created) = notif.insert(&self.db).await {
                        // 添加到时间轮
                        let task = TimerTask {
                            id: Uuid::new_v4(),
                            notification_id: created.id,
                            trigger_at: trigger_at.timestamp(),
                        };
                        self.time_wheel.add_task(task).await;
                    }
                }

                // 生成 bark 通知（检查用户是否启用且有 URL）
                if *channel_bark && bark_enabled && has_bark_url {
                    let notif = notification::ActiveModel {
                        id: Set(Uuid::new_v4()),
                        recipient_id: Set(*recipient_id),
                        target_type: Set(target_type.clone()),
                        target_id: Set(target_id),
                        trigger_at: Set(trigger_at),
                        channel: Set(ChannelType::Bark),
                        status: Set(NotificationStatus::Pending),
                        locked_at: Set(None),
                        sent_at: Set(None),
                        read_at: Set(None),
                        created_at: Set(now),
                        updated_at: Set(now),
                        offset_id: Set(*offset_id),
                    };

                    if let Ok(created) = notif.insert(&self.db).await {
                        // 添加到时间轮
                        let task = TimerTask {
                            id: Uuid::new_v4(),
                            notification_id: created.id,
                            trigger_at: trigger_at.timestamp(),
                        };
                        self.time_wheel.add_task(task).await;
                    }
                }
            }
        }

        info!(
            "Generated notifications for {:?}/{}",
            target_type, target_id
        );
        Ok(())
    }
}

/// Worker 命令
#[derive(Debug)]
pub enum WorkerCommand {
    /// 调度一个通知
    ScheduleNotification {
        notification_id: Uuid,
        trigger_at: i64,
    },
    /// 取消一个通知
    CancelNotification { notification_id: Uuid },
    /// 为目标生成通知
    GenerateNotifications {
        target_type: TargetType,
        target_id: Uuid,
    },
}
