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

class JobQueue:
    """
    A basic in-memory job queue implementation.
    """
    def __init__(self):
        # Queue of jobs waiting to be processed (FIFO)
        # Stores tuples: (job_id, data)
        self._pending_jobs: deque[tuple[str, Dict[str, Any]]] = deque()
        
        # Storage for results of completed jobs: {job_id: result_data}
        self._results: Dict[str, Dict[str, Any]] = {}
        
        # Status tracking: {job_id: 'pending' | 'completed'}
        self._job_status: Dict[str, str] = {}

    def add_job(self, job_id: str, data: Dict[str, Any]) -> str:
        """
        Adds a job to the queue.

        Args:
            job_id: Unique identifier for the job.
            data: The data payload for the job.

        Returns:
            The job_id.
        """
        if job_id in self._job_status:
            raise ValueError(f"Job ID {job_id} already exists.")
            
        self._pending_jobs.append((job_id, data))
        self._job_status[job_id] = 'pending'
        return job_id

    def get_result(self, job_id: str) -> Optional[Dict[str, Any]]:
        """
        Retrieves the result of a completed job.

        Args:
            job_id: The ID of the job.

        Returns:
            The result dictionary, or None if the job is not found or not completed.
        """
        if job_id not in self._job_status or self._job_status[job_id] != 'completed':
            return None
        return self._results.get(job_id)

    def process_next_job(self) -> Optional[tuple[str, Dict[str, Any]]]:
        """
        Simulates a worker taking the next job from the FIFO queue.

        Returns:
            The (job_id, data) tuple if a job is available, otherwise None.
        """
        if not self._pending_jobs:
            return None
        
        return self._pending_jobs.popleft()

    def complete_job(self, job_id: str, result: Dict[str, Any]):
        """
        Simulates a worker finishing a job and storing the result.

        Args:
            job_id: The ID of the completed job.
            result: The output data of the job.
        """
        if job_id not in self._job_status or self._job_status[job_id] != 'pending':
            raise ValueError(f"Job ID {job_id} is not currently pending or does not exist.")
        
        self._results[job_id] = result
        self._job_status[job_id] = 'completed'


# Example Usage Demonstration:
if __name__ == '__main__':
    queue = JobQueue()

    # 1. Add jobs
    job_id_1 = queue.add_job("job1", {"task": "process_data", "input": 10})
    job_id_2 = queue.add_job("job2", {"task": "send_email", "recipient": "test@example.com"})
    job_id_3 = queue.add_job("job3", {"task": "cleanup", "files": 5})

    print(f"Added job 1: {job_id_1}")
    print(f"Added job 2: {job_id_2}")
    print(f"Added job 3: {job_id_3}")
    
    print("\n--- Worker Processing Simulation ---")

    # 2. Simulate worker processing job 1
    job = queue.process_next_job()
    if job:
        jid, data = job
        print(f"Processing {jid}: {data['task']}...")
        
        # Simulate work and generate result
        if data['task'] == "process_data":
            result = {"status": "success", "processed_value": data['input'] * 2}
            queue.complete_job(jid, result)
            print(f"Job {jid} completed.")

    # 3. Simulate worker processing job 2
    job = queue.process_next_job()
    if job:
        jid, data = job
        print(f"Processing {jid}: {data['task']}...")
        
        # Simulate work and generate result
        if data['task'] == "send_email":
            result = {"status": "success", "sent_to": data['recipient']}
            queue.complete_job(jid, result)
            print(f"Job {jid} completed.")

    # 4. Simulate worker processing job 3
    job = queue.process_next_job()
    if job:
        jid, data = job
        print(f"Processing {jid}: {data['task']}...")
        
        # Simulate work and generate result
        if data['task'] == "cleanup":
            result = {"status": "success", "files_cleaned": data['files']}
            queue.complete_job(jid, result)
            print(f"Job {jid} completed.")


    print("\n--- Checking Results ---")
    
    # 5. Get results
    result_1 = queue.get_result(job_id_1)
    result_2 = queue.get_result(job_id_2)
    result_3 = queue.get_result(job_id_3)
    
    print(f"Result for {job_id_1}: {result_1}")
    print(f"Result for {job_id_2}: {result_2}")
    print(f"Result for {job_id_3}: {result_3}")

    # Check a job that hasn't been added/completed
    result_4 = queue.get_result("job4")
    print(f"Result for job4: {result_4}")
```