<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 processed first
   - Same priority jobs 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)
   - Return only Python code, no explanations

2.  **Identify Key Data Structure:**
   - Need a priority queue that maintains FIFO order for same-priority items
   - Python's `heapq` module is suitable, but needs a tie-breaker for FIFO order
   - Can use a counter to track insertion order: `(-priority, counter, job_name, job_data)`
   - Wait, `heapq` is a min-heap, so higher priority should come first. If priority is 0, 1, 2 (higher is more important), we can negate it: `-priority`
   - Alternatively, use `collections.deque` for each priority level, or just a list of deques/queues per priority level. But `heapq` with a counter is standard and efficient.
   - Let's stick with `heapq` + counter for simplicity and correctness.

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

   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 values come first in min-heap
           # Use counter to maintain FIFO for same priority
           entry = (-priority, self._counter, name, data)
           heapq.heappush(self._queue, entry)
           self._counter += 1

       def get_next_job(self) -> Optional[Tuple[str, Dict[str, Any]]]:
           if not self._queue:
               return None
           _, _, name, data = heapq.heappop(self._queue)
           return (name, data)
   ```

4.  **Check Requirements:**
   - `add_job` accepts optional priority (default=0) -> Yes
   - Higher priority processed first -> Yes (using `-priority`)
   - Same priority FIFO -> Yes (using `_counter`)
   - `get_next_job() -> tuple[str, dict] | None` -> Yes
   - Priority levels 0, 1, 2 -> Handled naturally
   - Example matches -> Yes

   Wait, the type hint in the requirement is `tuple[str, dict] | None`. I'll use that exact signature.
   Also, should I validate priority levels? The requirement says "Priority levels: 0, 1, 2" but doesn't strictly say to enforce them. I'll assume they're just informational, but I could add a check if needed. Usually, it's fine to just use the values as-is.

   Let's refine the type hints to match Python 3.10+ syntax as requested: `tuple[str, dict] | None`
   I'll import `Optional` or just use the union syntax directly.

   One thing: `heapq` stores tuples, and comparison works element-by-element. `(-priority, self._counter, name, data)` will compare `data` if priorities and counters are equal, but counters are unique, so it won't matter. Actually, `self._counter` ensures uniqueness, so `data` won't be compared. That's safe.

   Let's write it out carefully.

   ```python
   import heapq
   from typing import Optional

   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)
   ```

   Wait, should I keep the `priority` in the returned tuple? The requirement says `get_next_job() -> tuple[str, dict] | None`, so just name and data.

   Check FIFO requirement: "Jobs with the same priority should maintain FIFO order". The counter ensures this.

   Check priority: "Higher priority jobs should be processed before lower priority jobs". Using `-priority` in a min-heap achieves this.

   All good.

   One minor point: The example shows `queue.add_job("normal", {"type": "normal"}, priority=0)`. My signature matches.
   I'll make sure the code is self-contained and matches the exact request.

   Should I include type hints for `data`? The requirement says `dict`, so I'll stick with that.
   I'll use `from typing import Optional` if needed, but Python 3.10+ supports `tuple[str, dict] | None` natively. I'll just write it as requested.

   Let's double check the exact signature requested: `get_next_job() -> tuple[str, dict] | None`
   I'll implement exactly that.

   Code structure:
   ```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)
   ```

   Is there any edge case? What if `data` contains uncomparable types? Since `self._counter` is unique, `heapq` will never compare `name` or `data` because the second element (`self._counter`) will always differ. So it's safe.

   One thing: The requirement says "Modify `add_job` to accept an optional priority parameter (default=0)". This implies there might be an existing class, but I'll provide the full class definition as is standard.

   I'll output just the code as requested.
   Ready.✅
   Output matches response.✅
   Proceed. 
   Self-Correction/Verification during thought:
   - Should I validate priority? Not required.
   - Should I use `collections.deque` per priority? `heapq` is simpler and standard.
   - Type hints: `tuple[str, dict] | None` is valid in Python 3.10+. I'll keep it.
   - The example uses `queue.add_job("normal", {"type": "normal"}, priority=0)`. Matches.
   - All constraints met.

   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)
   ```
   Looks solid. Output matches exactly.✅
   One minor thing: `tuple[str, dict] | None` might cause a `SyntaxError` in Python < 3.10, but it's standard now. I'll stick with it as requested. If needed, I could use `Optional[tuple[str, dict]]`, but the prompt explicitly uses `tuple[str, dict] | None`. I'll follow the prompt.

   All good. Output matches. 
   Proceeds. 
   [Output Generation] -> *Proceeds*
   *(Self-Correction/Refinement during thought)*: 
   Wait, should I include `from __future__ import annotations` to be safe? Not necessary unless specified. The prompt uses modern syntax. I'll just output the code as is.
   The prompt says "Write only the Python code, no explanations."
   I will output exactly that.
   Done. 
   [Output Generation] -> *Proceeds*

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