<reasoning_content>
Thinking Process:

1.  **Analyze the Request:**
    *   Goal: Implement priority-based job scheduling for a queue.
    *   Requirements:
        1.  Modify `add_job` to accept an optional `priority` parameter (default=0).
        2.  Higher priority jobs processed before lower priority jobs (1 > 0, 2 > 1).
        3.  FIFO order for same priority.
        4.  Add `get_next_job() -> tuple[str, dict] | None` to retrieve the highest priority job.
    *   Priority Levels: 0 (Normal), 1 (High), 2 (Critical).
    *   Output: Only Python code, no explanations.

2.  **Determine Data Structure:**
    *   Need a structure that maintains order based on priority.
    *   Python's `heapq` module is suitable for priority queues.
    *   Since FIFO order is required for same priority, I need to include a counter/timestamp to break ties.
    *   Structure: `[(priority, counter, job_id, job_data), ...]`
    *   Wait, the requirement says `get_next_job` returns `tuple[str, dict]`. The input `add_job` takes `str` (name/id?) and `dict` (data).
    *   Actually, looking at the example: `queue.add_job("normal", {"type": "normal"})`. So `name` is the first arg, `data` is the second.
    *   `get_next_job` returns `tuple[str, dict]`.
    *   Priority logic: Higher number = Higher priority (2 > 1 > 0).
    *   `heapq` is a min-heap. To get highest priority (largest number) first, I can negate the priority or use a max-heap logic. Negating priority is easier with `heapq`.
    *   Tie-breaking: To maintain FIFO for same priority, I need a sequence number. Since `heapq` pops the smallest item, if priorities are equal, I need the sequence number to be smallest for the oldest item.
    *   Wait, if I negate priority:
        *   Priority 2 (Critical) -> -2
        *   Priority 1 (High) -> -1
        *   Priority 0 (Normal) -> 0
        *   Heap pops -2 first. This works.
    *   Tie-breaking for FIFO:
        *   If priorities are equal, I want the one added first to come out first.
        *   So I need a counter that increments.
        *   If I store `(neg_priority, counter, job_name, job_data)`, `heapq` will pop the one with smallest neg_priority (highest actual priority). If neg_priority is equal, it pops smallest counter (oldest).
    *   Wait, standard `heapq` compares tuples element by element.
    *   So `(neg_priority, counter)` works perfectly.

3.  **Drafting the Class:**
    *   Class name: `JobQueue` (implied by example).
    *   `__init__`: Initialize empty list and counter.
    *   `add_job(self, name: str, data: dict, priority: int = 0)`:
        *   Increment counter.
        *   Push `(-priority, counter, name, data)` to heap.
    *   `get_next_job(self) -> tuple[str, dict] | None`:
        *   Pop from heap.
        *   Return `(name, data)`.
        *   Handle empty queue (return `None`).

4.  **Refining Constraints:**
    *   Input example: `queue.add_job("normal", {"type": "normal"}, priority=0)`
    *   Return type: `tuple[str, dict] | None`
    *   Priority logic: 2 > 1 > 0.
    *   FIFO for same priority.
    *   Code must be clean and follow the requirements exactly.

5.  **Implementation Details:**
    *   Import `heapq`.
    *   Use `self.counter` to track order.

6.  **Code Structure:**
    ```python
    import heapq

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

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

        def get_next_job(self) -> tuple[str, dict] | None:
            if not self.heap:
                return None
            _, _, name, data = heapq.heappop(self.heap)
            return (name, data)
    ```
    Wait, `get_next_job` return type hint `tuple[str, dict] | None`.
    The example shows `queue.add_job("normal", {"type": "normal"}, priority=0)`.
    The prompt asks to "Modify `add_job`".
    I should define the class based on the usage context provided in the example.

    Let's double check the priority logic.
    Requirement: "Higher priority jobs should be processed before lower priority jobs".
    Levels: 0 (Normal), 1 (High), 2 (Critical).
    So 2 > 1 > 0.
    In a min-heap, smaller values come first.
    To make 2 come before 0, I should store `-2` and `0`. `-2 < 0`, so `-2` pops first.
    Correct.

    FIFO requirement:
    If priorities are equal, the one added earlier must come out earlier.
    Counter starts at 0, increments.
    Store `(-priority, counter)`.
    If priorities equal, compare `counter`. Smaller counter (earlier) pops first.
    Correct.

    Return type: `tuple[str, dict] | None`.
    The return statement should unpack the tuple from the heap.
    Heap item: `(neg_priority, counter, name, data)`.
    Return: `(name, data)`.

    Looks good.

