<reasoning_content>
The user wants a priority-based job scheduler implemented in Python.
Key requirements:
1. `add_job(name, params, priority=0)` method.
2. Higher priority number = processed first (1 is high, 2 is critical, 0 is normal). Wait, the example says:
   - priority=0: Normal
   - priority=1: High
   - priority=2: Critical
   - "Higher priority jobs should be processed before lower priority jobs"
   - So priority 2 > priority 1 > priority 0.
3. FIFO for same priority.
4. `get_next_job() -> tuple[str, dict] | None` method.

Data structure choice:
- A list of tuples: `(priority, insertion_order, job_name, job_params)`
- Use `heapq` or sort.
- Since we need to pop the highest priority, and `heapq` is a min-heap, we can store `(-priority, insertion_order, job_name, job_params)`.
- Or just use a list and sort/pop max. Given no specific performance constraints, a list with `max` or `heapq` is fine.
- Let's use `heapq` for efficiency, or just a list and sort if simplicity is preferred. The prompt doesn't specify performance, but `heapq` is standard for priority queues.
- Wait, `heapq` pops the smallest. So storing `(-priority, counter, name, params)` works.
- Counter ensures FIFO for same priority.

Let's draft the class:

```python
import heapq

class JobQueue:
    def __init__(self):
        self._queue = []
        self._counter = 0
    
    def add_job(self, name: str, params: dict, priority: int = 0):
        # Store as (-priority, counter, name, params)
        # heapq is min-heap, so -priority makes higher priority pop first
        heapq.heappush(self._queue, (-priority, self._counter, name, params))
        self._counter += 1
    
    def get_next_job(self) -> tuple[str, dict] | None:
        if not self._queue:
            return None
        _, _, name, params = heapq.heappop(self._queue)
        return (name, params)
```

Wait, the prompt says:
`get_next_job() -> tuple[str, dict] | None`
The example:
```python
queue = JobQueue()
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 job first
```
My implementation matches this.

Let's double check the signature for `add_job`. The prompt says:
"Modify `add_job` to accept an optional priority parameter (default=0)"
It doesn't specify the exact signature, but `add_job(name, params, priority=0)` is standard.
The example shows: `queue.add_job("normal", {"type": "normal"}, priority=0)`
So `add_job(name, params, priority=0)` is correct.

Wait, should I include type hints? The prompt uses them in `get_next_job() -> tuple[str, dict] | None`. I'll add them for consistency.

One detail: `tuple[str, dict] | None` is Python 3.10+ syntax. I'll stick to it or use `Optional[Tuple[str, dict]]`. I'll use the prompt's syntax.

Let's verify FIFO for same priority.
`heapq` compares tuples element by element.
`(-priority, counter, name, params)`
If priorities are equal, `-priority` is equal. Then it compares `counter`. Since `counter` increases monotonically, smaller counter means earlier insertion. So FIFO is preserved.

What if `params` is not comparable? It won't be compared because `counter` breaks ties. So it's safe.

Code structure:
```python
import heapq
from typing import Tuple, Optional

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

    def add_job(self, name: str, params: dict, priority: int = 0) -> None:
        heapq.heappush(self._queue, (-priority, self._counter, name, params))
        self._counter += 1

    def get_next_job(self) -> Tuple[str, dict] | None:
        if not self._queue:
            return None
        _, _, name, params = heapq.heappop(self._queue)
        return name, params
```

Wait, `Tuple[str, dict] | None` might cause syntax error in older Python versions, but the prompt uses it, so I'll assume Python 3.10+ or just use `Optional[Tuple[str, dict]]` to be safe, or stick to the prompt's exact syntax. I'll use `tuple[str, dict] | None` as requested. Actually, `typing` module is fine. I'll just write it cleanly.

Let's check if there's any edge case.
`params` is passed by reference. Modifying it later might affect stored job, but that's typical for this kind of exercise. I won't deep copy unless specified.
The prompt says "Write only the Python code, no explanations."

I will produce the code block.

One minor thing: `add_job` signature in the prompt example: `queue.add_job("normal", {"type": "normal"}, priority=0)`
So `add_job(self, name, params, priority=0)`

I'll write it out.

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

class JobQueue:
    def __init__(self) -> None:
        self._queue: list[tuple[int, int, str, dict]] = []
        self._counter: int = 0

    def add_job(self, name: str, params: dict, priority: int = 0) -> None:
        heapq.heappush(self._queue, (-priority, self._counter, name, params))
        self._counter += 1

    def get_next_job(self) -> tuple[str, dict] | None:
        if not self._queue:
            return None
        _, _, name, params = heapq.heappop(self._queue)
        return name, params
```

Wait, `list[tuple[int, int, str, dict]]` is Python 3.9+ syntax. I'll keep it simple or omit type hints for internal variables to avoid version issues, but the prompt uses `tuple[str, dict] | None`, so 3.10+ is assumed. I'll stick to standard hints.

Actually, to be perfectly safe and clean:
```python
import heapq

class JobQueue:
    def __init__(self):
        self._queue = []
        self._counter = 0
        
    def add_job(self, name: str, params: dict, priority: int = 0) -> None:
        heapq.heappush(self._queue, (-priority, self._counter, name, params))
        self._counter += 1
        
    def get_next_job(self) -> tuple[str, dict] | None:
        if not self._queue:
            return None
        _, _, name, params = heapq.heappop(self._queue)
        return name, params
```

This looks solid. Matches all requirements.
Higher priority processed first: `-priority` ensures larger priority becomes more negative, so it pops first.
FIFO: `_counter` ensures stable ordering.
`get_next_job` returns `tuple[str, dict] | None`.
`add_job` accepts optional priority default 0.

One thing: The prompt says `get_next_job() -> tuple[str, dict] | None`. I'll use exactly that.
I'll output just the code.
Done. 
Let's double check the prompt: "Write only the Python code, no explanations."
I will provide exactly that.
All good. 
Output matches. 
Proceeds. 
(Self-Correction/Refinement during thought)
Wait, should `params` be copied to avoid mutation issues? Usually not required unless specified. I'll leave it as is.
The type hint `tuple[str, dict] | None` is valid in Python 3.10+. I'll keep it.
I'll add `from typing import Tuple, Optional` just in case, but the prompt uses the new syntax, so I'll stick to it. Actually, `tuple[str, dict] | None` is fine.

Final code:
```python
import heapq

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

    def add_job(self, name: str, params: dict, priority: int = 0) -> None:
        heapq.heappush(self._queue, (-priority, self._counter, name, params))
        self._counter += 1

    def get_next_job(self) -> tuple[str, dict] | None:
        if not self._queue:
            return None
        _, _, name, params = heapq.heappop(self._queue)
        return name, params
```
This satisfies everything. Output matches request.
Proceeds. 
One minor point: `add_job` signature in example is `queue.add_job("normal", {"type": "normal"}, priority=0)`. My signature matches.
All good. 
Output matches. 
Done. 
[Output Generation] -> *Proceeds*

</reasoning_content>

<content>
```python
import heapq

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

    def add_job(self, name: str, params: dict, priority: int = 0) -> None:
        heapq.heappush(self._queue, (-priority, self._counter, name, params))
        self._counter += 1

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