import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.Scanner;

/** Teaching example, Java 17. Synthetic tokens only; no patient records or services. */
public final class OpdQueueDemo {
    private final Queue<Integer> waiting = new ArrayDeque<>();
    private Integer current;
    private int nextToken = 1;
    private int completed;

    public int add() { int token = nextToken++; waiting.add(token); return token; }
    public Integer callNext() {
        if (current != null) throw new IllegalStateException("Complete the current token first.");
        current = waiting.poll();
        return current;
    }
    public Integer complete() {
        if (current == null) return null;
        int token = current; current = null; completed++; return token;
    }
    public List<Integer> waitingTokens() { return new ArrayList<>(waiting); }
    public void reset() { waiting.clear(); current = null; completed = 0; nextToken = 1; }
    public String status() {
        return "Waiting=" + waitingTokens() + "; current=" + current + "; completed=" + completed;
    }
    private static void check(boolean condition, String message) {
        if (!condition) throw new IllegalStateException("Self-test failed: " + message);
    }
    private static void selfTest() {
        OpdQueueDemo q = new OpdQueueDemo();
        check(q.callNext() == null && q.complete() == null, "empty queue");
        check(q.add() == 1 && q.add() == 2, "unique sequential tokens");
        check(q.waitingTokens().equals(List.of(1, 2)), "arrival order");
        check(q.callNext() == 1, "first in, first out");
        try { q.callNext(); throw new IllegalStateException("current token was skipped"); }
        catch (IllegalStateException expected) {
            check(expected.getMessage().equals("Complete the current token first."), "guard");
        }
        check(q.complete() == 1 && q.callNext() == 2 && q.complete() == 2, "completion");
        check(q.completed == 2 && q.callNext() == null, "completed count");
        q.reset(); check(q.add() == 1 && q.completed == 0, "reset");
        System.out.println("PASS: empty queue, FIFO, token uniqueness, active-token guard, completion and reset.");
    }
    public static void main(String[] args) {
        if (args.length > 0 && args[0].equals("--self-test")) { selfTest(); return; }
        OpdQueueDemo q = new OpdQueueDemo();
        if (args.length > 0 && args[0].equals("--interactive")) {
            System.out.println("Synthetic queue demo. Commands: add, next, complete, status, reset, quit");
            try (Scanner in = new Scanner(System.in)) {
                while (in.hasNextLine()) {
                    String command = in.nextLine().trim();
                    if (command.equals("quit")) break;
                    try {
                        switch (command) {
                            case "add": System.out.println("Added token " + q.add()); break;
                            case "next": System.out.println("Called token " + q.callNext()); break;
                            case "complete": System.out.println("Completed token " + q.complete()); break;
                            case "reset": q.reset(); break;
                            case "status": break;
                            default: System.out.println("Use add, next, complete, status, reset or quit.");
                        }
                    } catch (IllegalStateException error) { System.out.println(error.getMessage()); }
                    System.out.println(q.status());
                }
            }
        } else {
            q.add(); q.add(); q.add(); System.out.println(q.status());
            q.callNext(); System.out.println(q.status());
            q.complete(); System.out.println(q.status());
        }
    }
}