7.  **Final Code Assembly:**
    Ensure imports are included. Ensure class definition matches the expected interface.

    One minor detail: The prompt asks to "Implement priority-based job scheduling for the queue." and gives an example usage `queue = JobQueue()`. So I need to define the `JobQueue` class.

    Wait, is there any existing code provided? No, just requirements and example. I need to provide the full implementation of the class.

    Let's verify the type hints. `tuple[str, dict] | None` is valid Python 3.10+ syntax. I will use it.

    One edge case: Is `name` strictly a string? The example uses strings. The type hint suggests `str`.
    Is `data` strictly a dict? The example uses dicts. The type hint suggests `dict`.

    Code looks solid.

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

class JobQueue:
    def __init__(self):
        self._queue = []
        self._counter = 0

    def add_job(self, job_id: str, job_data: Dict, priority: int = 0) -> None:
        heapq.heappush(self._queue, (-priority, self._counter, job_id, job_data))
        self._counter += 1

    def get_next_job(self) -> Optional[Tuple[str, Dict]]:
        if not self._queue:
            return None
        _, _, job_id, job_data = heapq.heappop(self._queue)
        return (job_id, job_data)
```
    Wait, the example uses `name` like "normal". I should probably name the parameters `name` and `data` to match the example signature `add_job("normal", {"type": "normal"})`.
    The prompt says `add_job` to accept...
    The example shows `add_job("normal", {"type": "normal"}, priority=0)`.
    So `name` and `data` are the arguments.
    I will use `name` and `data` in the function signature.

    Also, `tuple[str, dict] | None` syntax requires Python 3.10+. I will stick to the requested syntax.

    Final check on imports. `heapq` is needed. `tuple` and `dict` are builtins, but `Optional` or `Union` might be needed for type hinting if strict, but the prompt uses `tuple[str, dict] | None` which implies `|` union syntax is acceptable. I'll just use the builtins for types in the signature to be safe, or standard typing. The prompt uses `tuple[str, dict] | None` in the requirement section. I will match that.

    Wait, one detail in the prompt: `get_next_job() -> tuple[str, dict] | None`.
    I will ensure the return type matches.

    Let's write the code.

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

class JobQueue:
    def __init__(self):
        self._heap = []
        self._counter = 0

    def add_job(self, name: str, data: Dict, priority: int = 0) -> None:
        heapq.heappush(self._heap, (-priority, self._counter, name, data))
        self._counter += 1

    def get_next_job(self) -> Tuple[str, Dict] | None:
        if not self._heap:
            return None
        _, _, name, data = heapq.heappop(self._heap)
        return (name, data)
```
    Wait, `Tuple[str, Dict]` vs `tuple[str, dict]`. The prompt uses lowercase `tuple` and `dict`. In Python 3.9+, `tuple` and `dict` can be used for type hinting directly. I will use the prompt's style.

    Also, I should make sure not to include explanations. Just the code.

    One more check: `get_next_job` returns `tuple[str, dict]`.
    The heap stores `(neg_priority, counter, name, data)`.
    Unpacking: `_, _, name, data = ...`
    Return: `(name, data)`.
    Matches.

    Priority logic:
    Priority 2 (Critical) -> -2
    Priority 1 (High) -> -1
    Priority 0 (Normal) -> 0
    Min heap pops -2 first. Correct.

    FIFO logic:
    Counter increments.
    If priorities equal, smaller counter (earlier) pops first. Correct.

    Ready.

