"""Job API client.

Endpoints:
- POST /api/v1/jobs - Create job
- GET /api/v1/jobs - List jobs
- GET /api/v1/jobs/{id} - Get job info
- DELETE /api/v1/jobs/{id} - Cancel job
- GET /api/v1/jobs/{id}/stream - Stream job events (SSE)
- GET /api/v1/jobs/{id}/artifacts - List artifacts
- GET /api/v1/jobs/{id}/artifacts/{filename} - Download artifact
"""

from __future__ import annotations

from collections.abc import AsyncIterator
from typing import Any

from manta_client.api.client import MantaClient, get_client


class JobAPI:
    """Job API client."""

    def __init__(self, client: MantaClient | None = None):
        self.client = client or get_client()

    async def create_job(
        self,
        prompt: str,
        input_data: dict[str, Any] | None = None,
        workspace_id: int | None = None,
        skill_slugs: list[str] | None = None,
        conversation: str | None = None,
        model: str | None = None,
    ) -> dict[str, Any]:
        """Create a new async job.

        Args:
            prompt: Job prompt
            input_data: Additional input parameters
            workspace_id: Workspace ID (repos, cluster, kubeconfig)
            skill_slugs: Skill slugs for prompt injection
            conversation: Parent job ID for conversation continuation
            model: LLM model name

        Returns:
            JobInfo dict
        """
        data: dict[str, Any] = {"prompt": prompt}
        if input_data:
            data["input"] = input_data
        if workspace_id is not None:
            data["workspace_id"] = workspace_id
        if skill_slugs:
            data["skill_slugs"] = skill_slugs
        if conversation:
            data["conversation"] = conversation
        if model:
            data["model"] = model

        return await self.client.post("/api/v1/jobs", data=data)

    async def list_jobs(
        self,
        skip: int = 0,
        limit: int = 100,
        status: str | None = None,
        user_id: str | None = None,
        search: str | None = None,
        since: str | None = None,
        before: str | None = None,
    ) -> dict[str, Any]:
        """List jobs with optional filters.

        Args:
            skip: Number of jobs to skip (offset)
            limit: Maximum number of jobs to return
            status: Filter by status (pending/running/completed/failed/cancelled)
            user_id: Filter by user ID
            search: Search in title/prompt
            since: Jobs created after (ISO8601)
            before: Jobs created before (ISO8601)

        Returns:
            {items: list[JobBrief], total: int}
        """
        params: dict[str, Any] = {"skip": skip, "limit": limit}
        if status:
            params["status"] = status
        if user_id:
            params["user_id"] = user_id
        if search:
            params["search"] = search
        if since:
            params["since"] = since
        if before:
            params["before"] = before
        return await self.client.get("/api/v1/jobs", params=params)

    async def get_job(self, job_id: str) -> dict[str, Any]:
        """Get job by ID.

        Args:
            job_id: Job ID

        Returns:
            JobInfo dict
        """
        return await self.client.get(f"/api/v1/jobs/{job_id}")

    async def cancel_job(self, job_id: str) -> bool:
        """Cancel a running job.

        Args:
            job_id: Job ID

        Returns:
            True if successful
        """
        await self.client.delete(f"/api/v1/jobs/{job_id}")
        return True

    async def retry_job(self, job_id: str) -> dict[str, Any]:
        """Retry a failed or cancelled job.

        Args:
            job_id: Job ID to retry

        Returns:
            New JobInfo dict
        """
        return await self.client.post(f"/api/v1/jobs/{job_id}/retry")

    async def stream_job(self, job_id: str) -> AsyncIterator[dict[str, Any]]:
        """Stream job events via SSE.

        Args:
            job_id: Job ID

        Yields:
            Event data dicts
        """
        async for event in self.client.stream_sse(f"/api/v1/jobs/{job_id}/stream"):
            yield event

    async def list_artifacts(self, job_id: str) -> dict[str, Any]:
        """List all artifacts for a job.

        Args:
            job_id: Job ID

        Returns:
            {job_id: str, artifacts: list[ArtifactInfo], total: int}
        """
        return await self.client.get(f"/api/v1/jobs/{job_id}/artifacts")

    async def download_artifact(self, job_id: str, filename: str) -> bytes:
        """Download an artifact file.

        Args:
            job_id: Job ID
            filename: Artifact filename

        Returns:
            File content as bytes
        """
        return await self.client.download(f"/api/v1/jobs/{job_id}/artifacts/{filename}")

    async def download_session(self, job_id: str) -> bytes:
        """Download session JSONL file for a job.

        Args:
            job_id: Job ID

        Returns:
            Session JSONL content as bytes
        """
        return await self.client.download(f"/api/v1/jobs/{job_id}/session")


# Singleton API instance
_job_api: JobAPI | None = None


def get_job_api() -> JobAPI:
    """Get or create the global Job API instance."""
    global _job_api
    if _job_api is None:
        _job_api = JobAPI()
    return _job_api
