<reasoning_content>
Thinking Process:

1.  **Analyze the Request:**
    *   Goal: Implement priority-based job scheduling for a queue.
    *   Requirements:
        1.  Modify `add_job` to accept an optional `priority` parameter (default=0).
        2.  Higher priority jobs processed before lower priority jobs.
        3.  Jobs with the same priority maintain FIFO order.
        4.  Add `get_next_job() -> tuple[str, dict] | None` to retrieve the highest priority job.
    *   Priority Levels: 0 (Normal), 1 (High), 2 (Critical). Note: The example shows `priority=2` as critical and `priority=1` as high. This implies higher integer = higher priority.
    *   Output: Only Python code, no explanations.

2.  **Determine Data Structure:**
    *   Need to store jobs with priorities.
    *   Need to support FIFO for same priority.
    *   Need to extract max priority efficiently.
    *   Options:
        *   Sorted list (insertion sort): $O(N)$ insertion, $O(1)$ extraction.
        *   Heap: $O(\log N)$ insertion, $O(\log N)$ extraction.
        *   Priority Queue logic using `heapq` (min-heap by default).
    *   Since higher priority = higher number (2 > 1 > 0), and `heapq` is a min-heap, we need to negate the priority or invert the logic to make sure higher priority comes out first. Alternatively, use a max-heap logic. Python's `heapq` is a min-heap.
    *   To use `heapq` for max-priority: Store `(-priority, timestamp, job_name, job_data)`.
    *   Timestamp ensures FIFO for same priority (second item in tuple comparison).
    *   Wait, the requirement says "Higher priority jobs should be processed before lower priority jobs".
    *   Example: `priority=2` (Critical) comes before `priority=1` (High) comes before `priority=0` (Normal).
    *   So, 2 > 1 > 0.
    *   If using a min-heap with `(-priority, counter, ...)`, then -2 < -1 < 0. So -2 comes out first. This works.
    *   Alternatively, just use a list and sort, but heap is more efficient for a queue. Let's use `heapq`.
    *   To maintain FIFO for same priority, we need a counter/incrementing ID.

3.  **Drafting the Class:**
    *   Class name: `JobQueue` (inferred from example).
    *   `__init__`: Initialize empty list/heap.
    *   `add_job(job_name, job_data, priority=0)`:
        *   Increment a global counter for ordering.
        *   Push to heap: `(-priority, counter, job_name, job_data)`.
    *   `get_next_job()`:
        *   Pop from heap.
        *   Return `(job_name, job_data)`.
        *   Return `None` if empty.

4.  **Refining Priority Logic:**
    *   Example: `priority=2` (Critical).
    *   Example: `priority=1` (High).
    *   Example: `priority=0` (Normal).
    *   Requirement: Higher priority processed first.
    *   So 2 comes before 1.
    *   Heapq sorts smallest first.
    *   If I store `(-priority, order, ...)`, then:
        *   Priority 2 -> -2
        *   Priority 1 -> -1
        *   Priority 0 -> 0
    *   -2 is smaller than -1, so -2 pops first. This works.
    *   Tie-breaking: If priorities are equal, the second element in the tuple (order counter) ensures FIFO.

5.  **Handling `None` return:**
    *   The signature says `-> tuple[str, dict] | None`.
    *   Need to check if heap is empty.

6.  **Code Structure:**
    *   Import `heapq`.
    *   Define `JobQueue` class.
    *   Implement methods.

7.  **Reviewing Constraints:**
    *   "Write only the Python code, no explanations."
    *   Ensure imports are included.
    *   Ensure types are correct.

8.  **Edge Cases:**
    *   Empty queue.
    *   Multiple jobs with same priority.
    *   Default priority handling.

