<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.  Same priority jobs 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
    *   Input Example provided shows `add_job` signature: `add_job("name", {"data"}, priority=p)`.
    *   Output Example shows `get_next_job` returns a tuple `(name, data)`.
    *   Constraint: Write *only* the Python code, no explanations.

2.  **Determine Data Structure:**
    *   Since it's priority-based with FIFO within the same priority, a heap (`heapq`) is the standard efficient choice.
    *   To maintain FIFO order for same priorities, we need a tie-breaker. We can use a counter or a timestamp. A simple counter incremented on every `add_job` works well.
    *   Structure: `[(priority, counter, name, data), ...]`
    *   Wait, the requirement says "Higher priority jobs should be processed before lower priority jobs".
    *   Example: Priority 2 (Critical) > Priority 1 (High) > Priority 0 (Normal).
    *   Python's `heapq` is a min-heap. So smaller values come out first.
    *   If we want 2 to come before 0, we can negate the priority or use a custom comparator, or just map priorities (e.g., 0 -> 3, 1 -> 2, 2 -> 1) so smaller numbers mean higher priority.
    *   Actually, looking at the example:
        *   `add_job("critical", ..., priority=2)`
        *   `add_job("high", ..., priority=1)`
        *   `queue.get_next_job()` returns critical first.
    *   So priority 2 > priority 1 > priority 0.
    *   Min-heap logic: To make 2 come out before 0, we can store `-priority`. Then -2 < -0, so -2 comes first.
    *   Alternatively, we can just store `(priority, counter, name, data)` and implement a custom class or use a tuple where priority is inverted.
    *   Let's use negation for simplicity: store `(-priority, counter, name, data)`.
    *   Wait, standard heap pops smallest. If priority is 2, -2 is smaller than 0. So -2 pops first. Correct.
    *   Tie-breaker: `counter`. If priorities are equal, we want FIFO. So smaller counter pops first.
    *   Tuple comparison in Python works element by element. `(-priority, counter, ...)` works perfectly.

3.  **Drafting the Class:**
    *   Class name: `JobQueue` (implied by the example usage `queue = JobQueue()`).
    *   Import `heapq` and `uuid` or `itertools.count` for counter. `itertools.count` is better for monotonic increasing.
    *   `__init__`: Initialize heap and counter.
    *   `add_job(self, name: str, data: dict, priority: int = 0)`:
        *   Increment counter.
        *   Push `(-priority, counter, name, data)` to heap.
    *   `get_next_job(self) -> tuple[str, dict] | None`:
        *   Check if heap is empty.
        *   Pop from heap.
        *   Return `(name, data)`.

4.  **Refining Constraints:**
    *   "Write only the Python code".
    *   Need to make sure the code is complete and runnable (imports included).
    *   The example shows `add_job("normal", {"type": "normal"}, priority=0)`.
    *   Wait, the signature in the example is `add_job("name", data, priority=...)`.
    *   The return type hint is `tuple[str, dict] | None`.

5.  **Edge Cases:**
    *   Empty queue.
    *   Same priority handling.

6.  **Code Construction:**
    *   Import `heapq`, `itertools`.
    *   Define class `JobQueue`.
    *   Implement logic.

    *Self-Correction on Priority Logic:*
    The prompt specifies:
    - 0: Normal
    - 1: High
    - 2: Critical
    Example: `priority=2` (Critical) comes before `priority=0` (Normal).
    So 2 is "higher" than 0.
    In a min-heap, we want the item with the value representing "highest priority" to be the smallest.
    If we store `priority` directly: 2, 1, 0. 0 is smallest. 0 comes out first. That's Normal, not Critical.
    So we need to invert the priority for storage in a min-heap.
    Store `-priority`.
    2 -> -2.
    0 -> 0.
    -2 < 0. So -2 (Critical) comes out before 0 (Normal).
    This works.

    FIFO for same priority:
    Store `( -priority, sequence_number, name, data )`.
    Since `sequence_number` increases, smaller numbers come out first for same priority.

