import org.jobrunr.configuration.JobRunr;
import org.jobrunr.jobs.annotations.Job;
import org.jobrunr.jobs.context.JobContext;
import org.jobrunr.jobs.states.StateName;
import org.jobrunr.scheduling.BackgroundJob;
import org.jobrunr.server.BackgroundJobServerConfiguration;
import org.jobrunr.storage.InMemoryStorageProvider;

import java.time.Duration;
import java.util.concurrent.atomic.AtomicInteger;

/** JobRunr 9 durable steps: runStepOnce skips a step that already finished when the job is retried. */
public class StepsDemo {

    static final AtomicInteger attempt = new AtomicInteger();

    public static class Order {
        @Job(name = "Fulfil order", retries = 2)
        public void fulfil(JobContext ctx) throws Exception {
            int n = attempt.incrementAndGet();
            System.out.println("attempt " + n);
            ctx.runStepOnce("charge", () -> System.out.println("  charge the card"));
            ctx.runStepOnce("ship", () -> System.out.println("  book the courier"));
            ctx.runStepOnce("email", () -> {
                System.out.println("  send the email");
                if (n == 1) {
                    throw new IllegalStateException("mail server down");
                }
            });
            System.out.println("  done");
        }
    }

    public static void main(String[] args) throws Exception {
        var storage = new InMemoryStorageProvider();
        JobRunr.configure().useStorageProvider(storage)
                .useBackgroundJobServer(BackgroundJobServerConfiguration.usingStandardBackgroundJobServerConfiguration()
                        .andPollInterval(Duration.ofSeconds(5)))
                .initialize();
        var order = new Order();
        BackgroundJob.enqueue(() -> order.fulfil(JobContext.Null));
        Thread.sleep(14_000);
        System.out.println("SUCCEEDED: " + storage.countJobs(StateName.SUCCEEDED) + ", FAILED: " + storage.countJobs(StateName.FAILED));
        JobRunr.destroy();
    }
}
