<reasoning_content>
Thinking Process:

1.  **Analyze the Request:**
    *   Goal: Implement priority-based job scheduling for a queue.
    *   Requirements:
        1.  `add_job` method needs 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`.
    *   Priority levels defined: 0 (Normal), 1 (High), 2 (Critical). Note: Higher number = Higher priority.
    *   Output: Python code only, no explanations.

2.  **Determine Data Structure:**
    *   To satisfy priority requirements efficiently:
        *   Option 1: Sorted list (insertion sort style). $O(N)$ insertion, $O(1)$ retrieval.
        *   Option 2: Heap (Priority Queue). Python's `heapq` module. $O(\log N)$ insertion, $O(\log N)$ retrieval.
        *   Option 3: Multiple queues (buckets per priority).
    *   Requirement 3 (FIFO for same priority) needs careful handling.
    *   Using `heapq` with tuples `(priority, timestamp, job_id, data)` ensures that if priorities are equal, the one with the smaller timestamp (added earlier) comes first.
    *   Wait, the requirement says "Higher priority jobs should be processed before lower priority jobs". In the example, priority 2 is "Critical", priority 1 is "High", priority 0 is "Normal". So higher number = higher priority.
    *   `heapq` is a min-heap. To make higher numbers pop first, I can store `(-priority, timestamp, job)`.
    *   Alternatively, since the requirement is explicit about priority levels (0, 1, 2), I can just use a list of lists (buckets) for each priority level and iterate through buckets. However, a heap is more scalable for arbitrary priorities. Given the prompt implies a specific class implementation, a heap is the standard way to implement a Priority Queue.
    *   Let's check the FIFO requirement for same priority.
    *   If using a heap: Store `(priority, insertion_order, job_name, job_data)`.
        *   Since `heapq` pops the smallest item, and we want larger priority to pop first, we can store `(-priority, insertion_order, job_name, job_data)`.
        *   Tuple comparison works lexicographically.
        *   If priorities differ: `-2 < -1 < -0`. So priority 2 comes before priority 1. Correct.
        *   If priorities same: `(-p, order1)` vs `(-p, order2)`. Smaller order comes first. Correct (FIFO).

3.  **Drafting the Class:**
    *   Class Name: `JobQueue` (implied by example).
    *   Imports: `heapq`, `time` (for timestamp/counter).
    *   `__init__`: Initialize heap and counter.
    *   `add_job`: Append to heap.
    *   `get_next_job`: Pop from heap, return tuple.

4.  **Refining the Heap Logic:**
    *   Python `heapq` is a min-heap.
    *   We want Priority 2 > Priority 1 > Priority 0.
    *   To get Priority 2 first, we need to store `-priority`.
    *   `-2 < -1 < 0`. So `-2` pops before `-1`.
    *   Tie-breaking: Use a global counter/incrementing integer to ensure FIFO for same priority.
    *   Tuple structure in heap: `(-priority, sequence_number, job_name, job_data)`.

5.  **Addressing the specific return type:**
    *   `get_next_job() -> tuple[str, dict] | None`
    *   The example shows `queue.add_job("normal", {"type": "normal"}, priority=0)`.
    *   So `job_name` is a string, `job_data` is a dict.
    *   `get_next_job` should return `("job_name", {"type": ...})`.

6.  **Code Structure:**
    ```python
    import heapq
    import time

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

        def add_job(self, name: str, data: dict, priority: int = 0):
            # Store as (-priority, counter, name, data)
            # Min-heap: smaller value pops first.
            # -2 (priority 2) < -1 (priority 1) < -0 (priority 0)
            heapq.heappush(self.heap, (-priority, self.counter, name, data))
            self.counter += 1

        def get_next_job(self) -> tuple[str, dict] | None:
            if not self.heap:
                return None
            # Pop smallest (highest priority)
            priority_neg, seq, name, data = heapq.heappop(self.heap)
            return (name, data)
    ```

7.  **Review against constraints:**
    *   `add_job` accepts optional priority? Yes.
    *   Higher priority processed before lower? Yes (using negation).
    *   Same priority FIFO? Yes (using counter).
    *   `get_next_job` signature? Yes.
    *   Python code only? Yes.

8.  **Final Check:**
    *   Does the example match?
    *   `queue.add_job("normal", {"type": "normal"}, priority=0)`
    *   `queue.add_job("critical", {"type": "critical"}, priority=2)`
    *   `queue.add_job("high", {"type": "high"}, priority=1)`
    *   `get_next_job()` returns "critical".
    *   Heap contents:
        *   `(-0, 0, "normal", ...)`
        *   `(-2, 1, "critical", ...)`
        *   `(-1, 2, "high", ...)`
    *   Heap order (sorted by first element):
        *   `(-2, 1, ...)` (Critical)
        *   `(-1, 2, ...)` (High)
        *   `(-0, 0, ...)` (Normal)
    *   Pop returns Critical. Correct.

    *   Wait, is `tuple[str, dict] | None` valid syntax in older Python versions? It requires Python 3.10+ or `from __future__ import annotations`. Standard modern Python accepts it. I will use standard type hints.
    *   Wait, `get_next_job` returns `tuple[str, dict]`. The example shows `"normal"` as name.
    *   One detail: The prompt asks to "Implement priority-based job scheduling for the queue." It doesn't explicitly name the class, but the example uses `queue = JobQueue()`. I should define `JobQueue`.

    *   Wait, one edge case: `tuple[str, dict] | None`. In Python 3.9+, `|` is valid. In 3.10+, it's standard. I'll use standard typing syntax.
    *   Actually, to be safe and concise, I will just write the code.

    *   Wait, the prompt says "Write only the Python code, no explanations."
    *   I should ensure imports are included if necessary.

    *   Let's refine the implementation to be robust.
    *   Using a class named `JobQueue` based on the example usage.

    *   Wait, should I handle the priority levels explicitly (0, 1, 2)? The implementation handles integers generally, which covers the levels. The prompt defines levels but the logic works for any int.
    *   The prompt example: `queue.add_job("normal", {"type": "normal"}, priority=0)`.
    *   My implementation: `add_job(self, name, data, priority=0)`.
    *   Matches.

    *   One detail: `get_next_job` return type hint `tuple[str, dict] | None`.
    *   I will use `Optional[Tuple[str, dict]]` or the `|` syntax. `|` is cleaner for modern Python.

    *   Wait, I need to make sure I don't introduce external dependencies like `typing` if I use `|` syntax which is built-in in 3.10+. But `heapq` is standard.
    *   I'll use `heapq`.

    *   Final check on FIFO:
    *   If I push `(-0, 0, A)` then `(-0, 1, B)`.
    *   Heap pops `( -0, 0, A)` first. Correct.

    *   Let's write 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, data: Dict, priority: int = 0) -> None:
        # Use negative priority so higher priority numbers pop first (min-heap)
        # Counter ensures FIFO for same priority
        heapq.heappush(self.heap, (-priority, self.counter, name, data))
        self.counter += 1

    def get_next_job(self) -> Optional[Tuple[str, Dict]]:
        if not self.heap:
            return None
        _, _, name, data = heapq.heappop(self.heap)
        return (name, data)
```
    *   Wait, the prompt example `queue.add_job("normal", {"type": "normal"}, priority=0)` implies `name` is first arg, `data` is second.
    *   My signature: `add_job(self, name: str, data: Dict, priority: int = 0)`.
    *   Matches.

    *   Wait, the prompt asks for `get_next_job() -> tuple[str, dict] | None`.
    *   I will use `tuple[str, dict] | None` in the type hint to match the request exactly.
    *   I need to import `heapq`.
    *   I need to make sure the code is complete.

    *   One minor thing: `Tuple` vs `tuple`. `tuple` is a builtin generic in 3.9+. `Tuple` is from `typing`. I'll use `tuple` for simplicity and modern compatibility.
    *   I'll stick to the requested signature style.

    *   Wait, I should check if `typing` is needed for the return annotation `tuple[str, dict] | None`. In Python 3.10+, this is valid without imports. In 3.9, it might need `from __future__ import annotations` or `typing`. To be safe and standard, I'll use `typing` imports or just rely on 3.10+ syntax if assuming modern environment. Given "Write only the Python code", I should probably include imports.
    *   I will use `Optional` from `typing` to be safe across versions or just use `|` if I assume 3.10+. The prompt uses `|` in the requirement `get_next_job() -> tuple[str, dict] | None`. I will use that syntax.
    *   I will import `heapq`.

    *   Wait, one more check: `tuple[str, dict]`. `dict` is a builtin.
    *   Okay, ready to generate.

    *   Re-reading requirement: "Write only the Python code, no explanations."
    *   I must ensure no markdown text outside the code block? Usually, "Write only the Python code" means the output should be the code block content. I will provide the code block.

    *   Wait, I need to make sure I don't add markdown ticks if the instruction implies raw text, but usually, in these contexts, a code block is expected. However, "Write only the Python code" often means "Don't write text like 'Here is the code'". I will output the code within a markdown block for clarity, or just raw text. Standard practice for "Write only the Python code" is to provide the code block.
    *   Actually, usually it means "Don't add conversational filler". I will use a markdown code block.

    *   Wait, I'll check the priority logic again.
    *   Priority 2 (Critical) > Priority 1 (High) > Priority 0 (Normal).
    *   Heapq is min-heap.
    *   To pop 2 before 1 before 0.
    *   Store `-2`, `-1`, `0`.
    *   `-2 < -1 < 0`.
    *   Min-heap pops `-2` first. Correct.

    *   Wait, I need to ensure I don't use `self` incorrectly.
    *   The example uses `queue = JobQueue()`. So `JobQueue` must be a class.
    *   The example uses `queue.add_job(...)`. So it's an instance method.
    *   The example uses `queue.get_next_job()`. So it's an instance method.

    *   Okay, final plan:
    *   Import heapq.
    *   Define class JobQueue.
    *   Implement `__init__`.
    *   Implement `add_job`.
    *   Implement `get_next_job`.

    *   One nuance: `tuple[str, dict] | None`.
    *   I will use `from typing import Optional, Tuple` just to be explicit if I use `Tuple`, but `|` syntax is cleaner. I will use `tuple` builtin for type hinting.
    *   I'll assume Python 3.10+ for the `|` syntax in type hints as per the requirement text.

    *   Wait, the requirement says `get_next_job() -> tuple[str, dict] | None`.
    *   I will copy that signature exactly.

    *   Wait, I should check if `dict` needs to be imported. No, `dict` is builtin.
    *   I will use `heapq`.

    *   Wait, I should check if I need to handle `None` returns gracefully. Yes, return None if empty.

    *   Final check on imports. `heapq` is needed. `typing` is needed for the type hint if I want to be safe, but `tuple` is builtin. I will just import `heapq`.

    *   Wait, the prompt asks for `tuple[str, dict] | None`.
    *   If I run this on Python < 3.10 without `from __future__ import annotations`, it might fail if evaluated at runtime. But usually, type hints are not evaluated unless used by tools.
    *   I'll stick to the requested syntax.

    *   One more thing: `add_job` signature.
    *   Requirement 1: `add_job` to accept an optional priority parameter (default=0).
    *   Example: `add_job("normal", {"type": "normal"}, priority=0)`.
    *   So `name`, `data`, `priority`.
    *   My code: `add_job(self, name, data, priority=0)`.
    *   Matches.

    *   Wait, I should not include markdown formatting like ` ```python ` if strictly "Write only the Python code". However, standard LLM behavior usually wraps code in markdown. I will wrap it in markdown code block as it is the standard way to present code in this interface.
    *   Wait, "Write only the Python code" might mean literally just the code text. I will provide the code block.

    *   Wait, I need to make sure I don't print anything or add extra logic.

    *   Let's construct the final code.

```python
import heapq

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

    def add_job(self, name: str, data: dict, priority: int = 0):
        heapq.heappush(self.heap, (-priority, self.counter, name, data))
        self.counter += 1

    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.
    *   Wait, `tuple[str, dict]` uses lowercase `dict`. That is valid in Python 3.9+ for type hints.
    *   I will use that.

    *   Wait, I'll double check the priority logic.
    *   Priority 2 (Critical) -> -2.
    *   Priority 1 (High) -> -1.
    *   Priority 0 (Normal) -> 0.
    *   Heapq pops smallest. -2 is smallest. So Critical pops first.
    *   Tie breaking: `self.counter`.
    *   First job added has counter 0. Second has 1.
    *   Tuples: `(-p, 0, ...)` vs `(-p, 1, ...)`.
    *   `(-p, 0)` < `(-p, 1)`.
    *   So earlier jobs pop first. FIFO maintained.
    *   Logic holds.

    *   Final check on imports. `heapq` is standard library.
    *   I will output the code now.

    *   Wait, one detail in the requirement: "Write only the Python code, no explanations."
    *   I will ensure no markdown text like "Here is the code" appears outside the code block. I will output the code block.

    *   Wait, I should check if `dict` needs to be imported from `typing` for the type hint `tuple[str, dict]`. In Python 3.9+, `dict` works as a generic type. In 3.8, it needs `Dict`. Given the prompt uses `tuple[str, dict]`, I will assume Python 3.9+ semantics.

    *   Wait, I will use `typing` just in case to be safe? No, `tuple` and `dict` are builtins in 3.9+. The prompt uses `tuple[str, dict]`. I will follow that style.

    *   Wait, I'll add `from typing import Optional` just to be safe if `|` is used? No, `|` is syntax.
    *   Okay, I will stick to the simplest valid code.

    *   Wait, I'll check if I need to handle the case where `data` is not a dict in type hinting. The example shows `{"type": "normal"}`.
    *   Okay.

    *   Wait, I need to make sure I don't use `self` in the example usage logic, just the class definition.
    *   Okay.

    *   One more check: `get_next_job() -> tuple[str, dict] | None`.
    *   I will use this exact return type annotation.

    *   Wait, I need to ensure I don't import `typing` if I don't use it.
    *   I will import `heapq`.

    *   Final verification of the code.
    *   Imports: `heapq`.
    *   Class: `JobQueue`.
    *   Methods: `__init__`, `add_job`, `get_next_job`.
    *   Logic: Heap with negative priority and counter.
    *   Return: Tuple of name and data.
    *   Constraints met.

    *   Wait, I'll remove type hints from `add_job` arguments if not strictly required to keep it clean, but the requirement `get_next_job` has a type hint. I'll add type hints to `add_job` for consistency.
    *   Actually, I'll keep type hints minimal or consistent.
    *   I'll use `name: str, data: dict, priority: int = 0`.

    *   Wait, I should check if `dict` is valid in type hint without import in Python 3.10. Yes.
    *   Okay.

    *   Wait, 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, data: dict, priority: int = 0) -> None:
        heapq.heappush(self.heap, (-priority, self.counter, name, data))
        self.counter += 1

    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.

    *   Wait, one detail. `get_next_job` returns `tuple[str, dict]`.
    *   My code returns `(name, data)`.
    *   `name` is str, `data` is dict.
    *   Matches.

    *   One more detail: `add_job` in example: `queue.add_job("normal", {"type": "normal"}, priority=0)`.
    *   My code: `add_job(self, name, data, priority=0)`.
    *   Matches.

    *   Wait, I should check if the prompt implies I should just provide the methods or the whole class.
    *   "Implement priority-based job scheduling for the queue."
    *   "Example: queue = JobQueue()..."
    *   So I need to provide the `JobQueue` class.

    *   Okay, ready.

</reasoning_content>

<content>
```python
import heapq

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

    def add_job(self, name: str, data: dict, priority: int = 0) -> None:
        # Store as (-priority, counter, name, data)
        # Min-heap: smaller value pops first.
        # -2 (priority 2) < -1 (priority 1) < -0 (priority 0)
        heapq.heappush(self.heap, (-priority, self.counter, name, data))
        self.counter += 1

    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>