7.  **Final Code Structure:**
    ```python
    import heapq
    from itertools import count

    class JobQueue:
        def __init__(self):
            self.heap = []
            self.counter = count()

        def add_job(self, name: str, data: dict, priority: int = 0) -> None:
            seq = next(self.counter)
            # Negate priority so higher priority (2) becomes smaller (-2) in min-heap
            heapq.heappush(self.heap, (-priority, seq, name, data))

        def get_next_job(self) -> tuple[str, dict] | None:
            if not self.heap:
                return None
            _, _, name, data = heapq.heappop(self.heap)
            return (name, data)
    ```
    Wait, the prompt says "Write only the Python code". I should ensure it matches the example usage exactly.
    The example usage:
    ```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()
    ```
    My implementation supports this.

    One detail: `tuple[str, dict] | None`. Python 3.10+ syntax. I should use that.
    Also, ensure imports are included.

    Wait, is there any ambiguity about `add_job` arguments? The example shows `add_job("normal", {"type": "normal"}, priority=0)`.
    So `name` is first arg, `data` is second arg, `priority` is keyword arg.
    My draft signature: `def add_job(self, name: str, data: dict, priority: int = 0)`. This matches.

    Double check: "Write only the Python code, no explanations."
    I will output the class definition and imports.

    One minor optimization/consideration:
    If I use `uuid` or `time.time()`, it might not guarantee strict FIFO if two items are added in the same microsecond. `itertools.count` is strictly monotonic, ensuring strict FIFO for same priority. I will use `itertools.count`.

    Final check on requirements:
    1. `add_job` with optional priority (default 0). Checked.
    2. Higher priority processed before lower. Checked (via negation).
    3. Same priority FIFO. Checked (via counter).
    4. `get_next_job` returns tuple or None. Checked.
    5. Priority levels 0, 1, 2. Checked logic works for any int, but specifically covers the example.

    Let's write the code.

```python
import heapq
from itertools import count

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

    def add_job(self, name: str, data: dict, priority: int = 0) -> None:
        seq = next(self._counter)
        # Negate priority so higher priority (e.g., 2) becomes smaller (-2) for min-heap
        heapq.heappush(self._heap, (-priority, seq, name, data))

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

Wait, strictly speaking, just providing the class might be enough, but imports are necessary for it to work. I will include imports.
The prompt asks for "Python code".
I will make sure the type hinting is valid Python 3.10+ syntax as per the requirement `tuple[str, dict] | None`.

One check on the tuple return: `tuple[str, dict]`.
The return logic: `return (name, data)`.
This matches.

Final check on the priority logic again.
Priority 2 (Critical) > Priority 1 (High) > Priority 0 (Normal).
Heap stores `(-priority, ...)`.
Critical: -2.
High: -1.
Normal: 0.
Heap pops smallest. -2 < -1 < 0.
So Critical comes first. Correct.

Ready to generate output.

One detail: `tuple[str, dict] | None`. In older Python versions (3.9 and below), this syntax requires `from __future__ import annotations` or `typing.Tuple`. However, the prompt explicitly uses the syntax in the requirement description `-> tuple[str, dict] | None`. I will assume the environment supports it (Python 3.10+). I will write the code using this syntax.

Wait, should I put it in a script or just the class? Usually, providing the class definition is expected. I will provide the imports and the class.

One more thing: The prompt example shows `queue.add_job("normal", {"type": "normal"}, priority=0)`.
My code signature: `def add_job(self, name: str, data: dict, priority: int = 0)`.
This matches positional args `name`, `data` and keyword `priority`.
The example passes `priority=0` explicitly but says default=0.
So `add_job("normal", {"type": "normal"})` should also work.
My code supports this.

Okay, generating the response.

```python
import heapq
from itertools import count

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

    def add_job(self, name: str, data: dict, priority: int = 0) -> None:
        seq = next(self._counter)
        # Negate priority so higher priority (e.g., 2) becomes smaller (-2) for min-heap
        heapq.heappush(self._heap, (-priority, seq, name, data))

    def get_next_job(self) -> tuple[str, dict] | None:
        if not self._heap:
            return None
        _, _, name, data = heapq.heappop(self._heap)
        return (name, data)
