from abc import ABC, abstractmethod
from hiveos.models.chunk import Chunk

class AgentInterface(ABC):
    @abstractmethod
    def get_status(self):
        pass

    @abstractmethod
    def report_capabilities(self):
        pass

    # Was abstract, now used to interface more cleanly with the core allowing overrides downstream
    def execute_chunk(self, chunk_id, payload=None):
        #self.status = 'working'
        #self._available = False
        #self.chunk_progress = 0
        #self.current_chunk = chunk_id
        #self.required_ticks = Chunk.get_ttl(chunk_id) or 3
        
        self.payload = payload or self.get_payload(chunk_id)

    # Was abstract at some point, now flips the flag for has_executed
    def report_completion(self, chunk_id):
        #self.chunk_started = False
        self.has_executed = True
        self.status = 'idle'
        self.current_chunk = None
        self.chunk_progress = 0
        self.required_ticks = 0
        Chunk.complete(chunk_id)

        from hiveos.models.task import Task
        task_id = Chunk.get_task_id(chunk_id)
        Task.check_and_mark_complete(task_id)

    @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_id):
        from hiveos.models.chunk import Chunk
        Chunk.assign(chunk_id, self.agent_id)
        self.status = 'working'
        self._available = False
        self.current_chunk = chunk_id
        self.has_executed = False
        #self.chunk_started = False
        self.payload = self.get_payload(self.current_chunk)
        self.chunk_progress = 0
        self.required_ticks = Chunk.get_ttl(chunk_id) or 3
        self.execution_started = False
        print(f"[ASSIGN] {self.agent_id} -> {chunk_id}, resetting ticks")
        self.chunk_ticks_completed = 0

        
    def tick(self):
        
        if self.current_chunk:
            chunk = Chunk.get_by_id(self.current_chunk)
            if chunk and chunk.get("depends_on"):
                dependency = Chunk.get_by_id(chunk["depends_on"])
                dependency_status = dependency["status"] if dependency else "MISSING"
                print(f"[GATE DEBUG] {self.agent_id} holding {chunk['chunk_id']} (depends on {chunk['depends_on']}) → status: {dependency_status}")


        
        if self.status != "working" or not self.current_chunk:
            return

        """
        if not self.chunk_started:
            # Always init on first tick after assignment
            #self.payload = self.get_payload(self.current_chunk)
            #self.required_ticks = Chunk.get_ttl(self.current_chunk) or 3  # fallback for legacy
            #self.chunk_progress = 0
            self.chunk_started = True
        """

        # Gating check comes AFTER init
        if not Chunk.dependencies_satisfied(self.current_chunk):
            print(f"[EXEC GATED] Agent {self.agent_id} is holding chunk {self.current_chunk} — waiting on dependency")
            return

        # Gate lifted — trigger first execution setup
        if not self.execution_started:
            print(f"[EXEC START] Agent {self.agent_id} starting execution of {self.current_chunk}")
            self.execute_chunk(self.current_chunk, payload=self.payload)
            self.execution_started = True

        # Tick the chunk
        self.chunk_progress += 1
        if self.chunk_progress >= self.required_ticks:
            self.report_completion(self.current_chunk)
        
        
        """
        if getattr(self, "status", None) == "working" and self.current_chunk and not getattr(self, "has_executed", False):
            if Chunk.dependencies_satisfied(self.current_chunk):
                print(f"[EXEC RUN] Agent {self.agent_id} executing chunk {self.current_chunk}")
                if not self.is_chunk_started():                  
                    payload = self.get_payload(self.current_chunk)
                    self.execute_chunk(self.current_chunk, payload=payload)   
                    self.chunk_started = True
            else:
                print(f"[EXEC GATED] Agent {self.agent_id} is holding chunk {self.current_chunk} — waiting on dependency")
        """

    def get_summary(self) -> dict:
        return {
            "agent_id": getattr(self, 'agent_id', None),
            "status": self.get_status(),
            "capabilities": self.report_capabilities()
        }
        
    def get_payload(self, chunk_id):
        chunk = Chunk.get_by_id(chunk_id)
        if chunk and "payload" in chunk and chunk["payload"]:
            return chunk["payload"]
        return f"Chunk {chunk_id} output"