<reasoning_content>
Here's a thinking process:

1.  **Understand User Requirements:**
   - Implement a priority-based job scheduling system for a queue.
   - Modify `add_job` to accept an optional `priority` parameter (default=0).
   - Higher priority jobs should be processed first.
   - 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, default), 1 (High), 2 (Critical).
   - Provide only the Python code, no explanations.

2.  **Identify Key Data Structures & Algorithms:**
   - Need a queue that supports priority ordering and FIFO for same priorities.
   - Python's `heapq` module is perfect for priority queues.
   - Since higher priority should come first, and `heapq` is a min-heap, I need to negate the priority or use a custom comparison. Alternatively, I can store `(-priority, insertion_order, job_name, job_data)` in the heap.
   - To maintain FIFO for same priorities, I'll use a monotonic counter for insertion order.
   - `heapq` stores tuples, and Python compares tuples element-wise. So `(-priority, insertion_order, job_name, job_data)` will work perfectly: lower `-priority` means higher priority, and lower `insertion_order` means earlier added.

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

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

       def add_job(self, name: str, data: dict, priority: int = 0) -> None:
           # Use negative priority for max-heap behavior with min-heap
           # Counter ensures FIFO for same priority
           heapq.heappush(self._heap, (-priority, self._counter, name, data))
           self._counter += 1

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

4.  **Check Requirements:**
   - `add_job` accepts optional priority parameter (default=0)? Yes.
   - Higher priority jobs processed first? Yes, `-priority` makes higher priority values pop first.
   - Same priority maintains FIFO? Yes, `_counter` increases monotonically, so earlier jobs have smaller counter values and pop first.
   - `get_next_job() -> tuple[str, dict] | None`? Yes, returns `Optional[Tuple[str, dict]]`.
   - Priority levels 0, 1, 2? Handled naturally by the integer priority.
   - 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", {...}), (-1, 2, "high", {...}), (0, 0, "normal", {...})
     - get_next_job() pops (-2, 1, ...) -> returns ("critical", {...})
     - Matches example exactly.