9.  **Implementation Details:**
    *   Use `heapq.heappush` and `heapq.heappop`.
    *   Use a monotonic counter for stable sort within priority levels.

    *   Wait, is `JobQueue` the required class name? The example uses `queue = JobQueue()`. Yes.
    *   Signature for `add_job`: `add_job(self, job_name: str, job_data: dict, priority: int = 0)`.
    *   Signature for `get_next_job`: `get_next_job(self) -> tuple[str, dict] | None`.

    *   Wait, checking the example provided in the prompt:
        ```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 confirms `priority` is an argument to `add_job`.
    *   This confirms `get_next_job` returns the tuple.

    *   One detail: "Jobs with the same priority should maintain FIFO order".
    *   Using a counter is the standard way to ensure stability in heaps.

    *   Let's check the priority values again.
    *   0: Normal
    *   1: High
    *   2: Critical
    *   Requirement: "Higher priority jobs should be processed before lower priority jobs".
    *   So Critical (2) > High (1) > Normal (0).
    *   Heap logic: store `-priority`.
    *   -2 < -1 < 0.
    *   So -2 pops first. Correct.

10. **Final Code Assembly:**
    *   Import heapq.
    *   Class JobQueue.
    *   `__init__`: `self._heap`, `self._counter`.
    *   `add_job`: `heapq.heappush`.
    *   `get_next_job`: `heapq.heappop`.

    *   Wait, the prompt asks for "Implement priority-based job scheduling for the queue." and gives specific requirements. It doesn't explicitly demand a class named `JobQueue`, but the example uses `JobQueue`. I should stick to the example's class name.
    *   Also, ensure type hints match the requirement `get_next_job() -> tuple[str, dict] | None`.

    *   Wait, one small thing: The prompt says "Modify `add_job`". It implies there might be an existing structure, but since I'm writing the code from scratch based on the example, I will define the class.
    *   The prompt says "Write only the Python code".

    *   Let's write the code.

```python
import heapq

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

    def add_job(self, job_name: str, job_data: dict, priority: int = 0):
        # Negate priority so higher priority (e.g., 2) comes before lower (e.g., 0)
        # Use counter to maintain FIFO for same priority
        heapq.heappush(self._heap, (-priority, self._counter, job_name, job_data))
        self._counter += 1

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

    *   Wait, I need to make sure I don't add extra text.
    *   Check type hint syntax `tuple[str, dict] | None`. This requires Python 3.10+. Assuming valid Python environment.
    *   Check imports. `heapq` is needed.
    *   Check `add_job` signature. `add_job(self, job_name, job_data, priority=0)`. The example calls `queue.add_job("normal", {"type": "normal"}, priority=0)`. This matches `job_name` as first arg, `job_data` as second, `priority` as keyword.
    *   Wait, the example shows `queue.add_job("normal", {"type": "normal"}, priority=0)`.
    *   My signature `def add_job(self, job_name: str, job_data: dict, priority: int = 0):` matches.
    *   Wait, does the prompt imply I should modify an existing class or write the whole class? "Implement priority-based job scheduling... Requirements: 1. Modify `add_job`...". Usually, in these contexts, providing the full class definition that satisfies the requirements is the standard response.
    *   The prompt says "Write only the Python code".

    *   One detail: The example shows `queue.add_job("normal", {"type": "normal"}, priority=0)`.
    *   My code: `def add_job(self, job_name: str, job_data: dict, priority: int = 0):`.
    *   This matches.

    *   Wait, is there any ambiguity about `job_data`? The example passes a dict. The return type hint says `tuple[str, dict]`. So `job_data` should be a dict.

    *   Let's double check the priority logic.
    *   Requirement: "Higher priority jobs should be processed before lower priority jobs".
    *   Example: Priority 2 (Critical) processed before Priority 1 (High).
    *   Heapq is min-heap.
    *   If I push `(-priority, ...)`.
    *   Priority 2 -> -2.
    *   Priority 1 -> -1.
    *   -2 < -1. So -2 is popped first.
    *   This satisfies the requirement.

    *   FIFO for same priority:
    *   Tuple comparison compares element by element.
    *   If `-priority` is same, compare `self._counter`.
    *   Since `self._counter` increments, smaller counter (earlier added) comes first.
    *   This satisfies FIFO.

    *   Looks good.

    *   Wait, I should check if `|` union syntax is standard enough. It is standard in Python 3.10+. Given the context of modern Python code, it's acceptable.
    *   Just to be safe, I could use `Optional[Tuple[str, dict]]` from `typing`, but the prompt specifically used `tuple[str, dict] | None` in the requirement section. I should follow that syntax.

    *   Wait, one detail in the prompt: "Write only the Python code, no explanations."
    *   I will output the code block.