```python
import heapq

class JobQueue:
    def __init__(self):
        self._queue = []
        self._counter = 0

    def add_job(self, name: str, data: dict, priority: int = 0) -> None:
        heapq.heappush(self._queue, (-priority, self._counter, name, data))
        self._counter += 1

    def get_next_job(self) -> tuple[str, dict] | None:
        if not self._queue:
            return None
        _, _, name, data = heapq.heappop(self._queue)
        return (name, data)
```
    Looks correct. I will remove the type hints from `name` and `data` arguments to strictly follow the prompt's implied interface if needed, but adding them makes it robust. The prompt says "Modify `add_job`", implying I define the class. I will add type hints for clarity as per Python best practices, but ensure the signature matches the example call.
    Actually, to be safest with the prompt's specific request `get_next_job() -> tuple[str, dict] | None`, I will use that exact syntax for the return type.
    I will use `name` and `data` as argument names to match the example `add_job("normal", {"type": "normal"})`.

    Wait, the prompt example: `queue.add_job("normal", {"type": "normal"}, priority=0)`.
    So `name` is the first arg.
    I will use `name` and `job_data` or `data`. `data` is fine.

    Final check on constraints: "Write only the Python code, no explanations."

    One thing: The prompt example uses `queue = JobQueue()`. So I must define `JobQueue`.
    The prompt asks to "Implement...".
    Okay.

    One small detail: `tuple[str, dict] | None`. In older Python versions, this syntax isn't supported without `from __future__ import annotations` or using `typing`. However, since the prompt explicitly requests `tuple[str, dict] | None`, I will assume Python 3.10+ environment or that this is the expected syntax. I will write the code using this syntax.

    Wait, `dict` vs `Dict`. `dict` is built-in generic in 3.9+. I will use `dict`.

    Okay, constructing the final block.

```python
import heapq

class JobQueue:
    def __init__(self):
        self._heap = []
        self._counter = 0

    def add_job(self, name: str, data: dict, priority: int = 0) -> None:
        heapq.heappush(self._heap, (-priority, self._counter, name, data))
        self._counter += 1

    def get_next_job(self) -> tuple[str, dict] | None:
        if not self._heap:
            return None
        _, _, name, data = heapq.heappop(self._heap)
        return (name, data)
```
    Wait, I should check if `dict` is valid for type hinting in the context of the prompt's `tuple[str, dict]`. Yes, Python 3.9+ supports `dict[...]`.
    I will proceed.

    Wait, one detail in the prompt: `get_next_job() -> tuple[str, dict] | None`.
    I should ensure the return type annotation matches exactly.

    Okay, final check.
    1. `add_job` accepts priority (default 0). Done.
    2. Higher priority processed first. Done (using negative priority for min-heap).
    3. FIFO for same priority. Done (using counter).
    4. `get_next_job` returns tuple or None. Done.
    5. Only Python code. Done.

    One thing: The prompt example uses `priority=0`, `priority=2`, `priority=1`.
    My implementation uses `-priority`.
    2 -> -2 (pops first).
    1 -> -1.
    0 -> 0.
    -2 < -1 < 0.
    Correct.

    What if priority is negative? The requirements say 0, 1, 2. I don't need to handle other values strictly, but the logic holds for integers.
    I will stick to the logic.

    One more check on imports. `heapq` is needed.
    I will include it.

    The prompt says "Write only the Python code". I will provide the class definition.

    Wait, should I put the code in a specific way? Usually just the script content.
    I'll provide the class definition.

    Wait, I notice the prompt example uses `queue.add_job("normal", {"type": "normal"}, priority=0)`.
    This implies `name` is the first positional argument.
    My code: `def add_job(self, name: str, data: dict, priority: int = 0)`.
    This matches.

    Okay, ready to generate.

    Wait, I should check if `tuple[str, dict]` works without imports in the type hint.
    In Python 3.9+, yes.
    If I want to be 100% compatible with 3.10+ (implied by `|` syntax), I don't need imports for `tuple` or `dict`.
    I only need `heapq`.
    I will add `import heapq`.

    Final check on text.
    "Write only the Python code, no explanations."
    Okay.

    One nuance: `get_next_job` returns `tuple[str, dict]`.
    The heap item is `(-priority, counter, name, data)`.
    I unpack `_, _, name, data`.
    Then return `(name, data)`.
    This is correct.

    Let's assemble.

</reasoning_content>

<content>
```python
import heapq

class JobQueue:
    def __init__(self):
        self._heap = []
        self._counter = 0

    def add_job(self, name: str, data: dict, priority: int = 0) -> None:
        heapq.heappush(self._heap, (-priority, self._counter, name, data))
        self._counter += 1

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