from typing import TypedDict, Dict, Union, BinaryIO, Optional
from io import IOBase
import re

# Content-addressed hash format: sha256:<64 hex chars> = 71 chars total
_CONTENT_HASH_REGEX = re.compile(r'^sha256:[a-f0-9]{64}$')

class Asset(TypedDict):
    hash: str  # sha256:<hex> — primary identifier
    name: str
    type: str
    size: int
    created_at: Optional[str]
    meta: Optional[Dict]
    ephemeral: Optional[bool]
    alreadyExists: Optional[bool]

class AssetFilter(TypedDict, total=False):
    type: str
    hash: str

class ResolveAssetOptions(TypedDict, total=False):
    as_buffer: bool

class UploadAssetOptions(TypedDict, total=False):
    type: str
    meta: Dict
    filename: str

class AssetPresignedUrl(TypedDict):
    url: str
    expiresIn: int

def validate_hash(hash: str) -> None:
    """Validate a content-addressed hash (sha256:<64hex>). Raises ValueError if invalid."""
    if not hash.startswith('sha256:') or len(hash) != 71:
        raise ValueError(f'Invalid asset hash: expected sha256:<64-hex-chars>, got "{hash}"')

def is_valid_hash(hash: str) -> bool:
    """Check if a string is a valid content-addressed hash."""
    return bool(_CONTENT_HASH_REGEX.match(hash))

# Type aliases
AssetUploadInput = Union[str, bytes, BinaryIO, IOBase]
AssetUploadResult = Asset
