package eu.reply.lea.services.yms.task.locationaware.domain;

import java.util.List;

import eu.reply.sce.backend.core.entity.EntityReference;

/**
 * Service interface for task queue operations.
 * Provides methods to check and manage the queuing status of tasks.
 */
public interface TaskQueueService {

    /**
     * Checks whether a given task is currently queued.
     *
     * @param task the location-aware task to check
     * @return true if the task is queued, false otherwise
     */
    boolean isTaskQueued(LocationAwareTask<?, ?, ?> task);

    /**
     * Queues all tasks associated with the provided logistic unit reference.
     *
     * @param logisticUnitReference the reference of the logistic unit whose tasks are to be queued
     */
    void queueTasks(EntityReference logisticUnitReference);
    void queueTasks(EntityReference logisticUnitReference, String code);

    /**
     * Dequeues the given list of tasks.
     *
     * @param tasks the tasks to dequeue
     */
    void dequeueTasks(List<LocationAwareTask<?, ?, ?>> tasks) ;
    void dequeueTasks(List<LocationAwareTask<?, ?, ?>> tasks, String code) ;

    void dequeueTasksAndThenQueue(final List<LocationAwareTask<?, ?, ?>> tasksToDequeue);
}


add javadoc where missing
package eu.reply.lea.services.yms.task.locationaware.integration.yms.queue;

import javax.inject.Inject;

import java.util.List;

import org.slf4j.Logger;

import eu.reply.lea.services.yms.task.TaskReference;
import eu.reply.lea.services.yms.task.locationaware.domain.LocationAwareTask;
import eu.reply.lea.services.yms.task.locationaware.domain.TaskQueueService;
import eu.reply.lea.services.yms.task.queue.event.TaskDequeueQueueCommand;
import eu.reply.lea.services.yms.task.queue.event.TaskDequeueQueueCommandInfo;
import eu.reply.lea.services.yms.task.queue.process.QueueProcessTracker;
import eu.reply.lea.services.yms.task.queue.event.TaskQueueCommand;
import eu.reply.lea.services.yms.task.queue.event.TaskQueueCommandInfo;
import eu.reply.lea.services.yms.task.queue.process.repository.QueueProcessTrackerRepository;
import eu.reply.sce.backend.core.entity.EntityReference;
import eu.reply.sce.backend.core.event.ConfigurableEventProducer;

public class TaskQueueServiceImpl implements TaskQueueService {

    @Inject
    private Logger logger;

    @Inject
    private QueueProcessTrackerRepository queueProcessTrackerRepository;

    @Inject
    private ConfigurableEventProducer<TaskQueueCommand> taskQueueCommandProducer;

    @Inject
    private TaskQueueAdapter taskQueueAdapter;

    @Override
    public void dequeueTasks(final List<LocationAwareTask<?, ?, ?>> tasks) {
        dequeueTasks(tasks, null);
    }

    @Override
    public void dequeueTasks(List<LocationAwareTask<?, ?, ?>> tasksToDequeue, String code) {
        if( tasksToDequeue.stream().anyMatch(t -> t.getLocation() == null)){
            throw new RuntimeException("A task without location was found");
        }
        if( tasksToDequeue.stream().anyMatch(t -> !t.isEnableQueue())){
            throw new RuntimeException("A task without queue enabled was found");
        }
        try {
            taskQueueAdapter.notifyDequeueForTask(tasksToDequeue, code);
            logger.info("Successfully dequeued tasks.");
        } catch (Exception e) {
            logger.error("Error during task dequeuing: {}", e.getMessage());
            throw new RuntimeException("Failed to dequeue tasks.", e);
        }
    }

    public boolean isTaskQueued(LocationAwareTask<?, ?, ?> task){
        QueueProcessTracker
            transitQueueProcessTracker = queueProcessTrackerRepository.findByLogisticUnitRef(task.getLogisticUnitReference());
        if(transitQueueProcessTracker == null || !transitQueueProcessTracker.isTaskQueued(new TaskReference(task))){
            logger.info("No process tracker for logisticUnit [{}]", task.getLogisticUnitReference());
            return false;
        }
        return true;
    }

    public void queueTasks(EntityReference logisticUnitReference, String code){
        taskQueueCommandProducer.fire(new TaskQueueCommand(new TaskQueueCommandInfo(logisticUnitReference, code)));
    }
    public void queueTasks(EntityReference logisticUnitReference){
        queueTasks(logisticUnitReference, null);
    }


    public void dequeueTasksAndThenQueue(final List<LocationAwareTask<?, ?, ?>> tasksToDequeue) {
        try {
            taskQueueAdapter.notifyDequeueQueueForTask(tasksToDequeue);
            logger.info("Successfully dequeued and queued tasks.");
        } catch (Exception e) {
            logger.error("Error during task queueing dequeuing: {}", e.getMessage());
            throw new RuntimeException("Failed to dequeue queue tasks.", e);
        }
    }

}