<reasoning_content>
*   Requirement 1: `add_job` must accept an optional `priority` parameter (default=0).
    *   Requirement 2: Higher priority jobs come first (priority 2 > 1 > 0).
    *   Requirement 3: Same priority = FIFO (First-In, First-Out).
    *   Requirement 4: `get_next_job()` returns the highest priority job or `None`.
    *   Expected Behavior: If jobs are added as (Normal, 0), (Critical, 2), (High, 1), `get_next_job()` should return the (Critical, 2) job first.

    *   To handle priority and order efficiently, a Max-Heap is the standard data structure.
    *   However, standard `heapq` in Python is a Min-Heap. To turn it into a Max-Heap, we can negate the priority value.
    *   To maintain FIFO for same priorities, we need a tie-breaker (a sequence number/counter).

    *   `heapq` module.
    *   `dataclass` or `namedtuple` isn't strictly required but helps with readability. A tuple `(priority, sequence_number, job_id, data)` works well.
    *   Since `heapq` is a Min-Heap:
        *   Priority $P$: Store as $-P$.
        *   Sequence $S$: Store as $S$ (incrementing counter).
        *   Job Data: Store as the job name/id and the dictionary.

    *   `self._queue = []`
    *   `self._counter = 0`
    *   `add_job(job_id, data, priority=0)`:
        *   `entry = (-priority, self._counter, job_id, data)`
        *   `heapq.heappush(self._queue, entry)`
        *   `self._counter += 1`
    *   `get_next_job()`:
        *   `if not self._queue: return None`
        *   `priority, count, job_id, data = heapq.heappop(self._queue)`
        *   `return (job_id, data)`

    *   `queue.add_job("normal", {"type": "normal"}, priority=0)` -> `(-0, 0, "normal", {...})`
    *   `queue.add_job("critical", {"type": "critical"}, priority=2)` -> `(-2, 1, "critical", {...})`
    *   `queue.add_job("high", {"type": "high"}, priority=1)` -> `(-1, 2, "high", {...})`
    *   `heapq.heappop` returns min. Min of `(-0, 0, ...), (-2, 1, ...), (-1, 2, ...)` is `(-2, 1, ...)`.
    *   Correct.

    *   The prompt asks for a class `JobQueue`.
    *   Return type for `get_next_job` is `tuple[str, dict] | None`.
</reasoning_content>

<content>
```python
import heapq

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

    def add_job(self, job_id: str, data: dict, priority: int = 0):
        # Use negative priority because heapq is a min-heap
        # Use counter to maintain FIFO for jobs with same priority
        heapq.heappush(self._queue, (-priority, self._counter, job_id, data))
        self._counter += 1

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