<reasoning_content>
The user wants a Python implementation of a priority-based job scheduling queue.
Key requirements:
1. `add_job(name, data, priority=0)` method
2. Higher priority jobs processed first
3. FIFO for same priority
4. `get_next_job()` returns `(name, data)` or `None`
5. Priority levels: 0 (Normal), 1 (High), 2 (Critical)
6. Output only Python code, no explanations.

I'll use Python's `heapq` module for efficient priority queue implementation. Since `heapq` is a min-heap, I need to negate priorities to get higher priority first, or use a custom comparison. Actually, `heapq` orders by the first element of the tuple. So I can use `(-priority, counter, name, data)` where `counter` ensures FIFO order for same priorities.

Let's 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):
        # Negate priority so higher priority comes first in min-heap
        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, the requirement says `get_next_job() -> tuple[str, dict] | None`. The return type hint is fine.
I should make sure the type hints match exactly.
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)

job = queue.get_next_job()  # Returns critical job first
```

Let's verify the behavior:
- `add_job("normal", ..., 0)` -> pushes `(0, 0, "normal", ...)`
- `add_job("critical", ..., 2)` -> pushes `(-2, 1, "critical", ...)`
- `add_job("high", ..., 1)` -> pushes `(-1, 2, "high", ...)`
Heap order: `(-2, 1, ...)` is smallest, so it pops first. Correct.
Same priority: counter increases, so FIFO is maintained. Correct.

One minor thing: `heapq` compares tuples element by element. If priorities are equal, it compares counters, which are strictly increasing, so no issue with comparing `name` or `data`.

I'll write the complete class with type hints as requested.
Should I include `from typing import Tuple, Optional` or use modern syntax `tuple[str, dict] | None`? The prompt uses `tuple[str, dict] | None`, so I'll stick with that (Python 3.10+ syntax). I'll add `import heapq` at the top.

Let's assemble the 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)
```

Check requirements:
1. Modify `add_job` to accept optional priority parameter (default=0) -> Done
2. Higher priority jobs processed before lower -> Done (negated priority)
3. Same priority maintains FIFO -> Done (counter)
4. `get_next_job() -> tuple[str, dict] | None` -> Done
5. Priority levels mentioned in prompt are just documentation, no need to enforce unless specified. I'll assume integer input is fine.
6. Write only Python code -> Done.

One thing: `tuple[str, dict] | None` syntax requires Python 3.10+. That's fine.
I'll make sure the code is clean and matches exactly.
No extra text.
Ready.✅
Let's double check the prompt: "Write only the Python code, no explanations."
I will output just the code block.
All good. 
One minor point: `data` is a dict, but in the example it's `{"type": "normal"}`. The type hint `dict` is fine.
I'll provide the implementation. 
Proceed. 
Output matches the solution. 
Self-Correction/Verification during thought:
Is there any chance `heapq` might compare `name` if priorities and counters are equal? Counters are unique and strictly increasing, so they will never be equal. So tuple comparison stops at counter. Safe.
What about `get_next_job` return type? `tuple[str, dict] | None` is correct.
I'll wrap it in a code block.
Done. 
Output generation. 
```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. Matches all constraints. No extra text. Proceeds. 
Output matches response. 
Done. 
[Final Check]
- `add_job` accepts `priority=0`? Yes.
- Higher priority first? Yes, `-priority` makes 2 become -2, which is smaller than -1 and 0, so it pops first.
- FIFO for same priority? Yes, `_counter` ensures strict ordering.
- `get_next_job` signature matches? Yes.
- Only Python code? Yes.
All good. 
Output matches. 
Proceeds. 
[Output Generation] -> *Self-Correction/Refinement during generation prep*: 
Wait, should I include type hints for `add_job` parameters as in the prompt? The prompt says `add_job` to accept an optional priority parameter. I'll add type hints for clarity but it's not strictly required. I'll keep it simple.
The prompt uses `tuple[str, dict] | None`, so I'll stick to that.
Everything is fine.
Output matches the code block above.✅
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>