<reasoning_content>
*   Goal: Implement priority-based job scheduling for a `JobQueue` class.
    *   Requirement 1: `add_job` should accept an optional `priority` parameter (default=0).
    *   Requirement 2: Higher priority jobs processed before lower priority jobs.
    *   Requirement 3: FIFO order for same priority.
    *   Requirement 4: `get_next_job()` returns the highest priority job or `None`.
    *   Priority Levels: 0 (Normal), 1 (High), 2 (Critical).
    *   Implementation detail: To maintain FIFO for same priority while prioritizing higher numbers, a priority queue (heap) is ideal. However, standard heaps are min-heaps. I need to handle priority (descending) and timestamp/sequence (ascending).

    *   Python's `heapq` module implements a min-heap.
    *   To handle priorities where higher numbers are better: store priority as negative numbers (e.g., 2 becomes -2, 1 becomes -1, 0 becomes 0).
    *   To handle FIFO for same priority: store an incrementing counter.
    *   Entry format in heap: `(priority_val, sequence_number, job_id, payload)`.
    *   Wait, the user asked for `get_next_job() -> tuple[str, dict] | None`. The return type is specific.

    *   `self.queue = []` (heap)
    *   `self.counter = 0`
    *   `add_job(job_id, data, priority=0)`:
        *   Push `(-priority, self.counter, job_id, data)` into heap.
        *   Increment `self.counter`.
    *   `get_next_job()`:
        *   Pop from heap.
        *   Return `(job_id, data)` or `None`.

    *   Class name: `JobQueue`.
    *   `add_job` signature: `add_job(self, job_id: str, data: dict, priority: int = 0)`.
    *   `get_next_job` signature: `get_next_job(self) -> tuple[str, dict] | None`.

    *   Priority 2 -> -2
    *   Priority 1 -> -1
    *   Priority 0 -> 0
    *   Heap min: -2 < -1 < 0. So -2 comes out first. This correctly handles higher numbers as higher priority.
    *   Sequence counter ensures FIFO for same priority because if priorities are equal, the smaller sequence number wins.

    ```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):
            # Higher priority value means higher priority.
            # Use negative priority because heapq is a min-heap.
            # Use counter to ensure FIFO for 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)
    ```

    *   Modify `add_job` to accept optional priority (default=0)? Yes.
    *    Higher priority processed before lower? Yes (-2 < -1 < 0).
    *    Same priority maintain FIFO? Yes (counter).
    *    `get_next_job` signature correct? Yes.

    Wait, I should double check the `priority` values provided.
    0: Normal
    1: High
    2: Critical
    If I use negative values, 2 becomes -2, 1 becomes -1, 0 becomes 0.
    Heap pops smallest first: -2 is smallest. Correct.
</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 (smaller values come out first).
        # Use self.counter to ensure FIFO order for jobs with the 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>