```python
import heapq

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

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

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

    *   Wait, I should ensure imports are at the top.
    *   Is there any other constraint? "Implement priority-based job scheduling for the queue."
    *   The provided code looks complete.

    *   One minor check: `job_data` in example is `{"type": "normal"}`. It's a dict.
    *   Return type is `tuple[str, dict]`.
    *   `get_next_job` returns `(job_name, job_data)`.
    *   Looks correct.

    *   Wait, I need to make sure I don't use Python 3.10+ specific syntax if the environment is unknown, but the prompt explicitly used `| None` in the requirement text (`get_next_job() -> tuple[str, dict] | None`). So I should use that syntax.

    *   Final check on imports. `heapq` is standard.
    *   Final check on class name. `JobQueue` matches example.
    *   Final check on method names. `add_job`, `get_next_job`. Matches requirements.
    *   Final check on parameters. `priority` optional default 0. Matches requirement.

    *   Ready.

```python
import heapq

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

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

    def get_next_job(self) -> tuple[str, dict] | None:
        if not self._heap:
            return None
        _, _, job_name, job_data = heapq.heappop(self._heap)
        return (job_name, job_data)
```
    *   Wait, I should check if I need to define `__init__` explicitly? Yes, for the class to work.
    *   Is there any hidden requirement about thread safety? No.
    *   Is there any hidden requirement about `job_data` structure? No, just `dict`.
    *   Okay, proceeding.

    *   Wait, one more check on the prompt example:
        `queue.add_job("normal", {"type": "normal"}, priority=0)`
        My function signature: `def add_job(self, job_name: str, job_data: dict, priority: int = 0):`
        Call: `queue.add_job("normal", {"type": "normal"}, priority=0)`
        This works because `job_data` is the second positional argument.
        If I defined it as `def add_job(self, job_name, priority=0, job_data=None)`, the call `add_job("normal", {"type": "normal"}, priority=0)` would map `{"type": "normal"}` to `priority` (positional) which would break.
        My definition `job_name, job_data, priority=0` maps:
        1st arg -> `job_name`
        2nd arg -> `job_data`
        keyword arg -> `priority`
        This matches the example call perfectly.

    *   Wait, looking closely at the example call: `queue.add_job("normal", {"type": "normal"}, priority=0)`.
    *   `job_name` = "normal"
    *   `job_data` = {"type": "normal"}
    *   `priority` = 0
    *   My signature: `add_job(self, job_name: str, job_data: dict, priority: int = 0)`
    *   This is correct.

    *   One nuance: `tuple[str, dict] | None`.
    *   In Python 3.9 and below, `tuple[str, dict]` is valid (generic alias), but `|` union is 3.10+.
    *   Since the prompt used `|` in the requirement, I will use it.

    *   Final check on code correctness.
    *   `heapq` needs to be imported.
    *   `self._counter` ensures stability.
    *   `-priority` ensures max-heap behavior with min-heap.
    *   `get_next_job` handles empty queue.
    *   All good.

```python
import heapq

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

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

    def get_next_job(self) -> tuple[str, dict] | None:
        if not self._heap:
            return None
        _, _, job_name, job_data = heapq.heappop(self._heap)
        return (job_name, job_data)
