from abc import ABC, abstractmethod
#from hiveos.models.chunk import Chunk
import threading
from hiveos.messaging.message_bus import MessageBus
from hiveos.runtime.states import AgentStatus

class AgentInterface(ABC):
    
    def __init__(self):
        self.message_bus = None  # Will be injected by zone
        self.zone = None
        
        self.status = AgentStatus.IDLE
        self._available = True
        self.execution_started = False
        self.ready_to_execute = False
        self.has_executed = False
        self.current_chunk = None
        self.chunk_obj = None
        self.chunk_progress = 0
        self.required_ticks = 0
        self.realtime_timing = None
    
    @abstractmethod
    def get_status(self):
        pass

    @abstractmethod
    def report_capabilities(self):
        pass
        
    def on_injection(self):
        """
        Optional hook called when the agent is injected into the system.
        Can be overridden by subclasses to perform setup.
        """
        pass

    def execute_chunk(self, chunk, payload=None):
        print(f"[Debug] Type of chunk: {type(chunk)} | Chunk: {chunk}")
        self.payload = payload or chunk.payload
        self.execution_started = True
        self.ready_to_execute = False

    def report_completion(self, chunk):
        self.has_executed = True
        self.status = AgentStatus.IDLE
        self.current_chunk = None
        self.chunk_progress = 0
        self.required_ticks = 0
        self.execution_started = False
        print(f"{self.agent_id} has completed chunk: {chunk.chunk_id}")

        chunk.mark_complete()

    @abstractmethod
    def health_check(self):
        pass

    @abstractmethod
    def enter_cooldown(self, reason: str = ""):
        pass

    @abstractmethod
    def is_available(self):
        pass

    def assign_chunk(self, chunk):
        #assign_chunk(chunk_id, self.agent_id)
        chunk.assign_to_agent(self.agent_id)
        self.status = AgentStatus.WORKING
        self._available = False
        self.current_chunk = chunk.chunk_id
        self.has_executed = False
        self.payload = chunk.payload
        self.chunk_progress = 0
        self.execution_started = False
        self.ready_to_execute = False
        self.chunk_ticks_completed = 0
        self.chunk_obj = chunk

        
        
        ttl_value = chunk.ttl
        timing_mode = chunk.timing

        if timing_mode in ["seconds", "ms"]:
            self.realtime_timing = {
                "seconds": ttl_value if timing_mode == "seconds" else 0,
                "ms": ttl_value if timing_mode == "ms" else 0,
            }
            self.required_ticks = None
        else:
            self.required_ticks = ttl_value or 3
            self.realtime_timing = None

    def tick(self):
        if self.status != AgentStatus.WORKING or not self.current_chunk:
            return

        # if not dependencies_satisfied(self.current_chunk):
        #     return

        if self.realtime_timing and not self.execution_started:
            self.execute_chunk(self.chunk_obj, payload=self.payload)
            self.execution_started = True
            delay = self.realtime_timing.get("seconds", 0) + self.realtime_timing.get("ms", 0)/1000
            threading.Timer(delay, self._complete_realtime_chunk).start()
            return

        if self.ready_to_execute and not self.execution_started:
            self.execute_chunk(self.chunk_obj, payload=self.payload)            
            return

        if self.execution_started and not self.has_executed:
            if self.required_ticks is not None:
                self.chunk_progress += 1
                if self.chunk_progress >= self.required_ticks:
                    self.report_completion(self.chunk_obj)

    def _complete_realtime_chunk(self):
        self.report_completion(self.chunk_obj)


    def get_summary(self) -> dict:
        return {
            "agent_id": getattr(self, 'agent_id', None),
            "name": getattr(self, 'name', None),
            "status": self.get_status(),
            "capabilities": self.report_capabilities(),
            "zone": getattr(self, 'zone', None),
            "current_chunk": getattr(self, 'current_chunk', None),
            "chunk_progress": getattr(self, 'chunk_progress', 0),
            "required_ticks": getattr(self, 'required_ticks', 'N/A'),
            "execution_started": getattr(self, 'execution_started', False),
            "realtime_timing": getattr(self, 'realtime_timing', None)
        }
        
    def publish(self, key, value):
        if self.message_bus is not None:
            self.message_bus.publish(key, value)

    def get_bus_value(self, key, default=None):
        if self.message_bus is not None:
            return self.message_bus.get(key, default)
        return default
