<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 (dict), and optional priority (default=0).
   - Higher priority jobs processed first.
   - Same priority jobs maintain FIFO order.
   - `get_next_job()` method: returns `tuple[str, dict] | None` for the highest priority job.
   - Priority levels: 0=Normal, 1=High, 2=Critical (but the logic should work for any integer, with higher = higher priority).
   - Output: Only Python code, no explanations.

2.  **Identify Key Data Structures:**
   - Need a priority queue that supports:
     - Higher priority first
     - FIFO for same priority
   - Python's `heapq` module implements a min-heap. To make it a max-heap for priority, I can negate the priority.
   - To maintain FIFO for same priority, I need a tie-breaker. I can use a counter/incrementing sequence that increases for each job added. Since `heapq` compares tuples element by element, I can store `(neg_priority, counter, job_name, job_data)`.
   - `neg_priority` ensures higher priority comes first.
   - `counter` ensures FIFO order (lower counter = added earlier).
   - `job_name` and `job_data` are the actual payload.

3.  **Design the Class:**
   ```python
   import heapq

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

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

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

4.  **Check Requirements:**
   - `add_job` accepts optional priority parameter (default=0)? Yes.
   - Higher priority jobs processed first? Yes, using `-priority` in min-heap.
   - Same priority maintains FIFO? Yes, using `_counter`.
   - `get_next_job() -> tuple[str, dict] | None`? Yes.
   - Priority levels mentioned (0,1,2) are just examples, the logic handles them correctly.
   - Only Python code? Yes.

   Wait, should I include type hints exactly as requested? The prompt says `get_next_job() -> tuple[str, dict] | None`. I'll use that.
   I should also consider if the prompt expects a specific class name. It says "queue = JobQueue()", so `class JobQueue:` is correct.
   I'll add necessary imports.

   Let's double-check the tuple unpacking and return type.
   `heapq.heappop` returns the tuple. I extract `job_name` and `job_data`.
   Return type matches.
   The counter ensures FIFO. Since `_counter` starts at 0 and increments, lower counter values are popped first, which matches FIFO.
   Negative priority ensures higher priority values are popped first.
   All good.

   One minor thing: The prompt says `tuple[str, dict] | None`. In Python 3.9+, this is valid. I'll assume modern Python. If compatibility is needed, I could use `typing.Tuple` and `typing.Optional`, but the prompt uses the modern syntax, so I'll stick with it.

   Code structure:
   ```python
   import heapq
   from typing import Tuple, Optional

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

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

       def get_next_job(self) -> Tuple[str, dict] | None:
           if not self._queue:
               return None
           _, _, job_name, job_data = heapq.heappop(self._queue)
           return (job_name, job_data)
   ```
   Actually, I'll just use the exact syntax from the prompt for type hints to be safe, or stick to standard typing. The prompt uses `tuple[str, dict] | None`, so I'll use that. I'll import `heapq`.

   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
   ```
   With my implementation:
   - normal: (-0, 0, "normal", ...)
   - critical: (-2, 1, "critical", ...)
   - high: (-1, 2, "high", ...)
   Heap order: (-2, 1, ...), (-1, 2, ...), (-0, 0, ...)
   Pop gives critical. Correct.
   If same priority: (-1, 2, ...), (-1, 3, ...) -> pops 2 first. Correct.

   All requirements met. I will output only the code.
   I'll make sure the code is clean and self-contained.
   One thing: `tuple[str, dict] | None` is Python 3.10+ syntax. I'll keep it as requested.
   I'll add `from typing import Tuple, Optional` just in case, but it's not strictly necessary if using modern syntax. I'll stick to the prompt's syntax.
   Actually, I'll just write the class without extra imports unless needed. `heapq` is needed.
   I'll write it out.

   Final check of the prompt: "Write only the Python code, no explanations."
   I will output exactly the code block.

   ```python
   import heapq

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

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

       def get_next_job(self) -> tuple[str, dict] | None:
           if not self._queue:
               return None
           _, _, job_name, job_data = heapq.heappop(self._queue)
           return (job_name, job_data)
   ```
   This looks solid. I'll output it.✅
   One minor consideration: Should I handle the case where `job_data` might not be a dict? The prompt says `dict`, so it's fine.
   The prompt says `tuple[str, dict] | None`, I'll use that exact type hint.
   All good. Output matches request. 
   Proceeds. 
   Output generation. 
   [Done] 
   Self-Correction/Refinement during thought: 
   Wait, `tuple[str, dict] | None` is valid in Python 3.10+. I'll keep it. 
   I'll make sure the code is exactly as requested. No extra fluff.
   The prompt says "Write only the Python code, no explanations."
   I will provide just the code block.
   Ready. 
   Output matches the refined code.✅
   [Output Generation] -> *Proceeds*
   *(Self-Correction/Verification during thought)*: 
   Is there any edge case? Empty queue returns None. Correct.
   Priority default is 0. Correct.
   Higher priority first. Correct.
   FIFO for same priority. Correct.
   Type hints match. Correct.
   All good. 
   Output matches. 
   [Final Code]
   ```python
   import heapq

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

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

       def get_next_job(self) -> tuple[str, dict] | None:
           if not self._queue:
               return None
           _, _, job_name, job_data = heapq.heappop(self._queue)
           return (job_name, job_data)
   ```
   This is correct and complete. Output matches. 
   Proceeds. 
   [Output Generation] (done)
   *(Note: I'll make sure the formatting is exact and contains only the code as requested.)*
   All steps verified. Output matches response. 
   [Done]

</reasoning_content>

<content>
```python
import heapq

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

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

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