"""Requeue -- re-enqueue a failed/rejected task with lineage tracking.

Hard cap of MAX_REQUEUES per task lineage prevents infinite retry loops.
The requeue counter is inherited from the parent task via metadata.

Usage::

    new_item = requeue(queue, task, reason="Reviewer requested changes")
    if new_item is None:
        # Hit the cap -- escalate to human
        ...
"""

from __future__ import annotations

import logging
from typing import Optional

from cohort.pipeline.pipeline_task import PipelineTask
from cohort.work_queue import WorkItem, WorkQueue

logger = logging.getLogger(__name__)

MAX_REQUEUES = 3


def requeue(
    queue: WorkQueue,
    task: PipelineTask,
    reason: Optional[str] = None,
    priority_override: Optional[str] = None,
) -> Optional[WorkItem]:
    """Create a fresh queue entry from a failed or rejected task.

    Parameters
    ----------
    queue:
        The WorkQueue to enqueue into.
    task:
        The PipelineTask to requeue.
    reason:
        Human-readable reason for requeue (stored in new item's metadata).
    priority_override:
        Override priority for the new item.  Defaults to parent's priority.

    Returns
    -------
    WorkItem or None
        The new WorkItem, or None if the hard cap has been reached.
    """
    count = task.requeue_count
    if count >= MAX_REQUEUES:
        logger.warning(
            "[!] requeue cap reached for %s (count=%d, max=%d) -- escalate to human",
            task.item.id, count, MAX_REQUEUES,
        )
        return None

    new_meta = dict(task.item.metadata)
    new_meta["requeue_count"] = count + 1
    new_meta["requeued_from"] = task.item.id
    if reason:
        new_meta["requeue_reason"] = reason
    # Clear execution state from previous attempt
    for key in ("staleness_level", "staleness_report", "self_review_report",
                "changes_summary", "files_modified", "review_status"):
        new_meta.pop(key, None)

    new_item = queue.enqueue(
        description=task.item.description,
        requester=task.item.requester,
        priority=priority_override or task.item.priority,
        agent_id=task.item.agent_id,
        depends_on=task.item.depends_on,
        metadata=new_meta,
    )

    logger.info(
        "[requeue] %s -> %s (attempt %d/%d) reason=%r",
        task.item.id, new_item.id, count + 1, MAX_REQUEUES, reason,
    )
    return new_item
