<reasoning_content>
Here's a thinking process:

1.  **Understand User Requirements:**
   - Modify `add_job` to accept an optional `priority` parameter (default=0)
   - Higher priority jobs should be processed before lower priority jobs
   - Jobs with the same priority should maintain FIFO order
   - Add `get_next_job() -> tuple[str, dict] | None` to get the highest priority job
   - Priority levels: 0: Normal, 1: High, 2: Critical
   - Example provided shows usage
   - Output only Python code, no explanations

2.  **Identify Key Data Structures/Algorithms:**
   - Need a queue that supports priority-based ordering
   - FIFO within same priority level
   - Python's `heapq` module is perfect for priority queues, but it's a min-heap by default. Since higher priority = higher number, I can either negate the priority or use a custom comparison.
   - To maintain FIFO for same priority, I can use a counter/timestamp as a secondary sort key: `(-priority, insertion_order, job_id, job_data)`
   - Alternatively, use `collections.deque` per priority level, but `heapq` is simpler and standard.
   - Let's stick with `heapq` with a counter for FIFO ordering.

3.  **Design the Class:**
   ```python
   import heapq
   from typing import Optional, Tuple, Dict, Any

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

       def add_job(self, job_id: str, job_data: dict, priority: int = 0) -> None:
           # Use negative priority so higher priority comes first in min-heap
           # Use counter to maintain FIFO for same priority
           heapq.heappush(self._heap, (-priority, self._counter, job_id, job_data))
           self._counter += 1

       def get_next_job(self) -> Optional[Tuple[str, dict]]:
           if self._heap:
               _, _, job_id, job_data = heapq.heappop(self._heap)
               return job_id, job_data
           return None
   ```

4.  **Check Requirements:**
   - `add_job` accepts optional priority (default=0)? Yes.
   - Higher priority processed first? Yes, using `-priority` in min-heap.
   - Same priority maintains FIFO? Yes, using `_counter` as secondary key.
   - `get_next_job()` returns `tuple[str, dict] | None`? Yes.
   - Example matches? Let's trace:
     - add normal (0) -> heap: `[(0, 0, "normal", ...)]`
     - add critical (2) -> heap: `[(-2, 1, "critical", ...), (0, 0, "normal", ...)]`
     - add high (1) -> heap: `[(-2, 1, "critical", ...), (0, 0, "normal", ...), (-1, 2, "high", ...)]`
     - pop -> returns critical. Correct.
   - Type hints match requirement: `tuple[str, dict] | None`
   - Only Python code, no explanations.

5.  **Refine Code:**
   Make sure imports are included if needed, but the prompt doesn't specify imports. I'll include them for completeness.
   I'll use `typing` module for type hints as per Python 3.9+ syntax or just use built-in types. The prompt uses `tuple[str, dict] | None` which is Python 3.10+ syntax. I'll stick to that.

   Let's write it out carefully:
   ```python
   import heapq
   from typing import Optional, Tuple, Dict

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

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

       def get_next_job(self) -> tuple[str, dict] | None:
           if self._heap:
               _, _, job_id, job_data = heapq.heappop(self._heap)
               return job_id, job_data
           return None
   ```

   Wait, should I include type imports? The prompt uses `tuple[str, dict] | None` directly in the requirement, so Python 3.10+ is assumed. I'll just write the class. I don't need to import `typing` if I use modern syntax, but `heapq` is needed.

   Let's verify FIFO behavior with `heapq`:
   `heapq` compares tuples element by element.
   `(-priority, counter, job_id, job_data)`
   If priorities are equal, `-priority` is equal, then it compares `counter`. Since `counter` increases monotonically, lower counter (earlier insertion) comes first. This guarantees FIFO for same priority.
   `job_id` and `job_data` are only compared if both priority and counter are equal, which won't happen. So it's safe.

   One minor thing: `job_data` might not be comparable, but since `counter` is unique, it won't reach that comparison. So it's fine.

   The code looks solid. I'll output exactly that.
   I'll make sure to match the exact signature requested: `get_next_job() -> tuple[str, dict] | None`
   I'll add `import heapq` at the top.
   No extra text.

   Final check of the prompt: "Write only the Python code, no explanations."
   I will output just the code block.
   One thing: `typing` might be needed for `Optional` if using older Python, but the prompt uses `|` syntax, so I'll stick to that. I won't add unnecessary imports.

   Code:
   ```python
   import heapq

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

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

       def get_next_job(self) -> tuple[str, dict] | None:
           if self._heap:
               _, _, job_id, job_data = heapq.heappop(self._heap)
               return job_id, job_data
           return None
   ```
   This matches all requirements. Ready.✅
   I'll output exactly this.✅
   One minor consideration: Should I include type hints for `add_job`? The prompt doesn't specify, but it's good practice. I'll keep it simple.
   All good.✅
   Output matches response. 
   Proceeds. 
   [Self-Correction/Verification during thought]
   - Check FIFO: `counter` ensures strict insertion order for same priority. Correct.
   - Check priority: `-priority` ensures higher priority numbers come first in min-heap. Correct.
   - Check return type: `tuple[str, dict] | None`. Correct.
   - Check default priority: `priority: int = 0`. Correct.
   - No explanations. Correct.
   All requirements met. Output matches. 
   Generating. 
   [Output Generation] -> *Proceeds*
   *(Note: I'll make sure the code is exactly as refined)*
   ```python
   import heapq

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

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

       def get_next_job(self) -> tuple[str, dict] | None:
           if self._heap:
               _, _, job_id, job_data = heapq.heappop(self._heap)
               return job_id, job_data
           return None
   ```
   This is perfect.✅
   Output matches. 
   [Done] 
   *Self-Correction/Note during generation prep*: The prompt says "Write only the Python code, no explanations." I will strictly follow that. I'll output just the code block. No markdown if possible? The prompt says "Write only the Python code", so I'll wrap it in a code block as is standard, but I'll make sure there's absolutely no extra text. Actually, standard markdown code blocks are fine. I'll just output the code.
   All good. 
   Proceeds. 
   [Output Generation] -> *Outputs code*
   *(Done.)*

</reasoning_content>

<content>
```python
import heapq

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

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

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