""" Base class for POD provider integrations. """ from abc import ABC, abstractmethod from pathlib import Path from typing import Optional, Any from dataclasses import dataclass @dataclass class ProductResult: """Result of a product creation/update operation.""" success: bool product_id: Optional[str] = None error: Optional[str] = None data: Optional[dict] = None @dataclass class MockupResult: """Result of a mockup generation operation.""" success: bool image_url: Optional[str] = None local_path: Optional[Path] = None error: Optional[str] = None class PODProvider(ABC): """Abstract base class for print-on-demand providers.""" name: str = "base" def __init__(self, api_key: str, sandbox: bool = False) -> None: self.api_key = api_key self.sandbox = sandbox self._validate_credentials() @abstractmethod def _validate_credentials(self) -> None: """Validate API credentials.""" pass @abstractmethod async def create_product( self, design_path: Path, metadata: dict, product_config: dict, ) -> ProductResult: """ Create a new product on the POD service. Args: design_path: Path to the design file (PNG) metadata: Design metadata from metadata.yaml product_config: Product configuration from products.yaml Returns: ProductResult with product_id if successful """ pass @abstractmethod async def update_product( self, product_id: str, design_path: Path, metadata: dict, ) -> ProductResult: """ Update an existing product. Args: product_id: Provider's product ID design_path: Path to updated design file metadata: Updated metadata Returns: ProductResult indicating success/failure """ pass @abstractmethod async def generate_mockup( self, product_id: str, variant: Optional[str] = None, ) -> MockupResult: """ Generate a product mockup. Args: product_id: Provider's product ID variant: Optional variant (color, size) for mockup Returns: MockupResult with image URL or local path """ pass @abstractmethod async def get_product(self, product_id: str) -> Optional[dict]: """ Get product details from the provider. Args: product_id: Provider's product ID Returns: Product data dict or None if not found """ pass @abstractmethod async def list_products(self, limit: int = 100) -> list[dict]: """ List products from the provider. Args: limit: Maximum number of products to return Returns: List of product data dicts """ pass @abstractmethod async def get_catalog(self, product_type: Optional[str] = None) -> list[dict]: """ Get available products from provider catalog. Args: product_type: Optional filter by type (sticker, tshirt, etc) Returns: List of catalog items """ pass @abstractmethod async def upload_file(self, file_path: Path) -> Optional[str]: """ Upload a file to the provider. Args: file_path: Local path to file Returns: File URL or ID from provider, or None on failure """ pass