<reasoning_content>
*   Task: Implement priority-based job scheduling for a `JobQueue`.
    *    Requirements:
        1.  `add_job` accepts `priority` (default=0).
        2.  Higher priority jobs first.
        3.  FIFO for same priority.
        4.  `get_next_job()` returns `tuple[str, dict] | None`.
    *    Priority levels: 0 (Normal), 1 (High), 2 (Critical).
    *    Constraint: Write only Python code, no explanations.

    *   A heap (priority queue) is ideal for priority-based scheduling.
    *   Python's `heapq` module implements a min-heap.
    *   Since higher priority (higher number) should come first, and `heapq` is a min-heap, I should store priorities as negative numbers (e.g., -2 for Critical, -1 for High, 0 for Normal).
    *   To maintain FIFO for equal priorities, I need a tie-breaker (a sequence counter).

    *   `self.queue`: A list to act as a heap.
    *   `self.counter`: An integer to track order.

    *   `add_job(job_name, data, priority=0)`:
        *   Push `(-priority, counter, job_name, data)` into the heap.
        *   Increment counter.
    *   `get_next_job()`:
        *   Pop from the heap.
        *   Return `(job_name, data)` or `None`.

    ```python
    import heapq

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

        def add_job(self, job_name: str, data: dict, priority: int = 0):
            # Use negative priority for max-heap behavior using heapq (min-heap)
            # Use counter to maintain FIFO for same priorities
            heapq.heappush(self.queue, (-priority, self.counter, job_name, data))
            self.counter += 1

        def get_next_job(self) -> tuple[str, dict] | None:
            if not self.queue:
                return None
            priority, counter, job_name, data = heapq.heappop(self.queue)
            return (job_name, data)
    ```

    *   `add_job` signature matches requirements? Yes (`job_name`, `data`, `priority=0`).
    *   Higher priority first? Yes (negative priority makes higher values "smaller" in the min-heap).
    *   FIFO for same priority? Yes (`counter` ensures order).
    *   `get_next_job` returns `tuple[str, dict] | None`? Yes.
    *   Only Python code? Yes.
</reasoning_content>

<content>
```python
import heapq

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

    def add_job(self, job_name: str, data: dict, priority: int = 0):
        # Use negative priority to simulate a max-heap using heapq (min-heap)
        # counter ensures FIFO order for jobs with the same priority
        heapq.heappush(self.queue, (-priority, self.counter, job_name, data))
        self.counter += 1

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