"""
Resource — Base class for all SDK module resources.

Provides: list, get, create, update, delete, bulk_create, export, count, iterate
"""

from typing import Optional, Dict, Any, List, Iterator

from .http import HttpClient


class PaginatedResponse:
    """Response from a list endpoint with pagination info."""

    def __init__(self, data: List[Dict], total_count: int, limit: int, offset: int):
        self.data = data
        self.total_count = total_count
        self.limit = limit
        self.offset = offset

    @property
    def has_more(self) -> bool:
        return self.offset + self.limit < self.total_count

    @property
    def page(self) -> int:
        return (self.offset // self.limit) + 1 if self.limit > 0 else 1

    @property
    def total_pages(self) -> int:
        if self.limit <= 0:
            return 1
        return (self.total_count + self.limit - 1) // self.limit

    def __len__(self) -> int:
        return len(self.data)

    def __iter__(self):
        return iter(self.data)

    def __getitem__(self, index):
        return self.data[index]

    def __repr__(self) -> str:
        return f"PaginatedResponse(count={len(self.data)}, total={self.total_count}, page={self.page}/{self.total_pages})"


class BulkResult:
    """Response from a bulk operation."""

    def __init__(self, data: List[Dict], created_count: int, total_submitted: int):
        self.data = data
        self.created_count = created_count
        self.total_submitted = total_submitted

    @property
    def success_rate(self) -> float:
        if self.total_submitted == 0:
            return 0.0
        return self.created_count / self.total_submitted

    def __repr__(self) -> str:
        return f"BulkResult(created={self.created_count}/{self.total_submitted})"


class Resource:
    """
    Generic resource client — provides CRUD + bulk + export operations.

    Usage:
        contacts = Resource(http_client, "crm", "contacts")
        contacts.list(limit=50)
        contacts.create({"name": "John"})
        contacts.get("uuid-123")
    """

    def __init__(self, http: HttpClient, module: str, resource: str):
        self._http = http
        self._module = module
        self._resource = resource
        self._base_path = f"/sdk/v1/{module}/{resource}"

    def list(
        self,
        limit: int = 50,
        offset: int = 0,
        order_by: str = "created_at",
        order: str = "desc",
        search: Optional[str] = None,
        **filters,
    ) -> PaginatedResponse:
        """List records with pagination and optional search."""
        params: Dict[str, Any] = {
            "limit": limit,
            "offset": offset,
            "order_by": order_by,
            "order": order,
        }
        if search:
            params["search"] = search
        params.update(filters)

        result = self._http.get(self._base_path, params=params)
        return PaginatedResponse(
            data=result.get("data", []),
            total_count=result.get("total_count", 0),
            limit=limit,
            offset=offset,
        )

    def get(self, record_id: str) -> Dict:
        """Get a single record by ID."""
        result = self._http.get(f"{self._base_path}/{record_id}")
        return result.get("data", {})

    def create(self, data: Dict) -> Dict:
        """Create a new record."""
        result = self._http.post(self._base_path, json=data)
        return result.get("data", {})

    def update(self, record_id: str, data: Dict) -> Dict:
        """Update an existing record."""
        result = self._http.put(f"{self._base_path}/{record_id}", json=data)
        return result.get("data", {})

    def delete(self, record_id: str) -> bool:
        """Delete a record."""
        result = self._http.delete(f"{self._base_path}/{record_id}")
        return result.get("deleted", False)

    def bulk_create(self, items: List[Dict]) -> BulkResult:
        """Create multiple records in one request (max 500)."""
        result = self._http.post(f"{self._base_path}/bulk", json={"items": items})
        return BulkResult(
            data=result.get("data", []),
            created_count=result.get("created_count", 0),
            total_submitted=result.get("total_submitted", len(items)),
        )

    def export(self, format: str = "json", limit: int = 10000) -> Any:
        """Export all data (JSON list or CSV string)."""
        result = self._http.get(
            f"{self._base_path}/export",
            params={"format": format, "limit": limit},
        )
        if format == "csv":
            return result  # Raw CSV text
        return result.get("data", [])

    def count(self) -> int:
        """Get total record count."""
        result = self._http.get(f"{self._base_path}/count")
        return result.get("count", 0)

    def iterate(
        self,
        batch_size: int = 100,
        order_by: str = "created_at",
        order: str = "asc",
        **filters,
    ) -> Iterator[Dict]:
        """
        Auto-paginate through all records.

        Usage:
            for contact in client.crm.contacts.iterate():
                print(contact["name"])
        """
        offset = 0
        while True:
            page = self.list(
                limit=batch_size,
                offset=offset,
                order_by=order_by,
                order=order,
                **filters,
            )
            for item in page.data:
                yield item
            if not page.has_more:
                break
            offset += batch_size

    def __repr__(self) -> str:
        return f"Resource({self._module}/{self._resource})"
