class GateEvaluator:
    def __init__(self, zone_controller):
        self.zone = zone_controller  # Used to access chunk results, task state, etc.
        self.local_bus = zone_controller.local_bus

    
    # def should_assign(self, chunk):
        # """Returns True if the chunk's 'conditional' predicate is either absent or passes."""
        # conditional = getattr(chunk, "conditional", None)
        # if not conditional:
            # return True  # No predicate = assign as normal

        # return self._evaluate_conditional(conditional)
    
    def should_assign(self, chunk):
        cond = chunk.conditional
        if cond and isinstance(cond, dict) and cond.get("type"):
            
            dep_id = chunk.depends_on
            if dep_id:
                dep_chunk = self.zone.chunks.get(dep_id)
                if not dep_chunk or dep_chunk.status != "completed":
                    print(f"[GateEval] Waiting on dependency {dep_id} for chunk {chunk.chunk_id}. Skipping assignment.")
                    return False
                    
            result = self._evaluate_conditional(cond)
            if result is None:
                print(f"[GateEval] Conditional for chunk {chunk.chunk_id} could not yet be evaluated. Delaying assignment.")
                return False
                
            print(f"[GateEval] Conditional for chunk {chunk.chunk_id} evaluated: {result}")
            if result is False:
                print(f"[GateEval] Conditional failed for chunk {chunk.chunk_id}. Marking as stale.")
                chunk.mark_stale()
                self.mark_dependent_chunks_stale(chunk.chunk_id)
            return result
        return True


    def should_execute(self, chunk):
        """
        Determines if a chunk is ready to execute.
        - Always checks `depends_on`
        - Defers to should_assign() for any 'conditional' logic
        """
        # Gating based on chunk dependency
        if chunk.depends_on:
            parent_chunk = self.zone.get_chunk(chunk.depends_on)
            if not parent_chunk or parent_chunk.status != "completed":
                return False

        # Apply conditional branching gate only if present
        return self.should_assign(chunk)

    def _evaluate_conditional(self, conditional):
        """
        Evaluates a 'conditional' condition.
        Supported syntax:
            - type: gt / lt / eq
            - from: chunk_id
            - value: literal
            - fallback: true (special case)
        """
        # Handle fallback type
        if conditional.get("type") == "fallback":
            return self._should_trigger_fallback(conditional)

        key = conditional.get("key")
        comp_type = conditional.get("type")
        target_value = conditional.get("value")

        if not (key and comp_type):
            return False

        # Pull result from previous chunk
        value = self.local_bus.get(key)
        if value is None:
            return False  # Cannot evaluate yet

        # Now evaluate based on comparison type
        try:
            return self._compare(value, comp_type, target_value)
        except Exception as e:
            print(f"[GateEvaluator] Error evaluating condition: {e}")
            return False

    def _compare(self, actual, comp_type, target):
        if comp_type == "gt":
            return float(actual) > float(target)
        elif comp_type == "lt":
            return float(actual) < float(target)
        elif comp_type == "eq":
            return str(actual) == str(target)
        elif comp_type == "not":
            return str(actual) != str(target)
            
        return False

    def _should_trigger_fallback(self, conditional):
        """
        Optional fallback handler.
        Trigger this if all siblings with 'conditional' failed or are unreachable.
        For now, this should return False unless you build a parent context checker.
        """
        return False  # Placeholder for future fallback resolution logic

    def mark_dependent_chunks_stale(self, chunk_id):
        affected_chunks = [
            c for c in self.zone.chunks.values()
            if c.depends_on == chunk_id and c.status == "pending"
        ]
        for c in affected_chunks:
            print(f"[GateEval] Propagating stale mark to dependent chunk {c.chunk_id}")
            c.mark_stale()
            self.mark_dependent_chunks_stale(c.chunk_id)  # Recurse down the tree
