import logging
from typing import List, Dict, Any

# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')


class ReasoningChain:
    """
    A class to represent a chain of reasoning steps.
    """

    def __init__(self):
        """
        Initializes an empty reasoning chain.
        """
        self.chain: List[Dict[str, str]] = []

    def add_step(self, step: str, justification: str):
        """
        Adds a reasoning step to the chain.

        Args:
            step (str): The reasoning step.
            justification (str): The justification for the step.
        """
        if not isinstance(step, str) or not isinstance(justification, str):
            logging.error("Step and justification must be strings.")
            raise TypeError("Step and justification must be strings.")

        self.chain.append({"step": step, "justification": justification})
        logging.info(f"Added step: {step} with justification: {justification}")

    def get_chain(self) -> List[Dict[str, str]]:
        """
        Returns the entire reasoning chain.

        Returns:
            List[Dict[str, str]]: A list of dictionaries, where each dictionary
            represents a step and its justification.
        """
        return self.chain

    def print_chain(self):
        """
        Prints the reasoning chain to the console.
        """
        for i, step in enumerate(self.chain):
            print(f"Step {i+1}: {step['step']}")
            print(f"Justification: {step['justification']}\n")


def build_reasoning_chain() -> ReasoningChain:
    """
    Builds a simple reasoning chain.

    Returns:
        ReasoningChain: A ReasoningChain object.
    """
    chain = ReasoningChain()
    try:
        chain.add_step("Initial observation: The sky is dark.", "It is night time.")
        chain.add_step("Inference: The sun has set.", "Dark sky indicates absence of sunlight.")
        chain.add_step("Conclusion: It's time to sleep.", "Generally, people sleep when the sun is down.")
    except TypeError as e:
        logging.error(f"Error building reasoning chain: {e}")
        return ReasoningChain()  # Return an empty chain in case of error.
    return chain


def process_data(data: Any) -> str:
    """
    Processes input data and returns a string representation.
    Demonstrates basic error handling.

    Args:
        data (Any): The data to process.

    Returns:
        str: A string representation of the data.
    """
    try:
        if data is None:
            raise ValueError("Input data cannot be None.")
        return str(data)
    except ValueError as e:
        logging.error(f"Error processing data: {e}")
        return "Error: Unable to process data."
    except Exception as e:
        logging.error(f"Unexpected error: {e}")
        return "Error: An unexpected error occurred."


if __name__ == "__main__":
    # Example usage:
    reasoning_chain = build_reasoning_chain()
    reasoning_chain.print_chain()

    data = 123
    processed_data = process_data(data)
    print(f"Processed data: {processed_data}")

    data = None
    processed_data = process_data(data)
    print(f"Processed data: {processed_data}")