<reasoning_content>
Thinking Process:

1.  **Analyze the Request:**
    *   Goal: Implement a basic job queue in Python.
    *   Class: `JobQueue`
    *   Methods:
        *   `add_job(job_id: str, data: dict) -> str`
        *   `get_result(job_id: str) -> dict | None`
    *   Constraints:
        *   FIFO order.
        *   Store jobs internally until processed.
        *   Unique `job_id`.
    *   Output: Only Python code, no explanations.

2.  **Design the `JobQueue` Class:**
    *   Need a data structure to store jobs. A `deque` or `list` is suitable for FIFO.
    *   Need a data structure to store results of processed jobs for retrieval via `get_result`. A dictionary mapping `job_id` to `result` is suitable.
    *   Need a mechanism to simulate processing. Since the prompt implies a basic implementation without external threading or async loops explicitly requested, I should probably include a method to process jobs or assume the processing happens.
    *   Wait, the requirements say:
        1.  `add_job`
        2.  `get_result`
        3.  FIFO processing.
        4.  Store jobs until processed.
    *   The example usage shows: `add_job` -> "After processing..." -> `get_result`.
    *   To make this functional, I need a way to trigger processing. Usually, a job queue needs a worker or a method to process the queue. Since no `process()` method is specified in the requirements list, I should probably add one or simulate the processing logic inside the class to make `get_result` return something meaningful.
    *   However, strictly following the requirements:
        *   `add_job` adds to queue.
        *   `get_result` retrieves.
        *   Jobs are stored until processed.
    *   If I don't have a `process` method, how do jobs get processed? The example says "After processing...".
    *   I should probably add a `process()` method or `process_next()` method to simulate the worker consuming jobs from the queue and storing the result. Or I can implement a simple simulation where processing happens immediately upon addition (unlikely for a queue) or via a loop.
    *   Let's look at the constraints again. "The queue should store jobs internally until they are processed". This implies a separation between adding and processing.
    *   To make the code complete and runnable based on the example, I need a way to move jobs from the "waiting" state to the "completed" state.
    *   I will add a `process()` method (or similar) to handle the FIFO consumption. Even though it's not explicitly listed in requirement #1, it's necessary for the queue to function as described (storing until processed). Without it, `get_result` will always be None unless I assume `add_job` triggers processing. Given "Queue", usually implies batch processing.
    *   Actually, looking at the prompt "Implement a basic job queue... Requirements: 1. Create a `JobQueue` class with the following methods...". It lists specific methods. It doesn't explicitly forbid others, but I should focus on the required ones.
    *   To make `get_result` return data, I need to simulate a job processor. I'll define a simple default processor (e.g., just returning the data or a status) or allow a callback.
    *   Simpler approach: Add a `process_all()` method to consume the queue and store results. This makes the example usage valid.
    *   Let's refine the internal state:
        *   `self.queue`: List/Deque for pending jobs `(job_id, data)`.
        *   `self.results`: Dict mapping `job_id` to `result`.
        *   `self.processed`: Set to track processed jobs? Or just check `self.results`.

    *   Wait, the prompt asks for specific methods. If I add `process`, is that okay? Yes, usually "basic job queue" implies the mechanism to move items.
    *   Let's check the example usage again:
        ```python
        job_id = queue.add_job("job1", {"task": "process_data"})
        # After processing...
        result = queue.get_result("job1")
        ```
    *   This implies I need a way to trigger the processing. I will add a `process()` method to handle the FIFO logic.

