<reasoning_content>
*   Goal: Implement priority-based job scheduling in a `JobQueue` class.
    *    Requirements:
        1. `add_job(job_id, data, priority=0)`: Add a job with an optional priority.
        2. Priority logic: Higher priority (larger number) first.
        3. Tie-breaking: Same priority jobs should follow FIFO (First-In-First-Out).
        4. `get_next_job() -> tuple[str, dict] | None`: Retrieve and remove the highest priority job.
    *    Priority values: 0 (Normal), 1 (High), 2 (Critical).

    *   To efficiently handle priority queues, a `heapq` (binary heap) is standard.
    *   `heapq` is a min-heap. Since I need "higher priority first" (2 > 1 > 0), I can either store priorities as negative values or use a custom comparison.
    *   To maintain FIFO for equal priorities, I need a tie-breaker (like a counter/sequence number) because `heapq` doesn't guarantee order for equal keys.

    *   *Data Structure*: A list to be used with `heapq`.
    *   *Items in heap*: `(priority, insertion_order, job_id, data)`.
    *   *Wait*, if I use `heapq` as a min-heap and want highest priority first:
        *   Priority 2 should be "smaller" than 1 in the heap context.
        *   So, I can store `(-priority, counter, job_id, data)`.
    *   *Counter*: A simple integer incremented every time a job is added.

    ```python
    import heapq
    from typing import Tuple, Dict, Optional

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

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

        def get_next_job(self) -> Optional[Tuple[str, dict]] :
            if not self.heap:
                return None
            priority_neg, count, job_id, data = heapq.heappop(self.heap)
            return (job_id, data)
    ```

    *   `add_job` accepts `priority=0`? Yes.
    *   Higher priority first? Yes (`-2 < -1 < 0`).
    *   Same priority FIFO? Yes (the `counter` handles this).
    *   `get_next_job()` signature matches? Yes.

    *   The user asked for "only the Python code, no explanations".
</reasoning_content>

<content>
```python
import heapq
from typing import Tuple, Dict, Optional

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

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

    def get_next_job(self) -> Optional[Tuple[str, dict]] :
        if not self.heap:
            return None
        
        priority_neg, count, job_id, data = heapq.heappop(self.heap)
        return (job_id, data)
```
</content>