from __future__ import annotations

from dataclasses import asdict
from typing import Any, Dict, Optional, TYPE_CHECKING

from ..types import CreateAssetParams, FilterSyncResult, ListAssetsParams, UpdateAssetParams, VerificationResult

if TYPE_CHECKING:
    from ..client import Optropic


class Assets:
    """Operations on digital assets."""

    def __init__(self, client: Optropic) -> None:
        self._client = client

    def create(self, params: CreateAssetParams) -> Dict[str, Any]:
        """Create a new asset and return it together with its cryptographic seal."""
        return self._client._request("POST", "/assets", json=asdict(params))

    def list(self, params: Optional[ListAssetsParams] = None) -> Dict[str, Any]:
        """List assets with optional filtering and pagination."""
        query = asdict(params) if params else None
        return self._client._request("GET", "/assets", params=query)

    def get(self, asset_id: str) -> Dict[str, Any]:
        """Retrieve a single asset by ID."""
        return self._client._request("GET", f"/assets/{asset_id}")

    def update(self, asset_id: str, params: UpdateAssetParams) -> Dict[str, Any]:
        """Update an existing asset."""
        return self._client._request("PATCH", f"/assets/{asset_id}", json=asdict(params))

    def revoke(self, asset_id: str, reason: str) -> Dict[str, Any]:
        """Revoke an asset, providing a reason for the revocation."""
        return self._client._request(
            "POST",
            f"/assets/{asset_id}/revoke",
            json={"reason": reason},
        )

    def verify(
        self,
        asset_id: str,
        *,
        local_filter: Optional[bytes] = None,
        filter_salts: Optional[Dict[str, bytes]] = None,
        public_key: Optional[bytes] = None,
        filter_policy: str = "permissive",
        trust_window_seconds: int = 259200,
    ) -> VerificationResult:
        """Verify an asset's cryptographic seal and revocation status.

        Supports both online (API call) and offline (local Cuckoo filter) verification.
        When a local_filter is provided, performs offline verification without network access.
        """
        if local_filter is not None:
            from ..filter_verify import verify_offline
            return verify_offline(
                asset_id,
                local_filter,
                filter_salts or {},
                public_key=public_key,
                filter_policy=filter_policy,
                trust_window_seconds=trust_window_seconds,
            )

        data = self._client._request("POST", f"/assets/{asset_id}/verify")
        return VerificationResult(
            signature_valid=data["signature_valid"],
            revocation_status=data["revocation_status"],
            filter_age_seconds=data["filter_age_seconds"],
            verified_at=data["verified_at"],
            verification_mode=data["verification_mode"],
        )

    def sync_filter(self) -> FilterSyncResult:
        """Download the latest revocation filter for offline use.

        Returns the signed binary filter and per-tenant salts.
        Call this periodically (e.g. every 6 hours) to keep the filter fresh.
        """
        from ..filter_verify import parse_header, parse_salts_header
        from datetime import datetime, timezone

        response = self._client._request_raw("GET", "/sync/revocation-filter")
        filter_bytes = response.content

        salts_header = response.headers.get("x-optropic-filter-salts", "")
        salt_header = response.headers.get("x-optropic-filter-salt", "")

        if salts_header:
            salts = parse_salts_header(salts_header)
        elif salt_header:
            salts = {"_self": bytes.fromhex(salt_header)}
        else:
            salts = {}

        header = parse_header(filter_bytes)

        return FilterSyncResult(
            filter=filter_bytes,
            salts=salts,
            issued_at=datetime.fromtimestamp(header["issued_at"], tz=timezone.utc),
            item_count=header["item_count"],
        )
