#!/usr/bin/env python3
# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
"""Task routing and claiming operations for background workers."""
from __future__ import annotations

from pulse.core.brain_utils import atomic_update_json, TASK_BOARD_FILE, now_iso as _now_iso
from pulse.tasks.task_ops import tier_matches as _tier_matches
from pulse.tasks.dispatcher_lifecycle import DAEMON_AGENTS


def claim_task_atomic(worker_id: str, tier: str) -> dict | None:
    """Atomically claim a matching task from the task board."""
    if worker_id in DAEMON_AGENTS or worker_id.endswith("_daemon"):
        return None  # Daemons NEVER claim tasks
    claimed = [None]

    def _claim(board):
        if not isinstance(board, dict):
            return board
        for allow_fallback in (False, True):
            for d in board.get("dispatches", []):
                for t in d.get("tasks", []):
                    st = t.get("status")
                    if st not in ("open", "escalated"):
                        continue
                    if st == "escalated" and t.get("escalate_to") != tier:
                        continue
                    el = t.get("eligible_agents")
                    if el and worker_id not in el:
                        continue
                    match, fb = _tier_matches(t, tier)
                    if ((not allow_fallback and ((match and not fb) or st == "escalated")) or (allow_fallback and match and fb)):
                        t.update(status="active", claimed_by=worker_id, claimed_at=_now_iso())
                        claimed[0] = dict(t)
                        return board
        return board

    atomic_update_json(TASK_BOARD_FILE, _claim, default={"dispatches": []})
    return claimed[0]
