"""
Patcher for CrewAI.
Wraps: Agent.execute_task
"""

import time
import functools
import logging
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from ..emitter import NotiLensEmitter
    from ..loop_detector import LoopDetector

logger = logging.getLogger("notilens.crewai")

_patched = False


def patch(emitter: "NotiLensEmitter", loop_detector: "LoopDetector", timeout: float) -> bool:
    global _patched
    if _patched:
        return True
    try:
        from crewai import Agent

        _orig_execute = Agent.execute_task

        @functools.wraps(_orig_execute)
        def _execute_task(self, task, *args, **kwargs):
            agent_role = getattr(self, "role", "unknown")
            task_desc = getattr(task, "description", str(task))[:80]
            start = time.time()

            loop_msg = loop_detector.record()
            if loop_msg:
                emitter.send("task.loop", loop_msg, level="warning",
                             meta={"agent_role": agent_role, "source": "crewai"})

            emitter.send("ai.call.start", f"[{agent_role}] {task_desc}",
                         level="info", meta={"agent_role": agent_role, "task": task_desc, "source": "crewai"})
            try:
                result = _orig_execute(self, task, *args, **kwargs)
                duration = round(time.time() - start, 3)
                if duration > timeout:
                    emitter.send("task.timeout", f"[{agent_role}] task took {duration}s",
                                 level="warning", meta={"agent_role": agent_role, "duration": duration, "source": "crewai"})
                emitter.send("ai.call.complete", f"[{agent_role}] done in {duration}s",
                             level="info", meta={"agent_role": agent_role, "duration": duration, "source": "crewai"})
                return result
            except Exception as exc:
                emitter.send("task.error", f"[{agent_role}] error: {exc}",
                             level="error", meta={"agent_role": agent_role, "error": str(exc), "source": "crewai"})
                raise

        Agent.execute_task = _execute_task

        _patched = True
        logger.debug("NotiLens: CrewAI patched")
        return True

    except ImportError:
        return False
    except Exception as e:
        logger.warning("NotiLens: failed to patch CrewAI — %s", e)
        return False
