"""Bulk operations with auto-polling and auto-pagination."""

from __future__ import annotations

from typing import Any, Callable

from ..client import HttpClient


class BulkJob:
    """Wrapper around a completed bulk job with its results attached."""

    def __init__(self, data: dict[str, Any], results: list[dict[str, Any]]):
        self._data = data
        self.results = results

    def __getattr__(self, name: str) -> Any:
        if name in self._data:
            return self._data[name]
        raise AttributeError(f"BulkJob has no attribute {name!r}")

    def __getitem__(self, key: str) -> Any:
        return self._data[key]

    def get(self, key: str, default: Any = None) -> Any:
        return self._data.get(key, default)

    @property
    def status(self) -> str:
        return self._data.get("status", "unknown")

    @property
    def total_records(self) -> int:
        return self._data.get("total_records", 0)

    @property
    def completed_records(self) -> int:
        return self._data.get("completed_records", 0)

    @property
    def failed_records(self) -> int:
        return self._data.get("failed_records", 0)


class BulkResource:
    def __init__(self, client: HttpClient):
        self._client = client

    def email_find(
        self,
        *,
        records: list[dict[str, Any]],
        mode: str = "fastest",
        providers: list[str] | None = None,
        webhook_url: str | None = None,
        on_progress: Callable[[dict], None] | None = None,
    ) -> BulkJob:
        return self._submit_and_poll(
            "/bulk/email/find", records, mode, providers, webhook_url, on_progress
        )

    def email_verify(
        self,
        *,
        records: list[dict[str, Any]],
        mode: str = "fastest",
        providers: list[str] | None = None,
        webhook_url: str | None = None,
        on_progress: Callable[[dict], None] | None = None,
    ) -> BulkJob:
        return self._submit_and_poll(
            "/bulk/email/verify", records, mode, providers, webhook_url, on_progress
        )

    def phone_find(
        self,
        *,
        records: list[dict[str, Any]],
        mode: str = "fastest",
        providers: list[str] | None = None,
        webhook_url: str | None = None,
        on_progress: Callable[[dict], None] | None = None,
    ) -> BulkJob:
        return self._submit_and_poll(
            "/bulk/phone/find", records, mode, providers, webhook_url, on_progress
        )

    def get(self, job_id: str) -> dict[str, Any]:
        return self._client.request("GET", f"/bulk/{job_id}")

    def get_results(
        self,
        job_id: str,
        *,
        limit: int = 100,
        offset: int = 0,
        status: str | None = None,
    ) -> dict[str, Any]:
        params: dict[str, Any] = {"limit": limit, "offset": offset}
        if status:
            params["status"] = status
        return self._client.request("GET", f"/bulk/{job_id}/results", params=params)

    def cancel(self, job_id: str) -> dict[str, Any]:
        return self._client.request("POST", f"/bulk/{job_id}/cancel")

    def list(
        self,
        *,
        status: str | None = None,
        limit: int = 20,
        offset: int = 0,
    ) -> dict[str, Any]:
        params: dict[str, Any] = {"limit": limit, "offset": offset}
        if status:
            params["status"] = status
        return self._client.request("GET", "/bulk", params=params)

    def _submit_and_poll(
        self,
        endpoint: str,
        records: list[dict[str, Any]],
        mode: str,
        providers: list[str] | None,
        webhook_url: str | None,
        on_progress: Callable[[dict], None] | None,
    ) -> BulkJob:
        body: dict[str, Any] = {
            "records": records,
            "options": {"mode": mode},
        }
        if providers:
            body["options"]["providers"] = providers
        if webhook_url:
            body["options"]["webhook_url"] = webhook_url

        task = self._client.request("POST", endpoint, json_body=body)
        job_id = task["id"]

        final = self._client.poll(f"/bulk/{job_id}", on_progress=on_progress)
        results = self._client.fetch_all_results(job_id)

        return BulkJob(final, results)
