use async_trait::async_trait;
use chrono::{DateTime, Utc};
use uuid::Uuid;

use crate::{error::JobResult, job::Job};

/// Primitive operations for job persistence
#[async_trait]
pub trait Datastore: Send + Sync {
    /// Insert a new job
    async fn insert_job(&self, job: Job) -> JobResult<Uuid>;

    /// Get a job by ID
    async fn get_job(&self, job_id: Uuid) -> JobResult<Option<Job>>;

    /// Get all jobs
    async fn get_all_jobs(&self) -> JobResult<Vec<Job>>;

    /// Update a job
    async fn update_job(&self, job: Job) -> JobResult<()>;

    /// Delete a job
    async fn delete_job(&self, job_id: Uuid) -> JobResult<()>;

    /// Atomically claim the next available job
    async fn claim_next_job(
        &self,
        locked_until: DateTime<Utc>,
    ) -> JobResult<Option<Job>>;
}

#[cfg(feature = "postgres")]
pub mod postgres;

#[cfg(feature = "postgres")]
pub use self::postgres::PostgresDatastore;
