<reasoning_content>
*   Task: Implement priority-based job scheduling for a `JobQueue`.
    *   Requirements:
        1.  `add_job(name, data, priority=0)`: Optional priority parameter.
        2.  Higher priority first.
        3.  Same priority: FIFO (First-In-First-Out).
        4.  `get_next_job() -> tuple[str, dict] | None`: Retrieve and remove the highest priority job.
    *   Priority levels: 0 (Normal), 1 (High), 2 (Critical). *Wait*, the prompt says "Higher priority jobs should be processed before lower priority jobs". In standard priority queue logic, usually, a larger number means higher priority. The examples show `critical` with `2` comes first.
    *   FIFO for same priority: Using a heap is common for priority queues, but a standard heap (like `heapq`) doesn't guarantee FIFO for equal keys without a secondary key (like a sequence number/timestamp).

    *   Python's `heapq` is a min-heap.
    *   To handle "Higher priority first", we can store priority as a negative number (so 2 becomes -2, 1 becomes -1, 0 becomes 0; -2 < -1 < 0) or just negate it during insertion.
    *   To handle FIFO for equal priorities, we need a counter (sequence number). The tuple in the heap would be `(-priority, sequence_number, job_name, job_data)`.
    *   `sequence_number` will increment with every `add_job`.

    *   `self.queue`: A list to be used with `heapq`.
    *   `self.counter`: An integer to track order of arrival.
    *   `add_job(name, data, priority=0)`:
        *   `counter += 1`
        *   `heapq.heappush(self.queue, (-priority, self.counter, name, data))`
    *   `get_next_job()`:
        *   If `not self.queue`: return `None`.
        *   `_, _, name, data = heapq.heappop(self.queue)`
        *   return `(name, data)`

    *   `add_job("normal", ..., priority=0)` -> `heap: [ (0, 1, "normal", {...}) ]`
    *   `add_job("critical", ..., priority=2)` -> `heap: [ (-2, 2, "critical", {...}), (0, 1, "normal", {...}) ]`
    *   `add_job("high", ..., priority=1)` -> `heap: [ (-2, 2, ...), (-1, 3, ...), (0, 1, ...) ]`
    *   `get_next_job()`: pops `(-2, 2, "critical", {...})`. Returns `("critical", {...})`.

    *   Import `heapq`.
    *   Define `JobQueue` class.
    *   Implement methods.

    *   `priority=2` is Critical.
    *   `priority=1` is High.
    *   `priority=0` is Normal.
    *   The prompt says: "Higher priority jobs should be processed before lower priority jobs".
    *   If I use `heapq` directly with `priority` as is, `0` (Normal) would be popped before `2` (Critical) because `heapq` is a min-heap.
    *   Therefore, I must negate the priority: `(-priority, sequence_number, ...)`.

    *   `add_job("normal", ..., 0)`
    *   `add_job("high", ..., 1)`
    *   `add_job("critical", ..., 2)`
    *   Heap entries: `(0, 1, "normal", ...)`, `(-1, 2, "high", ...)`, `(-2, 3, "critical", ...)`
    *   Min-heap pops:
        1. `(-2, 3, "critical", ...)`
        2. `(-1, 2, "high", ...)`
        3. `(0, 1, "normal", ...)`
    *   This matches the requirement.

    *   "Write only the Python code, no explanations."

    ```python
    import heapq

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

        def add_job(self, name: str, data: dict, priority: int = 0):
            # Use -priority for max-heap behavior with heapq
            # Use self._counter for FIFO behavior with 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)
    ```

    Wait, let's check if `tuple[str, dict] | None` requires `from __future__ import annotations` or if I should use `Optional` for compatibility. The prompt uses the modern syntax `tuple[str, dict] | None`, so I'll stick to it.

    *Self-correction*: In the prompt example:
    `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` first.

    My logic:
    `(-2, count, "critical", ...)`
    `(-1, count, "high", ...)`
    `(0, count, "normal", ...)`
    Min-heap: -2 is smallest. Correct.

    One final check on FIFO:
    If priority is same:
    Job A: `(-1, 1, "A", ...)`
    Job B: `(-1, 2, "B", ...)`
    Heap pops `(-1, 1, ...)` first. Correct.

    Code implementation looks solid.

    ```python
    import heapq

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

        def add_job(self, name: str, data: dict, priority: int = 0) -> None:
            # heapq is a min-heap. To simulate a max-priority queue, we negate the priority.
            # We include a counter to ensure FIFO order for jobs with the 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)
    ```
</reasoning_content>

<content>
```python
import heapq

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

    def add_job(self, name: str, data: dict, priority: int = 0) -> None:
        """
        Adds a job to the queue.
        Higher priority values are processed first.
        Jobs with same priority follow FIFO.
        """
        # heapq is a min-heap. To process higher priority first, we negate the priority.
        # self._counter ensures FIFO order for jobs with the same priority.
        heapq.heappush(self._queue, (-priority, self._counter, name, data))
        self._counter += 1

    def get_next_job(self) -> tuple[str, dict] | None:
        """
        Returns the highest priority job from the queue.
        Returns None if the queue is empty.
        """
        if not self._queue:
            return None
        
        _, _, name, data = heapq.heappop(self._queue)
        return (name, data)
```
</content>