<reasoning_content>
Here's a thinking process:

1.  **Understand the Goal**: The user wants a priority-based job scheduling queue in Python. The queue needs to support adding jobs with an optional priority (default 0), where higher priority jobs are processed first. Jobs with the same priority must maintain FIFO order. There should be a `get_next_job()` method that returns the highest priority job as a tuple `(str, dict) | None`.

2.  **Identify Key Requirements**:
   - `add_job(name: str, job_data: dict, priority: int = 0)`
   - Higher priority processed first
   - FIFO for same priority
   - `get_next_job() -> tuple[str, dict] | None`
   - Priority levels: 0 (Normal), 1 (High), 2 (Critical) - though the code just needs to handle integer priorities correctly, higher number = higher priority.
   - Output: Only Python code, no explanations.

3.  **Choose Data Structure**:
   - A priority queue is needed. Python's `heapq` module provides a min-heap. Since we want higher priority first, we can negate the priority or use a max-heap approach.
   - To maintain FIFO for same priorities, we need a tie-breaker. We can use a counter that increments with each `add_job` call. Since `heapq` is a min-heap, we can store tuples: `(-priority, counter, name, job_data)`. This way, higher priority (larger number) becomes smaller when negated, so it comes first. For same priority, smaller counter comes first (FIFO).
   - Alternatively, use `queue.PriorityQueue` from the standard library, but `heapq` is simpler and more flexible for this use case. I'll stick with `heapq`.

4.  **Design the Class**:
   ```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, job_data: dict, priority: int = 0) -> None:
           # Store as (-priority, counter, name, job_data)
           heapq.heappush(self._heap, (-priority, self._counter, name, job_data))
           self._counter += 1

       def get_next_job(self) -> Optional[Tuple[str, dict]]:
           if not self._heap:
               return None
           # Pop the smallest tuple (which corresponds to highest priority, then earliest added)
           _, _, name, job_data = heapq.heappop(self._heap)
           return (name, job_data)
   ```

5.  **Check Requirements**:
   - `add_job` accepts optional priority parameter (default=0)? Yes.
   - Higher priority jobs processed before lower? Yes, because of `-priority`.
   - Same priority maintains FIFO? Yes, because of `_counter`.
   - `get_next_job() -> tuple[str, dict] | None`? Yes.
   - Only Python code? Yes.
   - 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", {...}), (0, 0, "normal", {...}), (-1, 2, "high", {...})`
     - `heappop` returns `(-2, 1, "critical", {...})` -> returns `("critical", {...})`. Correct.
   - Type hints: The prompt uses `tuple[str, dict] | None`, which is Python 3.10+ syntax. I'll use `Optional[Tuple[str, dict]]` or keep the modern syntax. I'll stick to modern syntax as requested, or use standard typing. I'll use `typing.Optional` and `typing.Tuple` for broader compatibility, or just the modern syntax since it's in the prompt. I'll use `from typing import Tuple, Optional` to be safe, or just match the prompt's style. Actually, I'll just use the prompt's style: `tuple[str, dict] | None`.

   Let's refine the code to match exactly:
   ```python
   import heapq
   from typing import Optional, Tuple

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

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

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

   Wait, `Optional[tuple[str, dict]]` is fine. I'll use standard typing imports to be safe, or just rely on Python 3.10+ syntax as in the prompt. The prompt uses `tuple[str, dict] | None`, so I'll use that.

   Let's double check the exact signature requested: `get_next_job() -> tuple[str, dict] | None`
   I'll add `from __future__ import annotations` if needed, but it's fine without it in modern Python. I'll just write it directly.

   One minor thing: `job_data` is passed by reference. That's fine for this exercise.
   Should I handle `name` and `job_data` types explicitly? The prompt says `tuple[str, dict] | None`, so I'll stick to that.

   Let's verify the heap behavior with negative priority:
   Priority 2 -> -2
   Priority 1 -> -1
   Priority 0 -> 0
   Min-heap pops smallest: -2 comes first. Correct.
   Counter ensures FIFO for same priority. Correct.

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

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

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

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

   Is there any edge case? Empty queue returns None. Correct.
   Type hints: `tuple[str, dict] | None` is valid in Python 3.10+. I'll keep it.
   The prompt says "Write only the Python code, no explanations."
   I will output exactly the code.

   One thing: `job_data` might be mutated later, but that's standard for queues. No deep copy requested.
   I'll make sure the class name is `JobQueue` as implied by the example.
   All good.

   Final check of the code:
   ```python
   import heapq
   from typing import Optional

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

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

       def get_next_job(self) -> tuple[str, dict] | None:
           if not self._heap:
               return None
           _, _, name, job_data = heapq.heappop(self._heap)
           return (name, job_data)
   ```
   This matches all requirements. I'll output it. 
   One minor adjustment: I'll use `typing.Optional` and `typing.Tuple` for broader compatibility, or just stick to the prompt's syntax. The prompt uses `tuple[str, dict] | None`, so I'll keep it. It's fine.
   I'll remove the `from typing import Optional` since I'm not using it in the return type annotation in the final version. Actually, I'll just use `Optional` if needed, but `| None` is standard now. I'll stick to `| None`.

   Ready. Output matches exactly.✅
   I will generate the code block now. 
   Self-Correction/Verification during thought:
   - Does `heapq` handle tuples correctly? Yes, it compares element by element. `(-priority, counter, name, job_data)` will compare priority first, then counter. Since name and job_data are different types, if priorities and counters are equal (impossible due to counter), it would fail, but counter is unique, so it's safe.
   - The prompt example: `queue.add_job("normal", {"type": "normal"}, priority=0)` - matches signature.
   - All good.
   Output matches request.✅
   Proceeds. 
   Output generation. 
   ```python
   import heapq
   from typing import Optional, Tuple

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

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

       def get_next_job(self) -> tuple[str, dict] | None:
           if not self._heap:
               return None
           _, _, name, job_data = heapq.heappop(self._heap)
           return (name, job_data)
   ```
   Actually, I'll remove the `from typing` imports since they aren't strictly necessary with `| None` and `tuple`/`dict` built-ins in modern Python, but keeping them doesn't hurt. I'll stick to minimal imports. The prompt uses `tuple[str, dict] | None`, which is valid in Python 3.10+. I'll just output the class.
   Final code:
   ```python
   import heapq

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

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

       def get_next_job(self) -> tuple[str, dict] | None:
           if not self._heap:
               return None
           _, _, name, job_data = heapq.heappop(self._heap)
           return (name, job_data)
   ```
   This is clean and meets all requirements. Output matches.✅
   Proceeds. 
   [Output Generation] -> *Proceeds*
   *(Self-Correction/Refinement during thought)*: Wait, `tuple[str, dict] | None` might cause a syntax error in Python < 3.10 if not using `from __future__ import annotations`. To be safe, I'll use `Optional[Tuple[str, dict]]` or just keep the prompt's exact syntax since it's standard now. I'll stick to the prompt's syntax. It's fine.
   All good.✅
   Output matches. 
   [Final Check of the Prompt]: "Write only the Python code, no explanations." -> I will output just the code block.
   Done. 
   *Output Generation* (matches the refined code)
   ```python
   import heapq

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

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

       def get_next_job(self) -> tuple[str, dict] | None:
           if not self._heap:
               return None
           _, _, name, job_data = heapq.heappop(self._heap)
           return (name, job_data)
   ```
   This is correct. Proceeds. 
   [Output] -> *Code Block* (as requested)
   *(Done.)*

</reasoning_content>

<content>
```python
import heapq

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

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

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