<reasoning_content>
*   Goal: Implement a basic job queue in Python.
    *   Class: `JobQueue`.
    *   Methods:
        *   `add_job(job_id: str, data: dict) -> str`: Add job, return `job_id`.
        *   `get_result(job_id: str) -> dict | None`: Get result of completed job.
    *   Processing: FIFO.
    *   Storage: Store jobs internally until processed.
    *   Constraint: Write *only* Python code, no explanations.

    *   A `collections.deque` is perfect for FIFO.
    *   A dictionary to store results: `{job_id: result}`.
    *   A way to handle the "processing" part. The prompt implies the jobs are *added* and then *processed*. However, the prompt doesn't explicitly define a `process_next_job()` method, but the example implies "After processing...". To make a functional example, I should probably include a way to process them or assume a background worker/manual trigger.
    *   Wait, looking at the requirements: "Each job has a unique job_id that is returned when added".
    *   Actually, the prompt says `add_job` returns the `job_id` passed in.
    *   If I want a working implementation that follows the logic of a queue, I need a way to move jobs from "pending" to "completed".
    *   Let's look at the `get_result` method: `get_result(job_id: str) -> dict | None`.

    *   Internal state:
        *   `self.queue`: `collections.deque` of tuples `(job_id, data)`.
        *   `self.results`: `dict` mapping `job_id` to result.
    *   `add_job`: Append `(job_id, data)` to `self.queue`.
    *   `process_next_job` (not explicitly requested, but necessary to demonstrate functionality): Pop from queue, "do work", put in `self.results`.
    *   *Self-correction*: The prompt says "The queue should store jobs internally until they are processed". It doesn't specify a `process` method, but for the example to work, there must be a mechanism. I'll add a `process_next_job` method so the user can actually use it, even though it wasn't explicitly in the signature list. Or, I can just implement the requested signatures.
    *   Actually, a "Job Queue" usually implies a worker. I'll include a `process_job` method to make it complete.

    *Refining the method requirements*:
    1. `add_job(job_id, data)`
    2. `get_result(job_id)`

    Wait, if I don't have a `process` method, how do the results get populated? I'll add a `process_next_job` method to allow the simulation of work.

    *   `collections.deque` for the queue.
    *   `dict` for results.

    ```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_next_job(self):
            if not self.queue:
                return None
            job_id, data = self.queue.popleft()
            # Mock processing
            result = {"status": "completed", "original_data": data}
            self.results[job_id] = result
            return result

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

    *   `add_job` returns `job_id`? Yes.
    *   FIFO? Yes (using `deque.popleft`).
    *   `get_result` returns `dict | None`? Yes.
    *   Code only? Yes.

    Wait, should I include a background thread? The prompt asks for a "basic job queue". Usually, that means the core data structures. I will provide the class with the requested methods and a `process_next_job` to make the example logic sound.

    *Self-Correction on `add_job` return value*: The prompt says `add_job` takes `job_id` and returns `job_id`. That's slightly redundant but I will follow it.

    Let's double check the `get_result` signature.
    `get_result(job_id: str) -> dict | None`.

    Final Code Structure:
    ```python
    from collections import deque
    from typing import Dict, Any, Optional

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

        def add_job(self, job_id: str, data: Dict[str, Any]) -> str:
            self._queue.append((job_id, data))
            return job_id

        def process_next_job(self):
            """Helper method to simulate job processing."""
            if not self._queue:
                return None
            job_id, data = self._queue.popleft()
            # Simulate processing logic
            result = {"status": "success", "processed_data": data}
            self._results[job_id] = result
            return result

        def get_result(self, job_id: str) -> Optional[Dict[str, Any]]:
            return self._results.get(job_id)
    ```

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

    I'll ensure `process_next_job` is included because otherwise `get_result` would always return `None`.

    Actually, looking at the prompt again:
    "The queue should store jobs internally until they are processed"
    "After processing..." (in example)
    It doesn't define a `process` method in the requirement list, but it's required for the class to be functional.

    Final polish of the code.

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

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

        def add_job(self, job_id: str, data: Dict[str, Any]) -> str:
            self._queue.append((job_id, data))
            return job_id

        def process_next_job(self) -> Optional[Dict[str, Any]]:
            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

        def get_result(self, job_id: str) -> Optional[Dict[str, Any]]:
            return self._results.get(job_id)

    if __name__ == "__main__":
        queue = JobQueue()
        job_id = queue.add_job("job1", {"task": "process_data"})
        queue.process_next_job()
        result = queue.get_result("job1")
        print(result)
    ```

    I will omit the `if __name__ == "__main__":` block to keep it strictly to the requested class if I want to be safe, or include it to show it works. I'll just provide the class.

    One detail: The requirement `add_job(job_id: str, data: dict) -> str` implies the user provides the ID.

    Let's check the imports. `deque` from `collections`. `Dict`, `Any`, `Optional` from `typing`.

    Final check of the prompt: "Write only the Python code, no explanations."

    One last thing: In a real system, `add_job` might generate a UUID, but here the user provides it. I'll stick to the signature provided.

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

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

        def add_job(self, job_id: str, data: Dict[str, Any]) -> str:
            self._queue.append((job_id, data))
            return job_id

        def process_next_job(self) -> Optional[Dict[str, Any]]:
            if not self._queue:
                return None
            job_id, data = self._queue.popleft()
            # Simulate processing: in a real scenario, this would involve worker logic
            result = {"status": "success", "processed": data}
            self._results[job_id] = result
            return result

        def get_result(self, job_id: str) -> Optional[Dict[str, Any]]:
            return self._results.get(job_id)
    ```

    Actually, I'll make `process_next_job` a method that simulates the processing logic mentioned in the prompt's example.

    Wait, the prompt says `get_result(job_id: str) -> dict | None`. In Python 3.10+, `dict | None` is valid. I'll use that to be modern.

    Final Code Plan:
    - `from collections import deque`
    - `class JobQueue`
    - `__init__` initializes `deque` and `dict`.
    - `add_job` appends to `deque`.
    - `process_next_job` (added to make the class usable/testable) pops and adds to `dict`.
    - `get_result` returns from `dict`.

    One small detail: "The queue should store jobs internally until they are processed".
    This implies a separation between the "Queue" (pending) and the "Results" (completed). My structure does this.

    Final Code generation.
</reasoning_content>

<content>
```python
from collections import deque
from typing import Any

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

    def add_job(self, job_id: str, data: dict[str, Any]) -> str:
        """Add a job to the queue, return job_id."""
        self._queue.append((job_id, data))
        return job_id

    def process_next_job(self) -> dict[str, Any] | None:
        """
        Processes the next job in the queue (FIFO).
        In a real-world scenario, this might be handled by a separate worker thread.
        """
        if not self._queue:
            return None
        
        job_id, data = self._queue.popleft()
        
        # Simulate processing logic
        result = {
            "job_id": job_id,
            "status": "completed",
            "processed_data": data
        }
        
        self._results[job_id] = result
        return result

    def get_result(self, job_id: str) -> dict[str, Any] | None:
        """Get the result of a completed job."""
        return self._results.get(job_id)

# Example usage
if __name__ == "__main__":
    queue = JobQueue()
    job_id = queue.add_job("job1", {"task": "process_data"})
    
    # Simulate the background worker processing the job
    queue.process_next_job()
    
    # Get the result
    result = queue.get_result("job1")
    print(result)
```
</content>