```
    *   Wait, I will remove the `self` from the first line of the method if I want to be concise, but `self` is standard for class methods.
    *   I will keep `self`.

    *   Wait, is there any chance the user wants me to modify a specific existing code snippet provided elsewhere? No, "Implement... for the queue". "Requirements: 1. Modify `add_job`...". This implies defining the class to meet these requirements.
    *   Okay, generating output.

    *   Wait, I need to make sure I don't include markdown code block ticks if the instruction "Write only the Python code" implies raw text. However, usually, code blocks are expected. "Write only the Python code" usually means "no markdown text outside the code block" or "no natural language explanations". I will provide the code inside a markdown block as is standard for code output.
    *   Actually, usually "Write only the Python code" means don't write "Here is the code:". Just the code. I will use the markdown block for clarity.

    *   Wait, one detail in `get_next_job`. The return type hint `tuple[str, dict] | None`.
    *   In Python 3.9+, `tuple[str, dict]` is valid.
    *   In Python 3.10+, `|` is valid.
    *   I will assume a modern Python environment consistent with the requirement text.

    *   One more check: `job_data` is a dict. `job_name` is str.
    *   Return is `(job_name, job_data)`.
    *   Correct.

    *   Wait, I should check if `job_data` needs to be deep copied? Not specified.
    *   I will pass it as is.

    *   Okay, final verification.
    *   Imports: `heapq`.
    *   Class: `JobQueue`.
    *   Methods: `__init__`, `add_job`, `get_next_job`.
    *   Logic: Priority inverted, Counter for FIFO.
    *   Signatures: Match requirements.
    *   Output: Code only.

    *   Wait, I notice the prompt says "Write only the Python code, no explanations."
    *   I will output just the code block.

```python
import heapq

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

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

    def get_next_job(self) -> tuple[str, dict] | None:
        if not self._heap:
            return None
        _, _, job_name, job_data = heapq.heappop(self._heap)
        return (job_name, job_data)
```
    *   Wait, I should check indentation. 4 spaces.
    *   Looks good.
    *   Wait, is there any chance `job_data` in the example `{"type": "normal"}` implies specific keys? No, it's just a dict.
    *   Okay, ready to print.

    *   Wait, I should check if I need to handle `None` in `add_job`? No, `job_data` is expected.
    *   Okay.

    *   Wait, one more thought. If I use `tuple[str, dict] | None`, I should ensure the environment supports it. But since I must follow the prompt's type hint style, I will use it.

    *   Final check on `get_next_job`.
    *   If heap is empty, return `None`.
    *   If not, pop and return tuple.
    *   Correct.

    *   One detail: "Jobs with the same priority should maintain FIFO order".
    *   My implementation uses `_counter`.
    *   Since `_counter` increases monotonically, smaller counter = earlier insertion.
    *   Heap compares `(-priority, counter)`.
    *   If `-priority` equal, smaller `counter` wins (pops first).
    *   This ensures FIFO for same priority.
    *   Correct.

    *   Wait, is `heapq` imported in the code block? Yes.
    *   Okay.

    *   Wait, I will remove the markdown ticks if "Write only the Python code" implies raw text. But standard practice for "code" is markdown block. I'll use markdown block.
    *   Actually, to be safest with "Write only the Python code", I will provide the code within the block without extra text.

    *   Wait, I'll check if `self` is required in `add_job`. Yes, instance method.
    *   Okay.

    *   Wait, I'll check if I should use `typing` module for type hints. The prompt used `tuple[str, dict] | None` which is built-in generic syntax (PEP 585) introduced in 3.9. So no `typing` import needed.
    *   Okay.

    *   Wait, one last check on the priority logic.
    *   Priority 2 (Critical) vs Priority 1 (High).
    *   -2 vs -1.
    *   -2 < -1.
    *   -2 pops first.
    *   Critical comes before High.
    *   Requirement: "Higher priority jobs should be processed before lower priority jobs".
    *   Critical (2) > High (1).
    *   So Critical before High.
    *   My logic: -2 pops before -1.
    *   So Critical before High.
    *   Correct.

    *   Okay, generating response.

</reasoning_content>

<content>
```python
import heapq

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

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

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