"""Async job polling with exponential backoff for Influ2 operations."""

from __future__ import annotations

import asyncio
import logging
import time

from influ2_mcp.client import Influ2ApiClient
from influ2_mcp.errors import Influ2JobTimeoutError

logger = logging.getLogger(__name__)


async def poll_job_until_complete(
    client: Influ2ApiClient,
    job_id: str,
    timeout_seconds: int = 120,
) -> dict:
    """Poll GET /public/v1/jobs/{job_id} until completion or timeout.

    Uses exponential backoff:
    - First 10 seconds: poll every 2 seconds
    - 10-30 seconds: poll every 5 seconds
    - 30+ seconds: poll every 10 seconds

    Returns the final job status dict on completion.
    Raises Influ2JobTimeoutError if the timeout is reached.
    """
    start = time.monotonic()
    last_status = "pending"

    while True:
        elapsed = time.monotonic() - start
        if elapsed >= timeout_seconds:
            raise Influ2JobTimeoutError(job_id=job_id, last_status=last_status)

        result = await client.get(f"/public/v1/jobs/{job_id}")
        last_status = result.get("status", "unknown")

        logger.info("Job %s status: %s (%.0fs elapsed)", job_id, last_status, elapsed)

        if last_status in ("completed", "done", "finished"):
            return result

        if last_status in ("failed", "error"):
            error_msg = result.get("error", result.get("message", "Unknown error"))
            return {
                **result,
                "_error": True,
                "_message": f"Job failed: {error_msg}",
            }

        # Exponential backoff
        if elapsed < 10:
            interval = 2.0
        elif elapsed < 30:
            interval = 5.0
        else:
            interval = 10.0

        # Don't sleep past the timeout
        remaining = timeout_seconds - (time.monotonic() - start)
        await asyncio.sleep(min(interval, max(remaining, 0.5)))
