<reasoning_content>
Thinking Process:

1.  **Understand the Goal**: The user wants a Python implementation of a priority-based job queue.
2.  **Analyze Requirements**:
    *   Class name implied: `JobQueue` (based on example usage).
    *   Method `add_job(job_name: str, job_data: dict, priority: int = 0)`: Adds a job. Higher priority comes first.
    *   Method `get_next_job() -> tuple[str, dict] | None`: Returns the highest priority job.
    *   Priority Logic: Higher number = higher priority.
    *   Tie-breaking: FIFO (First-In-First-Out) for same priority.
    *   Output format: Only Python code.

3.  **Choose Data Structure**:
    *   We need a way to store jobs and efficiently retrieve the max priority job.
    *   A heap is a common choice for priority queues.
    *   Python's `heapq` module implements a min-heap.
    *   To get max-heap behavior using `heapq`, we can store negative priorities.
    *   To handle FIFO for same priorities, we need a tie-breaker. We can use a counter or timestamp. Since `heapq` compares tuples element by element, a counter works well.
    *   Tuple structure for heap: `(priority, counter, job_name, job_data)`.
    *   Since we want higher priority first, we store `-priority`.
    *   Since we want FIFO, smaller counter comes first.

4.  **Refining the Heap Structure**:
    *   Item: `(-priority, counter, job_name, job_data)`
    *   `add_job`:
        *   Increment counter.
        *   Push `(-priority, counter, job_name, job_data)` to heap.
    *   `get_next_job`:
        *   If heap empty, return `None`.
        *   Pop item.
        *   Return `(job_name, job_data)`.

5.  **Drafting the 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):
           # Negative priority because heapq is a min-heap
           # Counter ensures FIFO for same priorities
           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
           # Pop the item with smallest negative priority (highest actual priority)
           # and smallest counter (earliest added)
           _, _, job_name, job_data = heapq.heappop(self._queue)
           return (job_name, job_data)
   ```

6.  **Review against Constraints**:
    *   `add_job` accepts optional priority (default=0)? Yes.
    *   Higher priority processed before lower? Yes (`-priority` logic).
    *   FIFO for same priority? Yes (`counter` logic).
    *   `get_next_job` returns `tuple[str, dict] | None`? Yes.
    *   Example usage matches?
        *   `add_job("normal", ..., 0)` -> `(-0, 0, "normal", ...)`
        *   `add_job("critical", ..., 2)` -> `(-2, 1, "critical", ...)`
        *   `add_job("high", ..., 1)` -> `(-1, 2, "high", ...)`
        *   Heap order: `(-2, 1, ...)` (Critical) < `(-1, 2, ...)` (High) < `(-0, 0, ...)` (Normal).
        *   Pop 1: Critical. Correct.

7.  **Final Polish**:
    *   Ensure type hints are correct.
    *   Ensure imports are present.
    *   No explanations in output.

8.  **Alternative Implementation Consideration**:
    *   Could use a list and sort, but heap is O(log n) insertion and O(1) peek (or O(log n) pop), which is better than O(n) scan for `get_next_job`. The prompt doesn't strictly specify performance, but a priority queue usually implies heap.
    *   Could use `collections.deque` if it was just FIFO, but priority is needed.
    *   The heap approach is standard.

9.  **Constructing Final Output**:
    *   Just 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):
           # Use negative priority for max-heap behavior with heapq (min-heap)
           # Use counter to maintain FIFO order for same priorities
           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)
   ```

   Wait, checking the return type hint syntax `tuple[str, dict] | None`. This requires Python 3.10+. The prompt uses it, so I will use it. If strict compatibility with older Python is needed, `Optional[Tuple[str, dict]]` would be safer, but usually, modern syntax is preferred in these prompts unless specified otherwise. I'll stick to the syntax provided in the prompt's requirement.

   One detail: The prompt asks for `get_next_job() -> tuple[str, dict] | None`.
   The code looks solid.

   Let's double check the example logic.
   `queue = JobQueue()`
   1. `add_job("normal", ..., 0)`. Heap: `[(-0, 0, "normal", ...)]`. Counter: 1.
   2. `add_job("critical", ..., 2)`. Heap: `[(-2, 1, "critical", ...), (-0, 0, "normal", ...)]` (after heapify). Counter: 2.
   3. `add_job("high", ..., 1)`. Heap: `[(-2, 1, "critical", ...), (-0, 0, "normal", ...), (-1, 2, "high", ...)]`. Counter: 3.
   Wait, heap structure isn't strictly sorted list, but `heappop` returns the smallest item.
   Comparisons:
   `(-2, 1, ...)` vs `(-1, 2, ...)` -> -2 < -1, so Critical is smallest.
   `(-2, 1, ...)` vs `(-0, 0, ...)` -> -2 < 0, so Critical is smallest.
   So `get_next_job` returns Critical. Correct.

   What if priorities are equal?
   1. `add_job("A", ..., 0)`. Heap: `[(-0, 0, "A", ...)]`. Counter: 1.
   2. `add_job("B", ..., 0)`. Heap: `[(-0, 0, "A", ...), (-0, 1, "B", ...)]`.
   `(-0, 0)` vs `(-0, 1)`. 0 < 1. So "A" is popped first. FIFO maintained. Correct.

   Final check on imports. `heapq` is standard library.

   One minor thing: The prompt asks for `get_next_job() -> tuple[str, dict] | None`.
   The implementation returns exactly that.

   Code looks good.

   ```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):
           # heapq is a min-heap, so we negate priority to get max-heap behavior
           # counter ensures FIFO order for jobs with the same priority
           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)
   ```
   Looks complete.

   Wait, is `job_data` passed by reference? Yes, dicts are mutable. This is standard behavior for queues unless deep copy is requested, which wasn't.

   One potential issue: `tuple[str, dict] | None` syntax is Python 3.10+. The prompt uses it in the requirement text, so it's safe to assume the environment supports it.

   I will provide the solution now.

   Wait, looking at the code `tuple[str, dict] | None`.
   If I want to be super safe regarding Python versions, I could use `typing.Optional` and `typing.Tuple`, but the prompt explicitly wrote `tuple[str, dict] | None` in the method signature requirement. I will follow that.

   Final check: "Write only the Python code, no explanations."

   ```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):
           # Use negative priority for max-heap behavior (higher priority first)
           # Use counter to preserve FIFO order for equal priorities
           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 perfect.

   Wait, just to be pedantic about the prompt's `get_next_job` signature: `get_next_job() -> tuple[str, dict] | None`.
   My code has `def get_next_job(self) -> tuple[str, dict] | None:`. Matches.

   The prompt example:
   `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()`

   My implementation handles this perfectly.

   One edge case: What if `job_data` is not a dict? The type hint says `dict`. I'll stick to the hint.
   What if `job_name` is not str? Type hint says `str`.

   Ready.

   Wait, I should check if `typing` imports are needed for the type hints if I were writing a full file, but usually for these snippets, built-in generic types (like `tuple` and `dict` in hints) work in 3.9+, and `|` union works in 3.10+. The prompt used the syntax, so I will output code that uses the syntax. No extra imports needed other than `heapq`.

   Actually, to be safe against `NameError` if the user runs this on 3.9 without `from __future__ import annotations`, I should probably stick to standard imports or just rely on the environment matching the prompt's syntax. The prompt used `tuple[str, dict] | None`. I will reproduce that.

   Wait, actually, I don't need to import `tuple` or `dict` or `None` as they are built-ins. I just need `heapq`.

   Final Code Structure:
   ```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):
           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 concise and correct.

   Double check: "Higher priority jobs should be processed before lower priority jobs".
   Priority 2 (Critical) vs 0 (Normal).
   -2 vs 0. -2 is smaller. `heappop` returns smallest. So 2 comes out first. Correct.

   Double check: "Jobs with the same priority should maintain FIFO order".
   Counter increases.
   Item 1: (-0, 0, ...)
   Item 2: (-0, 1, ...)
   0 < 1. Item 1 comes out first. Correct.

   Double check: "add_job to accept an optional priority parameter (default=0)".
   `def add_job(self, job_name: str, job_data: dict, priority: int = 0):`. Correct.

   Double check: "get_next_job() -> tuple[str, dict] | None".
   Returns `(job_name, job_data)` which is a tuple of str and dict. Or None. Correct.

   Looks good.

   One thought: Does the user want the class definition or just the methods? "Implement priority-based job scheduling... Modify add_job... Add get_next_job". Usually implies writing the class. The example shows `queue = JobQueue()`. So the class is required.

   I will write the full class.

   One tiny detail: Does the prompt imply I should keep existing methods if they existed? "Modify add_job... Add get_next_job". Since no existing code was provided, I must create the class from scratch satisfying the interface.

   Final check on constraints.
   "Write only the Python code, no explanations."

   I will output 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):
           # Use negative priority for max-heap behavior (higher priority value = processed first)
           # Use counter to ensure FIFO order for jobs with the same priority
           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 seems robust.

   Wait, is `job_data` required to be a dict? The prompt says `job_data: dict` in the example and type hint. Yes.

   One detail: The prompt example `queue.add_job("normal", {"type": "normal"}, priority=0)`.
   My signature: `add_job(self, job_name: str, job_data: dict, priority: int = 0)`.
   Matches.

   I'm confident.

   One last check on the type hint syntax in the output.
   If the environment is Python 3.9, `tuple[str, dict]` works, but `|` does not.
   If the environment is Python 3.10+, both work.
   Given the prompt used `|`, I will use `|`.

   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):
        # heapq is a min-heap, so we negate priority to process higher numbers first
        # counter ensures FIFO order for jobs with the same priority
        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)
