<reasoning_content>
Thinking Process:

1.  **Analyze the Request:**
    *   Goal: Implement a priority-based job scheduling system for a queue.
    *   Requirements:
        1.  `add_job` method needs an optional `priority` parameter (default=0).
        2.  Higher priority jobs (higher number) come first.
        3.  FIFO order for same priority.
        4.  `get_next_job()` method returning `tuple[str, dict] | None`.
        5.  Priority levels: 0 (Normal), 1 (High), 2 (Critical).
    *   Output: Python code only, no explanations.

2.  **Design the Data Structure:**
    *   Need a queue that supports priority ordering.
    *   Python's `heapq` module is suitable for priority queues.
    *   To maintain FIFO for same priority, I need a tie-breaker. Since `heapq` compares tuples element-wise, I can use a combination of (priority, insertion_order, job_data).
    *   Wait, the requirement says "Higher priority jobs should be processed before lower priority jobs".
    *   Example: Priority 2 > Priority 1 > Priority 0.
    *   `heapq` is a min-heap by default. To make 2 come out before 0, I should store negative priority (so -2 < -0) or use a custom comparator. Storing negative priority is easier with standard `heapq`.
    *   Tie-breaking: If priority is the same, the one added earlier should come out first. I need a global counter or timestamp to track insertion order.

3.  **Drafting the Class:**

    ```python
    import heapq
    from typing import Optional, Tuple, Dict, Any

    class JobQueue:
        def __init__(self):
            self._heap = []
            self._counter = 0  # To maintain FIFO for same priority

        def add_job(self, name: str, job_data: dict, priority: int = 0) -> None:
            # Priority 2 (Critical) > Priority 1 (High) > Priority 0 (Normal)
            # Min-heap pops smallest. So we negate priority to make larger priority pop first.
            # -2 < -0.
            entry = (-priority, self._counter, name, job_data)
            heapq.heappush(self._heap, entry)
            self._counter += 1

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

4.  **Refining based on requirements:**
    *   `add_job` signature: `add_job(self, name, job_data, priority=0)`.
    *   `get_next_job` signature: `get_next_job(self) -> tuple[str, dict] | None`.
    *   Priority logic: 2 > 1 > 0.
    *   Using `-priority` in a min-heap ensures 2 becomes -2, 0 becomes 0. -2 < 0, so -2 pops first. Correct.
    *   FIFO logic: Using `_counter` ensures that if priorities are equal, the one with lower counter (added earlier) pops first.

5.  **Final Code Structure:**
    *   Imports.
    *   Class definition.
    *   Methods implementation.
    *   Type hints as requested in the prompt description (though strict typing isn't explicitly demanded, it's good practice). The prompt asks for `tuple[str, dict] | None` return type hint.

6.  **Double Check:**
    *   Requirement 1: `add_job` accepts optional priority. (Check)
    *   Requirement 2: Higher priority processed before lower. (Check, via negation).
    *   Requirement 3: FIFO for same priority. (Check, via counter).
    *   Requirement 4: `get_next_job` returns tuple or None. (Check).
    *   Output: Python code only.

7.  **Writing 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, job_data: Dict, priority: int = 0) -> None:
        # Negate priority so higher priority (e.g., 2) comes out before lower (e.g., 0)
        # Min-heap pops smallest value.
        entry = (-priority, self._counter, name, job_data)
        heapq.heappush(self._heap, entry)
        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, `tuple[str, dict] | None` syntax is Python 3.10+. I should use `typing` module for compatibility or just the standard syntax. The prompt uses `tuple[str, dict] | None` in the requirement description, implying modern Python syntax is acceptable. I will stick to standard type hints using `typing` for broader compatibility or just the built-in generic syntax if assuming 3.9+. Given the prompt uses `tuple[str, dict] | None`, I will use that style for the return type annotation in the function signature.

Also, I need to make sure I don't include markdown code blocks if the instruction implies raw text, but usually "Write only the Python code" implies a code block is fine or just the text. I will provide the code inside a block for clarity, or just plain text. Usually, markdown code blocks are expected for "Python code". I will use a markdown block.

Wait, looking at the instruction "Write only the Python code, no explanations."
I should output the code directly.

One detail: `tuple[str, dict] | None` uses the `|` union operator which requires Python 3.10+. If I want to be safe, I can use `Optional[Tuple[str, dict]]`. However, the prompt specifically used `tuple[str, dict] | None` in the requirement description. I will match that style in the implementation to be precise.

Let's refine the implementation to be clean.

```python
import heapq
from typing import Tuple, Dict, Optional

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

    def add_job(self, name: str, job_data: Dict, priority: int = 0) -> None:
        # Higher priority (larger number) means smaller negative value
        # Tie-break using insertion counter for FIFO
        entry = (-priority, self._counter, name, job_data)
        heapq.heappush(self._heap, entry)
        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)
```

Wait, `Tuple[str, Dict] | None` might fail on older Python versions if the environment isn't 3.10+. But since the prompt used that syntax in the requirement, I will use it.
Actually, to be safe and standard, `Optional` is often preferred, but I'll stick to the prompt's implied syntax style.
Actually, looking closely at the prompt: `get_next_job() -> tuple[str, dict] | None`.
I will use `tuple` (lowercase) as per the prompt, though `Tuple` (capital) from typing is more common. I will follow the prompt's hint style.

Wait, I should check if `dict` needs to be `Dict`. The prompt uses `dict`. I will use `dict` and `tuple` for consistency with the prompt's type hint style.

Revised 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:
        entry = (-priority, self._counter, name, job_data)
        heapq.heappush(self._heap, entry)
        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 looks correct and meets all constraints.

One final check on priority logic:
Priority 2 (Critical) vs Priority 0 (Normal).
Heap stores -2 vs 0.
-2 < 0.
heappop returns smallest.
So -2 comes out first.
So Priority 2 comes out first.
Correct.

FIFO:
Entry 1: (-2, 0, ...)
Entry 2: (-2, 1, ...)
heappop compares (-2, 0) vs (-2, 1).
0 < 1.
Entry 1 comes out first.
Correct.

I will write the code now.

```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:
        # Negate priority so higher priority numbers come first (since heapq is a min-heap)
        # Use counter to maintain FIFO order for same priority
        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 looks solid. I will remove the comment lines to keep it clean if needed, but comments are part of code. I'll keep it clean.