3.  **Drafting the Code:**

    ```python
    from collections import deque
    import uuid

    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(self):
            # Process all pending jobs in FIFO order
            while self._queue:
                job_id, data = self._queue.popleft()
                # Simulate job processing
                self._results[job_id] = {"status": "completed", "data": data}

        def get_result(self, job_id: str) -> dict | None:
            return self._results.get(job_id)
    ```
    *   Wait, the `add_job` returns `job_id`. The signature says `-> str`.
    *   The prompt requires `get_result` to return `dict | None`.
    *   I need to make sure the code is robust.
    *   One detail: `add_job` takes `job_id` as an argument in the signature `add_job(job_id: str, data: dict) -> str`. Usually, a queue generates the ID. But here the caller provides it. I should respect that.
    *   Also, I need to ensure uniqueness if the caller provides it, or just trust them? The prompt says "Each job has a unique job_id that is returned when added". If the caller provides it, I should probably check for uniqueness or just use it. Given the example `job_id = queue.add_job("job1", ...)` suggests the ID is passed in.
    *   Wait, if I add `process`, is it required? The requirements list specific methods. If I only implement those two, how does `get_result` return anything? I'd have to assume the user calls a `process` method or the processing happens elsewhere.
    *   However, to make the example valid ("After processing..."), there must be a state transition. I will add a `process` method to complete the logic, as a queue without processing logic isn't fully functional.
    *   Alternative interpretation: Maybe the processing happens inside `add_job`? No, that defeats the queue concept.
    *   Maybe I should just store the job and assume a background worker? But for a code snippet, I need to show how it works.
    *   I will add a `process_all` method to simulate the worker consuming the queue.

    *   Refining requirements:
        *   `add_job(job_id: str, data: dict) -> str`
        *   `get_result(job_id: str) -> dict | None`
    *   I will add `process_all` to ensure the example makes sense.

    *   Wait, strict adherence: "Write only the Python code".
    *   I should ensure imports are included.
    *   I'll use `collections.deque` for efficiency.

    *   Let's check the type hint for `get_result`: `dict | None`. Python 3.10+ syntax.
    *   I should ensure the code is compatible.

    *   One more thing: The prompt example shows `job_id = queue.add_job("job1", {"task": "process_data"})`.
    *   The `add_job` signature in the prompt: `add_job(job_id: str, data: dict) -> str`.
    *   So the user provides the ID.
    *   I need to handle the case where a job is retrieved before processing.

    *   Revised plan:
        1.  Import `deque`.
        2.  Class `JobQueue`.
        3.  `__init__`: `self._pending`, `self._results`.
        4.  `add_job`: Append to `_pending`, return `job_id`.
        5.  `get_result`: Check `_results`.
        6.  `process`: Remove from `_pending`, compute result, store in `_results`. (I'll add this to make it functional based on the comment "After processing...").

    *   Wait, looking closely at requirement 1: "Create a `JobQueue` class with the following methods". It lists `add_job` and `get_result`. It doesn't explicitly forbid other methods. To make it a working "Job Queue" that fulfills "Jobs should be processed in FIFO order" and "store jobs internally until they are processed", a processing mechanism is implicit. I will add a `process` method.

    *   Wait, does the prompt imply I should *not* add methods? "Requirements: 1. Create a `JobQueue` class with the following methods...". Usually, this allows helper methods.
    *   Let's consider if `get_result` should trigger processing? No, that breaks FIFO if I'm fetching results.
    *   I will add a `process` method to consume the queue.

    *   Wait, I should check if I can infer processing from the example.
    *   `job_id = queue.add_job("job1", {"task": "process_data"})`
    *   `# After processing...`
    *   `result = queue.get_result("job1")`
    *   This implies there is a distinct processing step.
    *   I will implement a `process` method that handles the FIFO logic.

    *   Wait, looking at the constraint "Write only the Python code, no explanations."
    *   I will write the class.

    *   One subtle point: `job_id` uniqueness. If the user provides "job1" twice, should I overwrite or error? The requirement says "Each job has a unique job_id". If the user provides it, I should probably ensure uniqueness or just use it. I'll assume the user ensures uniqueness or I track it. I'll track it in a set to be safe, or just use it. Given the requirement "Each job has a unique job_id that is returned when added", if the user provides it, I return it. If they provide a duplicate, it might be ambiguous. I'll stick to the provided ID for simplicity but store pending jobs.

    *   Let's finalize the structure.

    ```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 process(self):
            # Process all jobs in FIFO order
            while self._queue:
                job_id, data = self._queue.popleft()
                # Simulate processing
                self._results[job_id] = {"status": "completed", "data": data}

        def get_result(self, job_id: str) -> Optional[dict]:
            return self._results.get(job_id)
    ```
    *   Wait, the type hint `dict | None` is Python 3.10+. `Optional[dict]` is compatible with older versions but `dict | None` is requested in the prompt description (`-> dict | None`). I should use `dict | None` if possible, but standard typing is safer for compatibility. However, the prompt explicitly wrote `-> dict | None`. I will use that syntax in the function signature to match the prompt exactly.
    *   Also, I need to make sure I don't add extra text.

    *   Wait, is `process` required? The prompt says "Create a `JobQueue` class with the following methods". It lists two. If I add `process`, is it okay? Yes, to make the queue functional. Without `process`, jobs are never processed, `get_result` is always None.
    *   However, maybe I should simulate processing inside `add_job`? No, FIFO means they wait.
    *   Maybe I should implement a `process_next` or similar.
    *   Let's stick to adding `process` to ensure the example works.

    *   Wait, I need to check if I should use `typing` imports. Standard Python 3.9+ allows `dict` and `list` as generic types in type hints (PEP 585). `dict | None` is PEP 604 (3.10+). I will use `dict | None` as requested in the text description.

    *   Final check on constraints:
        *   `add_job(job_id: str, data: dict) -> str`
        *   `get_result(job_id: str) -> dict | None`
        *   FIFO.
        *   Store until processed.
        *   Unique job_id returned.

    *   I will add `process` method to fulfill the "processed" requirement.

    *   Wait, one detail: `job_id` uniqueness. If I just store it, I need to ensure I don't overwrite results if the same ID is added again? The requirement says "unique job_id". I will assume valid input.

    *   Code structure:
        ```python
        from collections import deque

        class JobQueue:
            def __init__(self):
                self._pending = deque()
                self._results = {}

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

            def process(self):
                while self._pending:
                    job_id, data = self._pending.popleft()
                    self._results[job_id] = {"status": "success", "data": data}

            def get_result(self, job_id: str) -> dict | None:
                return self._results.get(job_id)
        ```
    *   I need to make sure I don't use `Optional` if the prompt asks for `dict | None`. I will use `dict | None`.
    *   I will remove the `process` method if I want to be strictly compliant with "with the following methods", but a job queue without a process method is static. The example shows "After processing...", implying the state changes. I'll include `process` to make it valid.
    *   Actually, to be safest with "Requirements: 1. ... with the following methods", I should prioritize those. But a method to trigger processing is logical. I'll include it.

    *   Wait, looking at the example:
        ```python
        job_id = queue.add_job("job1", {"task": "process_data"})
        # After processing...
        result = queue.get_result("job1")
        ```
        If I don't implement `process`, the user has to implement it externally. But the class should manage the queue logic. I'll add `process`.

    *   Wait, I'll check if I can infer processing logic. "Jobs should be processed in FIFO order".
    *   Okay, I will add a `process` method.

    *   One more check: The prompt example usage shows `job_id = queue.add_job("job1", ...)`. It passes the ID. The return type is `str`.
    *   The `get_result` returns `dict | None`.
    *   I'll make sure the code is clean.

    *   Wait, I should check if I need to import anything. `deque` is useful. `typing` might be needed for hints if I use them, but `dict | None` is built-in.
    *   I will use `from collections import deque`.

    *   Final check on "Write only the Python code". No markdown blocks? Usually, markdown blocks are expected for code. "Write only the Python code" usually means no conversational text, but code blocks are standard for code. I will wrap it in a markdown block. Or just raw text?
    *   Usually, "Write only the Python code" implies no markdown formatting like `**` or text before/after, but code blocks ```python ... ``` are standard for displaying code. I will output the code block.
    *   Actually, sometimes "Write only the Python code" means "Don't write markdown ticks". But standard practice is markdown ticks. I'll use markdown ticks to be safe and clear.
    *   Wait, if I look at similar tasks, usually ```python ... ``` is the norm. I will use it.

    *   Re-reading: "Write only the Python code, no explanations."
    *   I will output the code inside the block.

    *   Wait, I should check if `add_job` should return the ID passed or a generated one.
    *   Signature: `add_job(job_id: str, data: dict) -> str`.
    *   Example: `job_id = queue.add_job("job1", ...)`
    *   It implies I just pass it back.

    *   Okay, ready to write.

    *   Wait, one detail: `get_result` returns `dict | None`. The result of a job needs to be a dict.
    *   I will simulate a simple result.

    *   Wait, I'll check if I need to handle the case where `job_id` is not found in `get_result`. `None` is returned.
    *   I'll handle the case where `job_id` is not in `_results`.

    *   Okay, final plan:
        1. Import deque.
        2. Define JobQueue.
        3. Implement `__init__`.
        4. Implement `add_job`.
        5. Implement `process` (to enable the "processing" mentioned in the example).
        6. Implement `get_result`.

    *   Wait, if I add `process`, does it violate "with the following methods"? Usually, this means "at least". I'll include it to make the code functional.

    *   Wait, I'll remove `process` if I can make the example work without it? No, I can't. "After processing" implies an action.
    *   Okay, I will include `process`.

    *   Wait, I need to ensure I don't use `Optional` if I use `dict | None`.
    *   I'll write `-> dict | None`.

    *   One more thing: The prompt asks for `get_result(job_id: str) -> dict | None`.
    *   I will use that exact signature.

    *   Let's write the code.

</reasoning_content>

<content>
```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 process(self):
        while self._queue:
            job_id, data = self._queue.popleft()
            self._results[job_id] = {"status": "completed", "data": data}

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