<reasoning_content>
*   Implement a priority-based job scheduling system.
    *   `add_job(name, data, priority=0)`: Add a job.
    *   `get_next_job() -> tuple[str, dict] | None`: Get the highest priority job.
    *   Higher priority (higher number) comes first.
    *   Same priority: FIFO (First-In-First-Out).
    *   Priority levels: 0 (Normal), 1 (High), 2 (Critical).
    *   Output should be Python code only.

    *   A priority queue is needed.
    *   Python's `heapq` is a min-heap. To implement a max-heap (higher priority first), I can use negative priority.
    *   To maintain FIFO for same priority, I need a counter/sequence number. The heap tuple would be `(-priority, sequence_number, name, data)`.
    *   `sequence_number` ensures that for identical priorities, the one added earlier (smaller sequence number) is popped first.

    *   Class `JobQueue`.
    *   `__init__`: Initialize a list for the heap and a counter.
    *   `add_job`:
        *   Increment counter.
        *   Push `(-priority, counter, name, data)` to heap.
    *   `get_next_job`:
        *   If heap is empty, return `None`.
        *   Pop from heap.
        *   Return `(name, data)`.

    ```python
    import heapq

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

        def add_job(self, name: str, data: dict, priority: int = 0):
            # heapq is a min-heap. To make it a max-priority queue,
            # we negate the priority.
            # We use self._counter to maintain FIFO for same priority.
            heapq.heappush(self._queue, (-priority, self._counter, name, data))
            self._counter += 1

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

    *   `add_job` accepts optional `priority`? Yes.
    *   Higher priority first? Yes (via `-priority`).
    *   Same priority FIFO? Yes (via `counter`).
    *   `get_next_job` returns `tuple[str, dict] | None`? Yes.
    *   Example check:
        *   `normal` (p=0, c=0) -> `(0, 0, "normal", ...)`
        *   `critical` (p=2, c=1) -> `(-2, 1, "critical", ...)`
        *   `high` (p=1, c=2) -> `(-1, 2, "high", ...)`
        *   Heap: `[(-2, 1, "critical", ...), (0, 0, "normal", ...), (-1, 2, "high", ...)]` (simplified)
        *   Popping:
            1. `-2` is smallest -> `critical`
            2. `-1` is next smallest -> `high`
            3. `0` is largest -> `normal`
    *   Requirement: "Higher priority jobs should be processed before lower priority jobs".
    *   Priority levels: 2 is highest, 0 is lowest.
    *   Heap will pop `-2` then `-1` then `0`. Correct.

    *   Use type hinting as requested in the method signature.
    *   Use `heapq`.

    ```python
    import heapq

    class JobQueue:
        def __init__(self):
            self._jobs = []
            self._index = 0

        def add_job(self, name: str, data: dict, priority: int = 0) -> None:
            # Use negative priority for max-heap behavior
            # Use index to maintain FIFO for equal priorities
            heapq.heappush(self._jobs, (-priority, self._index, name, data))
            self._index += 1

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

    Wait, the prompt asks for `tuple[str, dict] | None`. My implementation does that.

    Wait, checking requirements again:
    "Higher priority jobs should be processed before lower priority jobs"
    2 is critical. 0 is normal.
    `-2` is smaller than `0`.
    `heapq` pops the smallest element.
    So `-2` pops before `0`.
    Correct.

    Final check on types. `tuple[str, dict] | None` requires Python 3.10+ syntax (the `|` operator). I will assume a modern environment or just use it as written in the prompt.

    *Self-Correction on Requirements:*
    Example shows `queue.add_job("normal", {"type": "normal"}, priority=0)`.
    `queue.get_next_job()` returns critical first.
    My logic: `priority=2` -> `-2`. `priority=0` -> `0`. `-2 < 0`. Popped first. Correct.

    One detail: `tuple[str, dict] | None` is what I should return.

    ```python
    import heapq

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

        def add_job(self, name: str, data: dict, priority: int = 0) -> None:
            heapq.heappush(self._jobs, (-priority, self._counter, name, data))
            self._counter += 1

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

    Check FIFO requirement:
    Jobs: A (p=1), B (p=1)
    A: `(-1, 0, 'A', ...)`
    B: `(-1, 1, 'B', ...)`
    `heappop` pops `(-1, 0, ...)` then `(-1, 1, ...)`.
    Correct.

    The prompt doesn't specify importing `typing` but uses `tuple[...] | None` syntax which is native in 3.10. I'll provide standard implementation.

    *Wait, one tiny detail*: The prompt shows `get_next_job() -> tuple[str, dict] | None`.
    If I return `(name, data)`, that is a tuple of `(str, dict)`.

    Final Code Structure:
    ```python
    import heapq

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

        def add_job(self, name: str, data: dict, priority: int = 0) -> None:
            heapq.heappush(self._jobs, (-priority, self._counter, name, data))
            self._counter += 1

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

    Wait, the return type is `tuple[str, dict] | None`.
    `return name, data` is equivalent to `return (name, data)`.

    Final Polish.
</reasoning_content>

<content>
```python
import heapq

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

    def add_job(self, name: str, data: dict, priority: int = 0) -> None:
        # We use -priority because heapq is a min-heap, and we want higher 
        # priority numbers to be processed first.
        # self._counter ensures FIFO order for jobs with the same priority.
        heapq.heappush(self._jobs, (-priority, self._counter, name, data))
        self._counter += 1

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