"""Abstract base for job sources (durable queue)."""

from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Any

from pycharter.worker.models import ClaimedJob, ValidationJob


class JobSource(ABC):
    """Abstract interface for a durable, claimable job queue."""

    @abstractmethod
    async def submit(self, job: ValidationJob) -> str:
        """Insert a job into the queue. Returns job id."""
        ...

    @abstractmethod
    async def claim_next(self, worker_id: str) -> ClaimedJob | None:
        """Atomically claim the next eligible job. Returns None if queue empty."""
        ...

    @abstractmethod
    async def complete(
        self, event_id: str, result: dict[str, Any] | None = None
    ) -> None:
        """Mark a claimed job as completed, optionally storing result."""
        ...

    @abstractmethod
    async def fail(
        self,
        event_id: str,
        error: str,
        *,
        retry: bool = True,
    ) -> None:
        """Mark as failed; re-queue if retry and attempt < max_attempts."""
        ...

    @abstractmethod
    async def health_check(self) -> bool:
        """Return True if the backend is reachable."""
        ...

    async def get_job(self, job_id: str) -> dict[str, Any]:
        """Return job status/result for API. Default returns None."""
        return None

    async def list_jobs(
        self,
        status: str | None = None,
        limit: int | None = None,
        offset: int = 0,
    ) -> list[dict[str, Any]]:
        """List jobs for API. Default returns []."""
        return []

    async def cancel_job(self, job_id: str) -> bool:
        """Cancel a pending/claimed job. Default returns False."""
        return False

    async def delete_job(self, job_id: str) -> bool:
        """Delete a job. Default returns False."""
        return False

    async def get_stats(self) -> dict[str, int]:
        """Return counts by status. Default returns {}."""
        return {}

    async def pending_count(self) -> int:
        return -1

    async def close(self) -> None:
        pass