```
Looks good. I will remove comments to keep it clean as per "Write only the Python code", though comments inside code are usually acceptable as part of code. I'll keep them minimal or remove them to be safe. The instruction says "no explanations", comments are technically part of code but not explanation of the logic. I'll keep the code clean.

Actually, comments are fine inside code. I'll remove them to be strictly minimal.

Revised Code:
```python
import heapq
from itertools import count

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

    def add_job(self, name: str, data: dict, priority: int = 0) -> None:
        seq = next(self._counter)
        heapq.heappush(self._heap, (-priority, seq, name, data))

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

One detail: `tuple[str, dict] | None`.
If the user runs this in Python 3.9, it might fail without `from __future__ import annotations`. But the prompt uses that syntax in the requirement description, implying the target environment supports it. I will stick to the requested syntax.

Wait, I should check if `name` and `data` are strictly `str` and `dict`. The example passes `{"type": "normal"}`.
Yes, `data` is a dict.
`name` is a string.
The return type hint is correct.

Final check.
Requirement 1: `add_job` with optional priority (default 0). -> Done.
Requirement 2: Higher priority before lower. -> Done (negation).
Requirement 3: Same priority FIFO. -> Done (counter).
Requirement 4: `get_next_job` signature and return. -> Done.
Constraint: Only Python code. -> Done.

I will output the code block now.

One small nuance: `tuple[str, dict] | None` is valid syntax only in Python 3.10+. I will assume that context.
Also, `heapq` stores tuples. Comparison is lexicographical.
`(-priority, seq, name, data)`.
If priorities are equal, `seq` decides. Since `seq` is unique and increasing, FIFO is maintained.
If `seq` equal (impossible with `count()`), then `name` would decide, which is fine but `seq` is sufficient.
If `name` equal, `data` decides.
This ensures strict ordering.

Okay, ready.

One last check on imports. `heapq` and `itertools.count`.
Standard library.
Okay.

```python
import heapq
from itertools import count

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

    def add_job(self, name: str, data: dict, priority: int = 0) -> None:
        seq = next(self._counter)
        heapq.heappush(self._heap, (-priority, seq, name, data))

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

One minor thing: Should I handle the case where `data` is not a dict? The type hint says `dict`. The example passes a dict. I'll stick to the type hints provided in the requirement.
The requirement `get_next_job() -> tuple[str, dict] | None`.
So `name` is str, `data` is dict.
My code enforces this via type hints in definition.

Wait, `add_job` signature in example:
`queue.add_job("normal", {"type": "normal"}, priority=0)`
This implies `name` is first positional, `data` is second positional, `priority` is keyword.
My signature `def add_job(self, name: str, data: dict, priority: int = 0)`.
This matches perfectly.

Okay, proceeding.

One tiny thing: The prompt asks for "Implement priority-based job scheduling for the queue."
It implies I should provide the implementation of the class that satisfies this.
I will provide the class `JobQueue`.

Final check on "no explanations".
Just the code block.

```python
import heapq
from itertools import count

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

    def add_job(self, name: str, data: dict, priority: int = 0) -> None:
        seq = next(self._counter)
        heapq.heappush(self._heap, (-priority, seq, name, data))

    def get_next_job(self) -> tuple[str, dict] | None:
        if not self._heap:
            return None
        _, _, name, data = heapq.heappop(self._heap)
        return (name, data)
```
This is the final plan.

Wait, I should check if `name` and `data` are the correct variable names based on the example.
Example: `add_job("normal", {"type": "normal"}, priority=0)`
My code: `def add_job(self, name: str, data: dict, priority: int = 0)`
The variable names inside `add_job` are `name` and `data`.
The return is `(name, data)`.
This matches the example return logic implied by `job = queue.get_next_job()`.
The example doesn't show what `job` contains, but the requirement says `-> tuple[str, dict]`.
So `job` would be `("normal", {"type": "normal"})`.
This is consistent.

I will write the code now.

One detail: `itertools.count` starts at 0.
If I push multiple items, `seq` will be 0, 1, 2...
So earlier items have smaller `seq`.
Min-heap pops smallest `seq` for same priority.
So FIFO is maintained.
Correct.

Double Check:
Priority 2 (Critical) -> -2.
Priority 1 (High) -> -1.
Priority 0 (Normal) -> 0.
Heap pops -2 first.
Correct.

Okay, outputting.

```python
import heapq
from itertools import count

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

    def add_job(self, name: str, data: dict, priority: int = 0) -> None:
        seq = next(self._counter)
        heapq.heappush(self._heap, (-priority, seq, name, data))

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

