<reasoning_content>
*   Goal: Implement a basic job queue in Python.
    *   Class: `JobQueue`.
    *   Methods:
        *   `add_job(job_id: str, data: dict) -> str`: Adds a job, returns `job_id`.
        *   `get_result(job_id: str) -> dict | None`: Gets the result of a completed job.
    *   Requirements:
        *   FIFO order.
        *   Internal storage until processed.
        *   Unique `job_id`.
    *   Constraint: Write only the Python code, no explanations.

    *   I need a way to store the order of jobs (queue).
    *   I need a way to store the results (mapping `job_id` to `result`).
    *   I need a way to simulate "processing" or have a placeholder for it, though the prompt doesn't explicitly say I need a `process_job` method, but the `get_result` implies there's a state change from "pending" to "completed".
    *   Wait, looking at the prompt again: "The queue should store jobs internally until they are processed".
    *   Looking at the example: `job_id = queue.add_job(...)`, then `result = queue.get_result(...)`.
    *   In a real scenario, there's a worker. Since the prompt asks for a *basic* job queue and only specifies `add_job` and `get_result`, I should probably have a mechanism to actually "complete" a job or at least store a mock result so `get_result` works.
    *   Wait, the prompt doesn't mention a `process_jobs` method. Usually, a job queue implementation in a coding challenge like this expects the user to handle the "processing" logic or provide a way for it to happen.
    *   However, strictly following the provided signatures:
        *   `add_job` adds to a queue.
        *   `get_result` returns a result.
    *   If there is no `process` method, how does a job get a result?
    *   Maybe the `data` provided in `add_job` should be transformed into a result? Or maybe the class should have a `process_next` method?
    *   Let's look at the prompt again: "The queue should store jobs internally until they are processed".
    *   Actually, the simplest implementation of a "Job Queue" that satisfies these two specific methods is one where `add_job` puts it in a list, and maybe I should add a method to process them, or assume the user wants me to provide the structure.
    *   Actually, looking at the example: `job_id = queue.add_job(...)`, then `# After processing...`, `result = queue.get_result(...)`. This implies that "processing" happens outside or inside.
    *   Since I need to return a result for `get_result`, I need a dictionary to store results.
    *   If I don't have a `process` method, I'll assume that for the sake of a "basic" implementation, `add_job` stores the job and I might need a private or public way to complete it.
    *   Actually, many interview questions like this imply that `add_job` puts it in a `collections.deque` and `get_result` checks a results dict.
    *   Let's stick to the prompt exactly.

    *   `self._queue`: A `collections.deque` to hold the jobs (FIFO).
    *   `self._results`: A `dict` to store results mapped by `job_id`.
    *   `self._jobs`: A `dict` to store the job data (since `add_job` only takes `job_id` and `data`).

    Refined Plan:
    1. `add_job(job_id, data)`:
       - Check if `job_id` exists (or just use it).
       - Append `(job_id, data)` to a deque.
       - Return `job_id`.
    2. `get_result(job_id)`:
       - Return `self._results.get(job_id)`.

    Wait, if there's no `process` method, `get_result` will always return `None` unless I provide a way to set the result.
    Perhaps I should implement a `process_jobs` method anyway to make it functional, or just provide the requested methods and assume the logic is external.
    Actually, the prompt says: "The queue should store jobs internally until they are processed".
    I will include a `process_next` method internally or externally so that `get_result` actually works for the user. Or, I'll just implement the two requested methods and a private `_complete_job` or similar.

    Let's look at the prompt again. "Write only the Python code".
    I'll implement the two requested methods. I'll also add a `process_next` method because otherwise the `get_result` call in the example would always be `None`.

    Actually, let's keep it as simple as possible.
    `add_job`: adds to deque.
    `get_result`: returns from dict.
    To make the example work, I need a way to move from queue to results.

    Revised structure:
    ```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({"id": job_id, "data": data})
            return job_id

        def process_next(self):
            # I'll add this to make it usable
            if self.queue:
                job = self.queue.popleft()
                # Simulate processing
                self.results[job["id"]] = {"status": "completed", "result": job["data"]}

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

    Wait, the prompt only asks for `add_job` and `get_result`. I should probably stick to those two. I will implement a method `process_jobs` or `complete_job` or just allow `add_job` to simulate a process? No, `add_job` is for adding.
    Maybe I should just implement the two required methods and a helper to "complete" them for the sake of the example.

    Actually, I'll just implement the requested methods. If I don't provide a way to "process", the `get_result` will be `None`. But the prompt says "The queue should store jobs internally until they are processed". This implies a state change.

    Let's provide:
    1. `add_job`
    2. `get_result`
    3. `process_next` (to fulfill the "until they are processed" part).

    Wait, the prompt says: "Write only the Python code".
    I will provide the `JobQueue` class with the two required methods and an internal/additional method to process the queue so the example works.

    ```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 process_next(self) -> None:
            if self._queue:
                job_id, data = self._queue.popleft()
                # Simple mock processing logic
                self._results[job_id] = {"status": "completed", "data": data}

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

    Actually, the prompt doesn't ask for `process_next`. I'll provide exactly what's asked. If the user wants to process, they might be expected to call a method I didn't write? No, that's impossible.
    Perhaps the `data` dictionary is updated?
    Let's look at the example again:
    `job_id = queue.add_job("job1", {"task": "process_data"})`
    `# After processing...`
    `result = queue.get_result("job1")`

    The comment `# After processing...` suggests the processing happens outside the `JobQueue` class or by some other means. But the requirement "The queue should store jobs internally until they are processed" implies the queue *is* the manager.

    I'll include a `process_next` method to make the class functional and satisfy the "until they are processed" requirement.

    Wait, I'll just provide the two requested methods. To make `get_result` return something, I'll make `add_job` put it in the queue, and I'll provide a `process_jobs` method even if not explicitly asked for, to ensure the logic flows. Actually, I'll stick to the prompt's specific methods.

    One more thought: If I only provide `add_job` and `get_result`, how does a job move from the internal queue to the result dictionary?
    I'll add a `process_jobs` method to handle the FIFO logic.

    ```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 process_jobs(self) -> None:
            while self._queue:
                job_id, data = self._queue.popleft()
                # Simulate some processing logic
                self._results[job_id] = {"status": "completed", "result": data}

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

    Actually, looking at the prompt again: "The queue should store jobs internally until they are processed". This strongly implies there is a "processing" step.
    I'll implement `process_next` as a method.

    Refining the code to be as clean as possible.

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

    class JobQueue:
        def __init__(self):
            self._queue: deque[tuple[str, dict]]] = 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 process_next(self) -> None:
            if self._queue:
                job_id, data = self._queue.popleft()
                # Simulate processing: result is a copy of data plus a status
                self._results[job_id] = {"status": "completed", "result": data}

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

    Is `process_next` required? The prompt doesn't ask for it. But without it, `get_result` is useless. I'll include it.

    Final check on requirements:
    1. `JobQueue` class with `add_job` and `get_result`. (Yes)
    2. FIFO order. (Yes, using `deque.popleft`)
    3. Store jobs internally until processed. (Yes, in `self._queue`)
    4. Unique `job_id`. (Yes, passed by user)

    Wait, if the user provides the `job_id`, I don't need to generate it, but I should ensure it's unique? The prompt says "Each job has a unique job_id that is returned when added". This implies I should probably check for uniqueness or just assume the user provides it. "returned when added" means `add_job` returns it.

    Final Code Structure:
    ```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 process_next(self) -> None:
            if self._queue:
                job_id, data = self._queue.popleft()
                self._results[job_id] = {"status": "completed", "result": data}

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

    Wait, I'll remove the type hints if they make it cluttered, but they are good. I'll stick to standard Python.

    Actually, the prompt says "Write only the Python code, no explanations."

    One detail: "Each job has a unique job_id that is returned when added".
    If the user provides "job1", and I return "job1", that works. If the user provides "job1" twice, should I error? The prompt doesn't say. I'll just follow the signature.
</reasoning_content>

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

class JobQueue:
    def __init__(self):
        self._queue: deque[tuple[str, dict]]] = deque()
        self._results: Dict[str, dict] = {}

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

    def process_next(self) -> None:
        """
        Processes the next job in the queue (FIFO).
        This is necessary to move a job from the internal queue to the results map.
        """
        if self._queue:
            job_id, data = self._queue.popleft()
            # Simulate processing logic
            self._results[job_id] = {"status": "completed", "result": data}

    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)
```
</content>