import asyncio
import os
import json
from ..aiop2p import P2PNode
from ..grpc_lib import GRPCConnector
from ....core import federated_learning
from ..symbolic_reasoning import SymbolicReasoningModule
from ....core.federated_learning import FederatedLearningClient
from ..memory_manager import MemoryManager
from ..utils.logger import setup_logger

logger = setup_logger("AndroidIntegration")

class AndroidIntegration:
    """
    Android Integration Module for the vAIn AGI System.
    Allows Android devices to participate as mobile nodes in the P2P network.
    """
    def __init__(self, node_id: str, android_device_info: dict):
        self.node_id = node_id
        self.device_info = android_device_info
        self.p2p_node = None
        self.grpc_connector = None
        self.federated_client = None
        self.symbolic_reasoning = None
        self.memory_manager = None

    async def initialize(self):
        """
        Initializes the Android node for the vAIn system.
        """
        logger.info(f"Initializing Android node: {self.node_id}")
        
        # Initialize P2P node
        self.p2p_node = P2PNode(node_id=self.node_id)
        await self.p2p_node.connect()

        # Initialize gRPC for inter-node communication
        self.grpc_connector = GRPCConnector(node_id=self.node_id)
        await self.grpc_connector.initialize()

        # Initialize Memory Manager first as other components might need it
        self.memory_manager = MemoryManager(node_id=self.node_id)
        
        # Initialize Federated Learning Client with memory manager
        self.federated_client = FederatedLearningClient(self.node_id, self.device_info)
        
        # Initialize Symbolic Reasoning Module
        self.symbolic_reasoning = SymbolicReasoningModule(self.node_id)

        logger.info(f"Android node {self.node_id} initialized successfully.")

    async def join_network(self):
        """
        Connects the Android node to the vAIn P2P network.
        """
        logger.info(f"Joining P2P network for node: {self.node_id}")
        await self.p2p_node.join_network()
        logger.info(f"Node {self.node_id} joined the P2P network.")

    async def participate_in_federated_learning(self, local_data_path: str):
        """
        Participates in the federated learning process by training on local data.
        """
        logger.info(f"Node {self.node_id} starting federated learning.")
        try:
            # Load local data
            with open(local_data_path, "r") as file:
                local_data = json.load(file)

            # Train on local data and send updates
            updates = await self.federated_client.train(local_data)
            await self.federated_client.send_updates(updates)

            logger.info(f"Node {self.node_id} successfully contributed to federated learning.")
        except Exception as e:
            logger.error(f"Error during federated learning on node {self.node_id}: {e}")

    async def process_symbolic_reasoning(self, query: str):
        """
        Processes a symbolic reasoning query.
        """
        logger.info(f"Node {self.node_id} processing symbolic reasoning query: {query}")
        response = self.symbolic_reasoning.process_query(query)
        logger.info(f"Symbolic reasoning result: {response}")
        return response

    async def update_memory(self, key: str, value: str):
        """
        Updates the node's context-aware memory with enhanced logging.
        """
        logger.info(f"Updating memory for node {self.node_id}: {key} -> {value}")
        success = self.memory_manager.store(key, value)
        if success:
            logger.info(f"Successfully updated memory: {key}")
        else:
            logger.error(f"Failed to update memory: {key}")

    async def fetch_memory(self, key: str):
        """
        Retrieves information from the node's context-aware memory with enhanced logging.
        """
        logger.info(f"Fetching memory for node {self.node_id}: {key}")
        value = self.memory_manager.retrieve(key)
        if value is not None:
            logger.info(f"Successfully retrieved memory for key: {key}")
        else:
            logger.warning(f"No memory found for key: {key}")
        return value

    async def handle_communication(self):
        """
        Handles incoming and outgoing communication via gRPC.
        """
        logger.info(f"Starting communication handler for node {self.node_id}.")
        while True:
            try:
                message = await self.grpc_connector.receive_message()
                if message:
                    logger.info(f"Received message: {message}")
                    # Process message (example: federated learning task)
                    if message.get("type") == "federated_learning_task":
                        await self.participate_in_federated_learning(message.get("data_path"))
            except Exception as e:
                logger.error(f"Communication error on node {self.node_id}: {e}")
            await asyncio.sleep(1)

    async def shutdown(self):
        """
        Gracefully shuts down the Android node.
        """
        logger.info(f"Shutting down Android node: {self.node_id}")
        if self.p2p_node:
            await self.p2p_node.disconnect()
        if self.grpc_connector:
            await self.grpc_connector.shutdown()
        logger.info(f"Node {self.node_id} shut down successfully.")

async def main():
    """
    Main entry point for the Android node.
    """
    device_info = {
        "model": "Pixel 6",
        "os_version": "Android 12",
        "cpu_cores": 8,
        "ram": "8GB"
    }
    android_node = AndroidIntegration(node_id="android-12345", android_device_info=device_info)

    await android_node.initialize()
    await android_node.join_network()

    try:
        await asyncio.gather(
            android_node.handle_communication()
        )
    except KeyboardInterrupt:
        await android_node.shutdown()

if __name__ == "__main__":
    asyncio.run(main())
