import time
import asyncio
import traceback

class LoopTaskWatcher:
    def __init__(self, loop, interval=1.0, verbose=True):
        self.loop = loop
        self.interval = interval
        self.verbose = verbose
        self.task_meta = {}  # {task: start_time}

    async def run(self):
        while True:
            await asyncio.sleep(self.interval)
            await self.inspect_tasks()

    async def inspect_tasks(self):
        tasks = asyncio.all_tasks(self.loop)
        print(f"\n[Watcher] 🧵 Total tasks: {len(tasks)}")

        for task in tasks:
            if task not in self.task_meta:
                self.task_meta[task] = time.time()

            elapsed = time.time() - self.task_meta[task]
            status = self._get_task_status(task)

            print(f" - 🌀 Task: {repr(task)}")
            print(f"     ↪ Status : {status}")
            print(f"     ↪ Elapsed: {elapsed:.2f}s")

            if self.verbose:
                frames = task.get_stack(limit=3)
                if not frames:
                    print("     ↪ Stack: (empty, probably done or sleeping)")
                else:
                    for i, frame in enumerate(frames):
                        print("     ↪ Stack frame {}:\n{}".format(
                            i, "".join(traceback.format_stack(frame)[-3:])))
            print()

    def _get_task_status(self, task: asyncio.Task):
        if task.done():
            if task.cancelled():
                return "cancelled"
            elif task.exception():
                return f"error: {task.exception()}"
            else:
                return "done"
        elif task._fut_waiter is not None:
            # Private API, but helps detect if blocked on another Future
            return "waiting on future"
        else:
            return "running or pending"