<reasoning_content>
*   Input: A request to implement a basic job queue in Python.
    *   Requirements:
        1.  `JobQueue` class with `add_job(job_id: str, data: dict) -> str` and `get_result(job_id: str) -> dict | None`.
        2.  FIFO (First-In-First-Out) order.
        3.  Store jobs internally until processed.
        4.  Unique `job_id` returned when added.
    *   Constraints: Write only Python code, no explanations.

    *   To handle FIFO, a `collections.deque` or a simple list (though deque is more efficient for popping from the front) is suitable.
    *   To store job results, a dictionary mapping `job_id` to the result dictionary is needed.
    *   Since the prompt asks for `get_result` but doesn't explicitly ask for a `process_jobs` method, but implies jobs *are* processed, I should probably include a way to simulate processing or at least a way to set the result so `get_result` works in the example.
    *   *Correction*: Looking at the example: `job_id = queue.add_job(...)`, then `result = queue.get_result(...)`. This implies that `add_job` puts it in a list/queue, and there must be a way for the "system" to mark it as done.
    *   Wait, the requirement says "Jobs should be processed in FIFO order". Usually, a job queue system has a worker or a method to process the next job.
    *   Let's look closer at the requirements:
        *   `add_job`: Adds job, returns id.
        *   `get_result`: Returns result or None.
    *   If I only have those two methods, how does a job get "processed" and its result stored?
    *   Actually, to make the example work, I need a way to put a result into the dictionary. Since the prompt doesn't specify a `complete_job` method, but the example shows `After processing...`, I should probably include a `complete_job` method or similar, or just assume the result is stored somewhere.
    *   Wait, looking at standard interview questions like this, usually there's a `process_next_job()` method.
    *   Let's re-read: "The queue should store jobs internally until they are processed".
    *   Let's provide a `process_next_job` method to satisfy the "processed in FIFO order" requirement. Or, perhaps the user wants me to interpret "processed" as an external action and just provide the storage logic.
    *   Actually, to make the example usable, I'll add a `complete_job` method internally or simply ensure `get_result` returns something.
    *   Let's stick to the exact signatures requested but add a `process_next_job` method to handle the FIFO part.

    *   `self.queue = deque()`
    *   `self.results = {}`
    *   `add_job(job_id, data)`: Add `(job_id, data)` to `self.queue`.
    *   `get_result(job_id)`: Return `self.results.get(job_id)`.
    *   `process_next_job()`: Pop from front of `self.queue`. Simulate "processing" (maybe just store a dummy result).

    *Self-Correction*: If I only write the requested methods, the example provided won't actually "work" unless I provide a way for the job to reach the "completed" state. I'll include a `process_next_job` method to facilitate the FIFO requirement.

    Wait, if I look at the prompt again: "Jobs should be processed in FIFO order". This implies that the *queue* mechanism handles the order.
    Let's refine the class:
    ```python
    from collections import deque
    from typing import Dict, Optional

    class JobQueue:
        def __init__(self):
            self.queue = deque()
            self.results = {}

        def add_job(self, job_id: str, data: dict) -> str:
            self.queue.append((job_id, data))
            return job_id

        def get_result(self, job_id: str) -> Optional[dict]:
            return self.results.get(job_id)

        def process_next_job(self) -> dict:
            # This handles the FIFO requirement
            job_id, data = self.queue.popleft()
            # Simulate processing logic
            result = {"status": "completed", "original_data": data}
            self.results[job_id] = result
            return result
    ```
    However, the prompt only asks for `add_job` and `get_result`. I will provide those and include a `complete_job` or `process_next_job` so the user's example is actually valid. Actually, to be safe and stick to the prompt strictly, I'll just implement the two requested methods and a simple way to simulate the "processing" if needed, but I'll stick to the requested ones primarily.

    Actually, looking at the prompt "Write only the Python code, no explanations", I should provide a clean implementation.

    Refined Plan:
    1. `JobQueue` class.
    2. `__init__` with a deque for the queue and a dict for results.
    3. `add_job`: pushes to deque.
    4. `get_result`: looks up in dict.
    5. I will add `process_next_job` because "Jobs should be processed in FIFO order" is a requirement, and `get_result` would always return `None` otherwise.

    Actually, I'll make it even simpler.
    Requirements:
    1. `add_job`
    2. `get_result`
    3. FIFO order.
    4. Unique job_id.

    ```python
    from collections import deque
    from typing import Dict, Optional

    class JobQueue:
        def __init__(self):
            self.queue = deque()
            self.results = {}

        def add_job(self, job_id: str, data: dict) -> str:
            self.queue.append((job_id, data))
            return job_id

        def get_result(self, job_id: str) -> dict | None:
            return self.results.get(job_id)

        def process_next_job(self) -> dict:
            if not self.queue:
                return None
            job_id, data = self.queue.popleft()
            # Simulate processing logic
            result = {"status": "success", "data": data}
            self.results[job_id] = result
            return result
    ```

    Wait, the prompt doesn't ask for `process_next_job`, but it says "Jobs should be processed in FIFO order". If I don't provide a process method, the FIFO part is never realized. I'll include it as it's necessary for the logic.

    Actually, I will just provide the requested methods. If the user wants to process them, they'd call a method I provide.

    Wait, looking at the example:
    `job_id = queue.add_job("job1", {"task": "process_data"})`
    `# After processing...`
    `result = queue.get_result("job1")`
    This implies that some external code (or a method I didn't list but is implied) does the processing.
    To satisfy the FIFO requirement strictly, the `JobQueue` should probably have a `process_next_job` method.

    Let's check the prompt again.
    "The queue should store jobs internally until they are processed".
    "Jobs should be processed in FIFO order".

    I will include a `process_next_job` method.

    Wait, let's look at the return type for `get_result`: `dict | None`. This suggests using the `|` syntax (Python 3.10+).

    One more detail: "unique job_id". The prompt says `add_job(job_id: str, ...)`. This implies the *user* provides the ID. If the user provides the ID, it's the user's responsibility to ensure uniqueness? Or should I check it? The prompt says "Each job has a unique job_id that is returned when added". This suggests I might need to generate it? No, the signature `add_job(job_id: str, ...)` clearly shows the ID is an input.

    Revised plan for `process_next_job`:
    Since it's not in the requirements list, but required for functionality, I'll add it.

    Wait, I'll just implement the two requested methods and a private-ish `_complete_job` or just `process_next_job`. Actually, I'll stick to exactly what's asked + the FIFO logic.

    Actually, many "Job Queue" interview questions have a `process_next_job` method. I'll include it to ensure the code is actually functional.

    Final check on Requirements:
    1. `JobQueue` class.
    2. `add_job` -> returns job_id.
    3. `get_result` -> returns dict or None.
    4. FIFO order.
    5. Store internally.
    6. Unique id.

    I will implement:
    ```python
    from collections import deque
    from typing import Dict, Optional

    class JobQueue:
        def __init__(self):
            self.queue = deque()
            self.results = {}

        def add_job(self, job_id: str, data: dict) -> str:
            self.queue.append((job_id, data))
            return job_id

        def get_result(self, job_id: str) -> dict | None:
            return self.results.get(job_id)

        def process_next_job(self) -> dict | None:
            if not self.queue:
                return None
            job_id, data = self.queue.popleft()
            # Simulate processing
            result = {"job_id": job_id, "status": "completed", "data": data}
            self.results[job_id] = result
            return result
    ```

    Wait, the prompt says "Write only the Python code, no explanations."
    I should make sure the code is clean.

    One small detail: The prompt says "Each job has a unique job_id that is returned when added". This could mean I should generate it, but the signature `add_job(job_id: str, ...)` says the id is passed in. If the id is passed in, I just return it.

    Let's refine the signature `get_result(job_id: str) -> dict | None`.
    I will use `typing.Union` or just `dict | None` if I assume 3.10+. `dict | None` is standard now.

    ```python
    from collections import deque

    class JobQueue:
        def __init__(self):
            self.queue = deque()
            self.results = {}

        def add_job(self, job_id: str, data: dict) -> str:
            self.queue.append((job_id, data))
            return job_id

        def get_result(self, job_id: str) -> dict | None:
            return self.results.get(job_id)

        def process_next_job(self) -> dict | None:
            if not self.queue:
                return None
            job_id, data = self.queue.popleft()
            # Simulate some processing logic
            result = {"status": "completed", "data": data}
            self.results[job_id] = result
            return result
    ```
    Actually, I'll stick to the specific methods requested and only add `process_next_job` because it's the only way to satisfy "Jobs should be processed in FIFO order".

    Wait, I'll check if there's any other way to interpret "processed in FIFO order". If I don't have a process method, I can't satisfy that.

    Actually, I'll just provide the two required methods and the `process_next_job` method to make the example work.

    Wait, one more thing: "The queue should store jobs internally until they are processed".
    If I don't have a process method, they just stay in the `deque` forever.

    Final Code Structure:
    - Imports
    - JobQueue Class
    - Init
    - add_job
    - get_result
    - process_next_job (to fulfill FIFO requirement)

    One detail: "Each job has a unique job_id that is returned when added".
    Since the signature provided is `add_job(job_id: str, data: dict)`, I don't need to generate it, I just return the input.

    Let's double check the signature of `get_result`. `dict | None` is Python 3.10+. I'll use that.

    ```python
    from collections import deque
    from typing import Dict, Optional

    class JobQueue:
        def __init__(self):
            self.queue = deque()
            self.results: Dict[str, dict] = {}

        def add_job(self, job_id: str, data: dict) -> str:
            self.queue.append((job_id, data))
            return job_id

        def get_result(self, job_id: str) -> dict | None:
            return self.results.get(job_id)

        def process_next_job(self) -> dict | None:
            if not self.queue:
                return None
            job_id, data = self.queue.popleft()
            # Example processing logic
            result = {"job_id": job_id, "status": "completed", "data": data}
            self.results[job_id] = result
            return result
    ```

    Wait, I just noticed the prompt says "Write only the Python code, no explanations."
    I'll provide exactly that.

    One tiny detail: Should I handle the case where `job_id` is not unique? The requirement says "Each job has a unique job_id". Usually, that's a precondition for the caller, but I could check it. I'll skip the check to keep it "basic" as requested.

    One more look at the example:
    ```python
    job_id = queue.add_job("job1", {"task": "process_data"})
    # After processing...
    result = queue.get_result("job1")
    ```
    My `process_next_job` method makes this flow work.

    Final check on requirements:
    1. `JobQueue` class: Yes.
    2. `add_job`, `get_result` methods: Yes.
    3. FIFO order: Yes (deque popleft).
    4. Store internally: Yes (deque and dict).
    5. Unique job_id returned: Yes.

    Ready.
</reasoning_content>

<content>
```python
from collections import deque
from typing import Dict, Optional

class JobQueue:
    def __init__(self):
        # Stores jobs as (job_id, data) tuples to maintain FIFO order
        self.queue = deque()
        # Stores results mapped by job_id
        self.results: Dict[str, dict] = {}

    def add_job(self, job_id: str, data: dict) -> str:
        """
        Adds a job to the queue and returns the unique job_id.
        """
        self.queue.append((job_id, data))
        return job_id

    def get_result(self, job_id: str) -> dict | None:
        """
        Returns the result of a completed job, or None if not completed.
        """
        return self.results.get(job_id)

    def process_next_job(self) -> dict | None:
        """
        Processes the next job in the queue (FIFO) and stores its result.
        This method ensures the FIFO requirement is met.
        """
        if not self.queue:
            return None
            
        job_id, data = self.queue.popleft()
        
        # Simulate processing logic
        result = {
            "job_id": job_id,
            "status": "completed",
            "original_data": data
        }
        
        self.results[job_id] = result
        return result
```
</content>