5.  **Refine Code:**
   - Add type hints as requested/implied.
   - Ensure imports are included.
   - Keep it concise as requested ("Write only the Python code, no explanations.").
   - Check typing: `from typing import Optional, Tuple, Dict` is good. Python 3.10+ supports `tuple[str, dict] | None`, but I'll stick to standard typing or use the modern syntax if appropriate. The prompt uses `tuple[str, dict] | None`, so I'll use that or `Optional[Tuple[str, dict]]`. I'll stick to `Optional[Tuple[str, dict]]` for broader compatibility, or just use the modern syntax since the prompt uses it. Actually, I'll just use `from typing import Optional, Tuple, Dict` and `Optional[Tuple[str, dict]]` to be safe, or directly use `tuple[str, dict] | None` if assuming Python 3.10+. I'll stick to `typing` module for safety, but the prompt's syntax is fine. I'll just write it cleanly.

   Let's draft it:
   ```python
   import heapq
   from typing import Optional, Tuple, Dict

   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) -> Optional[Tuple[str, Dict]]:
           if not self._heap:
               return None
           _, _, name, data = heapq.heappop(self._heap)
           return name, data
   ```

   Wait, the prompt says `tuple[str, dict] | None`. I'll use that exact signature if possible, but `typing` is fine. I'll just use `from typing import Optional, Tuple, Dict` and `Optional[Tuple[str, Dict]]`. Or I can just use the modern syntax directly since it's valid in 3.10+. I'll stick to standard typing for maximum compatibility, but it doesn't matter much.

   Let's double check the FIFO requirement. `heapq` is stable for tuples? Actually, `heapq` doesn't guarantee stability for equal elements, but since we include `_counter`, all elements in the heap are unique. So it will strictly follow the tuple ordering: first by `-priority`, then by `_counter`. This guarantees FIFO for same priorities.

   One minor thing: `data` is a dict. The prompt example shows `{"type": "normal"}`. That's fine.

   Should I make a copy of the data dict to avoid mutation issues? Not strictly required by the prompt, but good practice. I'll skip it to keep it simple, as the prompt doesn't specify.

   Check signature: `get_next_job() -> tuple[str, dict] | None`
   I'll write exactly that.

   Final code structure:
   ```python
   import heapq
   from typing import Optional, Tuple, Dict

   class JobQueue:
       def __init__(self):
           self._heap: list = []
           self._counter: int = 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) -> Optional[Tuple[str, Dict]]:
           if not self._heap:
               return None
           _, _, name, data = heapq.heappop(self._heap)
           return name, data
   ```

   Wait, `tuple[str, dict] | None` is Python 3.10+ syntax. I'll use `from typing import Optional, Tuple, Dict` and `Optional[Tuple[str, Dict]]` to be safe, or just use the exact syntax from the prompt. I'll stick to `typing` module. Actually, I'll just write it cleanly.

   Let's verify the example:
   ```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
   ```
   This will work perfectly.

   One detail: `get_next_job` should return `tuple[str, dict] | None`. I'll use `from typing import Optional, Tuple, Dict` and return `Optional[Tuple[str, Dict]]`. It's functionally identical.

   I'll produce the code now. No extra text.
   I'll make sure imports are at the top.
   All requirements met.
   Ready. 
   Output matches the request.✅
   Code:
   ```python
   import heapq
   from typing import Optional, Tuple, Dict

   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) -> Optional[Tuple[str, Dict]]:
           if not self._heap:
               return None
           _, _, name, data = heapq.heappop(self._heap)
           return name, data
   ```
   Looks solid. I'll output exactly this. No extra text.✅
   One minor adjustment: The prompt uses `tuple[str, dict] | None`. I'll use that exact syntax in the type hint to match the prompt, assuming Python 3.10+. Actually, `from __future__ import annotations` isn't needed. I'll just use `Optional[Tuple[str, dict]]` to be safe, or stick to the prompt's syntax. It doesn't matter much. I'll keep it simple.
   I'll output the code block only.
   Done. 
   Self-Correction/Verification during thought:
   - Does `heapq` handle negative priorities correctly for max-heap behavior? Yes, `-priority` means higher priority becomes more negative, so it pops first.
   - FIFO for same priority? Yes, `_counter` ensures strict ordering.
   - Return type matches? Yes.
   - Default priority 0? Yes.
   - All good.
   Output matches. 
   Proceeds. 
   [Output Generation] -> *Proceeds*
   *(Note: I'll format it exactly as requested, just the code)*
   ```python
   import heapq
   from typing import Optional, Tuple, Dict

   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) -> Optional[Tuple[str, Dict]]:
           if not self._heap:
               return None
           _, _, name, data = heapq.heappop(self._heap)
           return name, data
   ```
   This is correct and complete. I will output it now. 
   One thing: `tuple[str, dict] | None` is in the prompt. I'll use `from typing import Optional, Tuple, Dict` and `Optional[Tuple[str, Dict]]` to be strictly compatible with older Python versions, but it's fine either way. I'll stick with it.
   All good. 
   Output matches response. 
   [Done] 
   *Self-Correction/Refinement during generation prep*: 
   I'll make sure the type hints exactly match the prompt's style if possible, but `typing` is standard. I'll just output the code as is. It's clean and correct.
   Final check of the prompt: "Write only the Python code, no explanations." -> I will strictly follow this.
   Code is ready.✅
   Output generation. 
   [Output] -> *Proceeds*

</reasoning_content>

<content>
```python
import heapq
from typing import Optional, Tuple, Dict

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) -> Optional[Tuple[str, Dict]]:
        if not self._heap:
            return None
        _, _, name, data = heapq.heappop(self._heap)
        return name, data
```
</content>