use crate::task::entity::{TaskParams, TaskPayload};

#[cfg_attr(any(test, feature = "mocks"), auto_impl::auto_impl(Arc))]
#[cfg_attr(any(test, feature = "mocks"), mockall::automock)]
pub trait TaskService: Send + Sync + 'static {
    fn start_task(
        &self,
    ) -> impl Future<Output = anyhow::Result<Option<super::entity::Task>>> + Send;
    fn complete_task(&self, task_id: u64) -> impl Future<Output = anyhow::Result<()>> + Send;
    fn fail_task(
        &self,
        task_id: u64,
        error: anyhow::Error,
    ) -> impl Future<Output = anyhow::Result<()>> + Send;
    fn find_by_target_ids(
        &self,
        method: super::entity::TaskMethod,
        target_ids: &[u64],
    ) -> impl Future<Output = anyhow::Result<Vec<super::entity::Task>>> + Send;
}

#[cfg_attr(any(test, feature = "mocks"), auto_impl::auto_impl(Arc))]
#[cfg_attr(any(test, feature = "mocks"), mockall::automock)]
pub trait TaskRepository: Send + Sync + 'static {
    fn start_task(
        &self,
    ) -> impl Future<Output = anyhow::Result<Option<super::entity::Task>>> + Send;
    fn complete_task(&self, task_id: u64) -> impl Future<Output = anyhow::Result<()>> + Send;
    fn fail_task(
        &self,
        task_id: u64,
        error: String,
    ) -> impl Future<Output = anyhow::Result<()>> + Send;
    fn find_by_target_ids(
        &self,
        method: super::entity::TaskMethod,
        target_ids: &[u64],
    ) -> impl Future<Output = anyhow::Result<Vec<super::entity::Task>>> + Send;
}

#[cfg_attr(any(test, feature = "mocks"), auto_impl::auto_impl(Arc))]
#[cfg_attr(any(test, feature = "mocks"), mockall::automock)]
pub trait TaskPublisher: Send + Sync + 'static {
    fn publish<I>(
        &self,
        tasks: I,
        params: &TaskParams,
    ) -> impl Future<Output = anyhow::Result<()>> + Send
    where
        I: Iterator<Item = TaskPayload> + Send + 'static;
}
