<reasoning_content>
Here's a thinking process:

1.  **Understand User Requirements:**
   - Implement a priority-based job scheduling queue.
   - `add_job` method: accepts job name, job data, and optional priority (default=0).
   - Higher priority jobs processed first.
   - FIFO order for same priority.
   - `get_next_job` method: returns `(job_name, job_data)` or `None`.
   - Priority levels: 0 (Normal), 1 (High), 2 (Critical) - though the exact numbers don't matter as long as higher means higher priority.
   - Example provided shows usage.
   - Output: Only Python code, no explanations.

2.  **Identify Key Data Structures:**
   - Need a queue that supports priority ordering.
   - Python's `heapq` is perfect for this. It's a min-heap, so to get higher priority first, I can either:
     a) Use negative priorities, or
     b) Use a tuple `(priority, insertion_order, job_name, job_data)` and rely on heapq's tuple comparison.
   - Since FIFO is required for same priority, I need a counter/timestamp to maintain insertion order.
   - Tuple structure for heap: `(priority, insertion_counter, job_name, job_data)`
   - Wait, `heapq` pops the smallest element. If higher priority should be processed first, I should either negate priority or reverse the comparison. Let's use negative priority: `(-priority, insertion_counter, job_name, job_data)`. This way, priority 2 becomes -2 (smallest), so it pops first. Priority 0 becomes 0. Same priority: insertion_counter ensures FIFO.
   - Alternatively, just use `(-priority, insertion_counter, ...)` and pop from heap.

3.  **Design the Class:**
   ```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:
           # Use negative priority so higher priority pops first
           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
   ```

4.  **Check Requirements:**
   - `add_job` accepts optional priority parameter (default=0)? Yes.
   - Higher priority jobs processed before lower? Yes, using `-priority`.
   - Same priority maintains FIFO? Yes, using `_counter`.
   - `get_next_job() -> tuple[str, dict] | None`? Yes.
   - Priority levels 0, 1, 2? The code handles any integer priority, which covers the requirement.
   - Example matches? Let's trace:
     - add_job("normal", {...}, 0) -> heap: [(-0, 0, "normal", {...})]
     - add_job("critical", {...}, 2) -> heap: [(-2, 1, "critical", {...}), (-0, 0, "normal", {...})]
     - add_job("high", {...}, 1) -> heap: [(-2, 1, "critical", {...}), (-0, 0, "normal", {...}), (-1, 2, "high", {...})] (heap order might vary but min is -2)
     - get_next_job() -> pops (-2, 1, "critical", {...}) -> returns ("critical", {...})
     - Matches example.
   - Type hints: `tuple[str, dict] | None` is valid in Python 3.10+. I'll keep it as requested.
   - Only Python code, no explanations.

5.  **Refine Code:**
   Let's make sure imports are included and the class is complete.
   I'll add type hints properly.
   ```python
   import heapq
   from typing import Optional, Tuple, Dict

   class JobQueue:
       def __init__(self):
           self._queue: list = []
           self._counter: int = 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) -> Optional[Tuple[str, Dict]]:
           if not self._queue:
               return None
           _, _, name, data = heapq.heappop(self._queue)
           return name, data
   ```
   Wait, the requirement says `get_next_job() -> tuple[str, dict] | None`. I'll stick to that syntax if possible, or use `typing.Optional`. Python 3.10+ supports `|`. I'll use `Optional` from typing to be safe, or just stick to the exact signature requested. The prompt uses `tuple[str, dict] | None`, so I'll use that.

   Let's adjust to match exactly:
   ```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
   ```

   Check edge cases:
   - Empty queue: returns None. Correct.
   - Same priority: counter ensures FIFO. Correct.
   - Higher priority first: negative priority ensures it. Correct.
   - Type hints: matches requirement.
   - Only code: I will output just the class definition.

   One minor thing: `data` is a dict, but in Python, `dict` is fine. I'll keep it as `dict`.
   The prompt says "Write only the Python code, no explanations."
   I'll provide exactly that.

   Let's double check the heap behavior with negative priorities and counters.
   Tuple comparison in Python compares element by element.
   (-2, 1, ...) vs (-1, 2, ...) -> -2 < -1, so (-2, ...) comes first. Correct.
   (-1, 2, ...) vs (-1, 3, ...) -> -1 == -1, then 2 < 3, so (-1, 2, ...) comes first. Correct (FIFO).
   All good.

   I will wrap it in a clean code block.
   One thing: `tuple[str, dict] | None` is Python 3.10+ syntax. I'll assume modern Python is fine. If needed, I can use `typing.Optional`, but the prompt explicitly uses `|`. I'll stick to it.

   Final code:
   ```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
   ```
   This matches all requirements. I'll output it.✅
   Self-Correction/Verification during thought:
   - Is `heapq` necessary? Yes, it's standard and efficient.
   - Could use `queue.PriorityQueue`, but it's thread-safe and handles tuples differently, and `heapq` is simpler for this use case.
   - The prompt says "Write only the Python code, no explanations." I will strictly follow that.
   - I'll make sure the imports are included.
   - All good. Output matches. 
   Proceed. 
   Output generation. 
   [Done] 
   *Self-Correction/Refinement during thought*: 
   Wait, should I include `from typing import ...`? The prompt uses `tuple[str, dict] | None` which is built-in in 3.10+. I'll just use it directly. No extra imports needed besides `heapq`.
   The code is solid.
   Output matches exactly.✅
   Proceeds. 
   [Output Generation] -> *See response.* 
   *(Note: I'll make sure the formatting is exactly as requested.)*
   ```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
   ```
   This is correct. Output matches.✅
   Final Check of the prompt: "Write only the Python code, no explanations." -> I will output just the code block.
   All good. 
   Proceeds. 
   [Output Generation] (matches the refined code)
   *(Done.)*

</reasoning_content>

<content>
```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
```
</content>