Actually, I should ensure imports are included.
The prompt asks for "Python code".
I will provide the class implementation.

One minor thing: `tuple[str, dict]` requires Python 3.9+ for generic built-ins, and `|` requires 3.10+. The prompt uses this syntax, so I will assume the environment supports it.

Final check on imports. `heapq` is needed. `typing` is not strictly needed if using built-in generics and `|`, but `Optional` is often used. The prompt used `tuple[...] | None`, so I will use that.

```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:
        entry = (-priority, self._counter, name, job_data)
        heapq.heappush(self._heap, entry)
        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)
```
Looks good. I will format it as a code block.
Wait, I should not output markdown ticks if the instruction says "Write only the Python code". However, usually, code blocks are expected. I will output the code within a markdown block for clarity as is standard for "Python code" requests unless specified "raw text". The instruction "Write only the Python code, no explanations" usually means no conversational text outside the code. A markdown block is technically formatting, not explanation. I will use the markdown block.

Wait, strictly speaking "Write only the Python code" might mean no markdown ticks either. But usually, LLM interfaces render markdown. I'll include the ticks to ensure it's recognized as code.
Actually, to be safest, I will just provide the code. But standard practice for "Code" requests is a code block. I'll use a code block.

Wait, I need to make sure I don't add extra text like "Here is the code".
Okay, ready.

One detail: `job_data: dict`. The prompt example shows `{"type": "normal"}`. So `dict` is correct.
`name: str`. The prompt example shows `"normal"`. So `str` is correct.
`priority: int = 0`.
Return type `tuple[str, dict] | None`.

Let's assemble.

```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:
        entry = (-priority, self._counter, name, job_data)
        heapq.heappush(self._heap, entry)
        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 satisfies all constraints.

Wait, I should check if `dict` is imported. In Python 3.9+, `dict` works as generic. In older Python, `Dict` from typing is needed. The prompt uses `dict` in the return type hint `tuple[str, dict]`. This implies Python 3.9+ generic support. I will stick to `dict`.

One more check: `tuple[str, dict] | None`.
If I run this in Python 3.9, `tuple[str, dict]` works. `|` works in 3.10+.
If I want to be super compatible, I'd use `Optional[Tuple[str, dict]]`.
But I will follow the prompt's syntax exactly in the signature.

Final check on logic:
Priority 2 -> -2
Priority 0 -> 0
Heap pops -2 before 0.
Correct.

Counter ensures FIFO for same priority.
Correct.

Return value matches example logic.
Correct.

I will remove the type hints from the function arguments if I want to be minimal, but the requirement implies type hints are expected (`get_next_job() -> tuple[str, dict] | None`). I will include them.

One small detail: `job_data` in `add_job` is a `dict`.
The example shows `queue.add_job("normal", {"type": "normal"}, priority=0)`.
So `name` is first arg, `job_data` is second.
My code: `def add_job(self, name: str, job_data: dict, priority: int = 0)`.
Matches.

Okay, generating response.

```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:
        entry = (-priority, self._counter, name, job_data)
        heapq.heappush(self._heap, entry)
        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)
```
Wait, I should check if I need to import `Tuple` or `Dict` if I use them. I used `dict` and `tuple` (built-in) in type hints, so no import needed for those. `heapq` needs import.
Okay.

One nuance: `tuple[str, dict]` creates a tuple type hint. `|` creates a union.
This requires Python 3.10 for the `|` syntax in type hints generally, though 3.9 allows `tuple[...]`.
I will assume the environment supports the syntax shown in the requirement.

Final check: No explanations. Just 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:
        entry = (-priority, self._counter, name, job_data)
        heapq.heappush(self._heap, entry)
        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)
```
Looks perfect.

Wait, I should make sure `dict` is not shadowed. It's fine.
I'll output the code now.

One detail: `tuple[str, dict] | None` vs `tuple[str, dict] | None`.
The prompt uses `tuple`. I will use `tuple`.
I will ensure indentation is correct (4 spaces).

One more thing: The prompt example `queue.add_job("normal", {"type": "normal"}, priority=0)`.
My signature `add_job(self, name: str, job_data: dict, priority: int = 0)`.
This matches.

Okay, ready to write.

One final check on imports. `heapq` is standard library.
I will not include `from typing import ...` since I used built-ins `tuple` and `dict` and `|`.
This is cleaner.

Wait, if I use `|` in type hint, it needs `from __future__ import annotations` or Python 3.10+.
Given the prompt explicitly used `tuple[str, dict] | None`, I will assume Python 3.10+ context.
I won't add the `from __future__` unless necessary, but it's safer to just write the code as requested without extra boilerplate unless it breaks syntax.
Since I'm writing the code, I'll assume the interpreter supports the syntax shown in the requirement.

Okay, proceeding.

</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:
        # Negate priority so higher priority numbers come first (min-heap behavior)
        # Use counter to maintain FIFO order for same priority
        entry = (-priority, self._counter, name, job_data)
        heapq.heappush(self._heap, entry)
        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>