<reasoning_content>
*   Goal: Implement priority-based job scheduling.
    *    Requirements:
        1. `add_job` accepts `priority` (default 0).
        2. Higher priority (larger number) comes first.
        3. Same priority uses FIFO.
        4. `get_next_job()` returns highest priority job or None.
    *    Priority levels: 0 (Normal), 1 (High), 2 (Critical).
    *    Output format: Python code only, no explanations.

    *   Data structure: A priority queue is usually implemented using a heap (like `heapq` in Python), but `heapq` is a min-heap. Since higher numbers mean higher priority, I can use negative values or just sort by priority descending.
    *    However, to maintain FIFO for equal priorities, I need an ordering mechanism. A common way to do this with a heap is to store a tuple `(priority, sequence_number, job_data)`.
    *    Wait, if I use a max-heap, I need to negate the priority.
    *    Actually, a simple way to handle FIFO + Priority is to use a list of lists (or a dictionary of lists) where keys are priorities. But a heap is more standard for "priority queues".
    *    Since the priority levels are small (0, 1, 2), a list of lists or even just sorting a list works. But let's stick to a clean implementation.
    *    Let's use a list of tuples and `sort()` or use `heapq`.
    *    If I use `heapq`, to get the *highest* priority first, I'd store `(-priority, entry_count, job_name, job_data)`.
    *    Let's re-read requirements: "Higher priority jobs should be processed before lower priority jobs". So 2 > 1 > 0.

    *   `self.jobs`: a list or heap.
    *   `self.counter`: to maintain FIFO for same priority.
    *   `add_job(name, data, priority=0)`:
        *   `heapq.heappush(self.jobs, (-priority, self.counter, name, data))`
        *   `self.counter += 1`
    *   `get_next_job()`:
        *   `if not self.jobs: return None`
        *   `priority, count, name, data = heapq.heappop(self.jobs)`
        *   `return (name, data)`

    *    `priority=0` default? Yes.
    *    Higher priority first? Yes (using negative priority in min-heap).
    *    FIFO for same priority? Yes (using `counter`).
    *    `get_next_job()` signature? `tuple[str, dict] | None`.

    ```python
    import heapq

    class JobQueue:
        def __init__(self):
            self.jobs = []
            self.counter = 0

        def add_job(self, name: str, data: dict, priority: int = 0):
            # Use negative priority to make heapq (min-heap) act like a max-heap
            # Counter ensures FIFO for same priority
            heapq.heappush(self.jobs, (-priority, self.counter, name, data))
            self.counter += 1

        def get_next_job(self) -> tuple[str, dict] | None:
            if not self.jobs:
                return None
            _, _, name, data = heapq.heappop(self.jobs)
            return (name, data)
    ```

    Wait, I should check if `heapq` is allowed. Usually, for these types of prompts, standard library is fine.

    Let's double check the requirement "Higher priority jobs should be processed before lower priority jobs".
    Priority 2 (Critical) > 1 (High) > 0 (Normal).
    In a min-heap:
    -2 is smaller than -1, which is smaller than 0.
    So `heappop` will give -2 first. Correct.

    Wait, I can also just use a simple list and `sort` every time, or use `bisect`. But `heapq` is $O(\log n)$.

    Let's provide the class structure.

    ```python
    import heapq

    class JobQueue:
        def __init__(self):
            self.jobs = []
            self.counter = 0

        def add_job(self, name: str, data: dict, priority: int = 0):
            # Use -priority to turn min-heap into max-priority behavior
            # self.counter ensures FIFO for same priority
            heapq.heappush(self.jobs, (-priority, self.counter, name, data))
            self.counter += 1

        def get_next_job(self) -> tuple[str, dict] | None:
            if not self.jobs:
                return None
            _, _, name, data = heapq.heappop(self.jobs)
            return (name, data)
    ```

    Wait, the prompt says "Modify `add_job` ... Add `get_next_job`". It implies there might be an existing class. I should provide a complete `JobQueue` class.

    Final check on types:
    `tuple[str, dict] | None`
    `add_job(self, name: str, data: dict, priority: int = 0)`

    Is there a simpler way without `heapq`?
    Yes, a list of lists: `self.queues = {0: [], 1: [], 2: []}`.
    When adding: `self.queues[priority].append((name, data))`.
    When getting: Iterate `[2, 1, 0]` and pop from the first non-empty list.
    This is actually very clean for a fixed small number of priorities.
    However, the prompt says "priority levels: 0, 1, 2", but doesn't strictly say "only 0, 1, 2". Usually, it's safer to assume a heap because it handles any priority integer.

    I'll stick to `heapq`.

    Wait, one detail: `tuple[str, dict] | None` is Python 3.10+ syntax. I will use that.

    One minor detail: `priority` parameter type.
    The prompt says "priority levels: 0, 1, 2".

    ```python
    import heapq
    from typing import Tuple, Dict, Optional

    class JobQueue:
        def __init__(self):
            self.jobs = []
            self.counter = 0

        def add_job(self, name: str, data: dict, priority: int = 0):
            # Negate priority to prioritize higher numbers (Max-Heap behavior)
            # counter ensures FIFO for items with same priority
            heapq.heappush(self.jobs, (-priority, self.counter, name, data))
            self.counter += 1

        def get_next_job(self) -> tuple[str, dict] | None:
            if not self.jobs:
                return None
            _, _, name, data = heapq.heappop(self.jobs)
            return (name, data)
    ```

    Wait, I'll remove the imports if not necessary? No, `heapq` is definitely needed.

    Let's refine the code to be as concise as possible.

    ```python
    import heapq

    class JobQueue:
        def __init__(self):
            self.jobs = []
            self.counter = 0

        def add_job(self, name: str, data: dict, priority: int = 0):
            heapq.heappush(self.jobs, (-priority, self.counter, name, data))
            self.counter += 1

        def get_next_job(self) -> tuple[str, dict] | None:
            if not self.jobs:
                return None
            _, _, name, data = heapq.heappop(self.jobs)
            return (name, data)
    ```

    Wait, the requirement says "Modify `add_job` to accept an optional priority parameter". This implies I should include the method definition.

    The request asks for "only the Python code".

    One check on `tuple[str, dict] | None`. This is allowed in Python 3.10+. I'll use it.

    One more thing: the prompt asks to "Modify `add_job` to accept an optional priority parameter". Since I'm writing the whole class, I will include the `__init__` too.

    Double checking logic:
    - `add_job("normal", ..., priority=0)` -> `(-0, 0, "normal", ...)`
    - `add_job("critical", ..., priority=2)` -> `(-2, 1, "critical", ...)`
    - `add_job("high", ..., priority=1)` -> `(-1, 2, "high", ...)`
    - `heappop` gives smallest values first:
        1. `(-2, 1, "critical", ...)`
        2. `(-1, 2, "high", ...)`
        3. `(-0, 0, "normal", ...)`
    This matches the priority order: 2 (Critical) > 1 (High) > 0 (Normal).
    FIFO for same priority:
    - `add_job("A", ..., 1)` -> `(-1, 0, "A", ...)`
    - `add_job("B", ..., 1)` -> `(-1, 1, "B", ...)`
    - `heappop` gives `-1, 0` then `-1, 1`. Correct.

    Wait, I'll provide the code now.

    One detail: `tuple[str, dict] | None` is Python 3.10 syntax. If the user is on an older version, it fails. But the prompt uses that specific syntax in the signature requirement `get_next_job() -> tuple[str, dict] | None`. So I must use it.

    Final code structure:
    ```python
    import heapq

    class JobQueue:
        def __init__(self):
            self.jobs = []
            self.counter = 0

        def add_job(self, name: str, data: dict, priority: int = 0):
            heapq.heappush(self.jobs, (-priority, self.counter, name, data))
            self.counter += 1

        def get_next_job(self) -> tuple[str, dict] | None:
            if not self.jobs:
                return None
            _, _, name, data = heapq.heappop(self.jobs)
            return (name, data)
    ```

    Wait, is `tuple[str, dict]` valid? Yes, it's the newer way to write `Tuple[str, Dict]`.

    Double check: The prompt says "Implement priority-based job scheduling for the queue." and then lists requirements. It doesn't give me the original `JobQueue` class, so I must provide the structure.

    Actually, looking at the prompt "Modify `add_job` ... Add `get_next_job`", it suggests I should write a class that has these methods.

    One check: `self.counter` needs to be initialized.

    Let's check if `heapq` is the best approach or if a simple list and `sort()` is simpler.
    For a job queue, $O(\log n)$ is better than $O(n \log n)$.

    I'll write it.

    Wait, the example shows:
    ```python
    queue = JobQueue()
    queue.add_job("normal", {"type": " normal"}, priority=0)
    queue.add_job("critical", {"type": "critical"}, priority=2)
    queue.add_job("high", {"type": "high"}, priority=1)
    ```
    My code handles this.

    One small thing: `tuple[str, dict]` vs `tuple[str, dict[str, Any]]`. I'll stick to what's in the prompt.

    Wait, does `tuple[str, dict]` work for type hinting? Yes.

    Final verification of the signature: `get_next_job() -> tuple[str, dict] | None`.

    ```python
    import heapq

    class JobQueue:
        def __init__(self):
            self.jobs = []
            self.counter = 0

        def add_job(self, name: str, data: dict, priority: int = 0):
            # Using a negative priority allows the min-heap to act as a max-heap
            # The counter ensures FIFO order for jobs with the same priority
            heapq.heappush(self.jobs, (-priority, self.counter, name, data))
            self.counter += 1

        def get_next_job(self) -> tuple[str, dict] | None:
            if not self.jobs:
                return None
            _, _, name, data = heapq.heappop(self.jobs)
            return (name, data)
    ```
</reasoning_content>

<content>
```python
import heapq

class JobQueue:
    def __init__(self):
        self.jobs = []
        self.counter = 0

    def add_job(self, name: str, data: dict, priority: int = 0):
        # Negate priority to transform min-heap into max-priority behavior
        # self.counter ensures FIFO order for jobs with the same priority
        heapq.heappush(self.jobs, (-priority, self.counter, name, data))
        self.counter += 1

    def get_next_job(self) -> tuple[str, dict] | None:
        if not self.jobs:
            return None
        
        # Pop the highest priority job (smallest negative value)
        _, _, name, data = heapq.heappop(self.jobs)
        return (name, data)
```
</content>