```
   The comments are helpful but the prompt said "no explanations". Comments in code are usually fine, but I'll keep them minimal or remove them to be safe. "Write only the Python code" usually allows comments, but strict interpretation might mean just logic. I'll keep minimal comments or none. I'll remove comments to be strictly "code only".

   Actually, comments are part of code. But to be safest, I'll remove them.

   Revised 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):
        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 cleaner.

   Wait, I should check if `typing` is needed for `tuple` or `dict` in older versions? No, `tuple` and `dict` are built-in types that can be used in annotations in Python 3.9+. The `|` union operator requires 3.10+. Since the prompt used it, I assume 3.10+.

   If I want to be extremely compatible, I could use `Optional[Tuple[str, dict]]` but that requires `from typing import ...` and changes the signature string from the prompt. I will stick to the prompt's syntax.

   Final check.
   Prompt: `get_next_job() -> tuple[str, dict] | None`
   My code: `def get_next_job(self) -> tuple[str, dict] | None:`
   Prompt: `add_job` ... optional priority (default=0)
   My code: `def add_job(self, job_name: str, job_data: dict, priority: int = 0):`
   Prompt: Higher priority first.
   My code: `-priority`.
   Prompt: FIFO for same priority.
   My code: `self._counter`.
   Prompt: Return tuple or None.
   My code: Returns tuple or None.

   Looks solid.

   One thing: `job_data` is a dict reference. If the caller modifies it later, it affects the queue. This is standard Python behavior. If isolation was needed, `copy.deepcopy` would be required, but it's not requested and adds overhead.

   I will output the code now.

</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):
        # Use negative priority for max-heap behavior (higher priority value processed first)
        # Use counter to maintain FIFO order for jobs with the same priority
        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>