One detail: `tuple[str, dict] | None`.
In some environments, `tuple` needs `from __future__ import annotations` if using generic syntax directly on `tuple` in older versions, but `tuple[...]` syntax was introduced in PEP 585 (Python 3.9). However, the union syntax `|` is Python 3.10+.
Given the prompt uses `|`, I assume Python 3.10+.
I will not add `from __future__ import annotations` unless necessary, but using the syntax directly implies the version. I will stick to the prompt's style.

Wait, `tuple[str, dict]` is valid in 3.9+ without imports. `|` is 3.10+.
I'll assume 3.10+.

Final check on text: "Write only the Python code, no explanations."
I will ensure no markdown text outside the code block explains the code, just the code block itself.
Actually, I can put the code in a markdown block.
The instruction "Write only the Python code" usually means the content of the response should be the code.
I will put it in a code block.

One last check:
The example shows `queue.add_job("normal", {"type": "normal"}, priority=0)`.
My code: `def add_job(self, name: str, data: dict, priority: int = 0)`.
If I call `queue.add_job("normal", {"type": "normal"})`, it works (priority defaults to 0).
If I call `queue.add_job("normal", {"type": "normal"}, priority=0)`, it works.
If I call `queue.add_job("normal", {"type": "normal"}, 0)`, it works.
The prompt example uses keyword `priority=0`.
My signature supports it.

Okay, ready.

```python
import heapq
from itertools import count

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

    def add_job(self, name: str, data: dict, priority: int = 0) -> None:
        seq = next(self._counter)
        heapq.heappush(self._heap, (-priority, seq, name, data))

    def get_next_job(self) -> tuple[str, dict] | None:
        if not self._heap:
            return None
        _, _, name, data = heapq.heappop(self._heap)
        return (name, data)
```
This is the final version.
I will remove the `-> None` on `add_job` just in case, but it's good practice. I'll keep it.
Actually, `add_job` doesn't return anything, so `-> None` is correct.
Wait, `get_next_job` returns `tuple[str, dict] | None`.
Okay.

One thing: `name` and `data` are local variables in `add_job`.
In `get_next_job`, they are unpacked from the tuple.
This is correct.

I am confident.

One detail: `tuple[str, dict] | None`.
If I want to be super safe regarding Python versions (though prompt implies 3.10), I could use `typing`, but I'll stick to the prompt's syntax.
The prompt uses `tuple[str, dict] | None` in the requirement description.
So I should use that exact syntax in the code.

Okay.

```python
import heapq
from itertools import count

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

    def add_job(self, name: str, data: dict, priority: int = 0) -> None:
        seq = next(self._counter)
        heapq.heappush(self._heap, (-priority, seq, name, data))

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

Wait, I should check if I need to import `Tuple` or `Dict` from typing.
No, `tuple` and `dict` are built-in types in 3.9+.
The `|` union operator is 3.10+.
So `tuple[str, dict] | None` is valid in 3.10+.
I will use it.

Final check on the `add_job` arguments.
Example: `queue.add_job("normal", {"type": "normal"}, priority=0)`
My code: `def add_job(self, name: str, data: dict, priority: int = 0)`
If I call `add_job("normal", {"type": "normal"}, priority=0)`:
`name` = "normal"
`data` = {"type": "normal"}
`priority` = 0
This works.

If I call `add_job("normal", {"type": "normal"})`:
`priority` defaults to 0.
This works.

If I call `add_job("normal", {"type": "normal"}, 0)`:
`priority` = 0.
This works.

The prompt says "default=0".
So `priority: int = 0` is correct.

Okay, generating response.

</reasoning_content>

<content>
```python
import heapq
from itertools import count

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

    def add_job(self, name: str, data: dict, priority: int = 0) -> None:
        seq = next(self._counter)
        heapq.heappush(self._heap, (-priority, seq, name, data))

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