use loco_rs::prelude::*;
use serde::{Deserialize, Serialize};

use crate::services::{subscriptions, worker_jobs};

pub struct NotificationDeliveryWorker {
    pub ctx: AppContext,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct NotificationDeliveryWorkerArgs {
    pub delivery_id: i32,
    #[serde(default)]
    pub job_id: Option<i32>,
}

#[async_trait]
impl BackgroundWorker<NotificationDeliveryWorkerArgs> for NotificationDeliveryWorker {
    fn build(ctx: &AppContext) -> Self {
        Self { ctx: ctx.clone() }
    }

    async fn perform(&self, args: NotificationDeliveryWorkerArgs) -> Result<()> {
        if let Some(job_id) = args.job_id {
            if !worker_jobs::begin_job_execution(&self.ctx, job_id).await? {
                return Ok(());
            }

            match subscriptions::process_delivery(&self.ctx, args.delivery_id).await {
                Ok(_) => {
                    worker_jobs::mark_job_succeeded(
                        &self.ctx,
                        job_id,
                        Some(serde_json::json!({ "delivery_id": args.delivery_id })),
                    )
                    .await?;
                    Ok(())
                }
                Err(error) => {
                    worker_jobs::mark_job_failed(&self.ctx, job_id, error.to_string()).await?;
                    Err(error)
                }
            }
        } else {
            subscriptions::process_delivery(&self.ctx, args.delivery_id).await
        }
    }
}
