"""
Prodigi API integration.

API Documentation: https://www.prodigi.com/print-api/docs/
"""

from pathlib import Path
from typing import Optional
import httpx

from .base import PODProvider, ProductResult, MockupResult


class ProdigiProvider(PODProvider):
    """Prodigi print-on-demand provider."""

    name = "prodigi"

    SANDBOX_URL = "https://api.sandbox.prodigi.com/v4.0"
    PRODUCTION_URL = "https://api.prodigi.com/v4.0"

    def __init__(self, api_key: str, sandbox: bool = False) -> None:
        super().__init__(api_key, sandbox)
        base_url = self.SANDBOX_URL if sandbox else self.PRODUCTION_URL
        self.client = httpx.AsyncClient(
            base_url=base_url,
            headers={
                "X-API-Key": api_key,
                "Content-Type": "application/json",
            },
            timeout=30.0,
        )

    def _validate_credentials(self) -> None:
        """Validate Prodigi API key."""
        if not self.api_key:
            raise ValueError("Prodigi API key is required")

    async def create_product(
        self,
        design_path: Path,
        metadata: dict,
        product_config: dict,
    ) -> ProductResult:
        """
        Create a product template on Prodigi.

        Note: Prodigi doesn't have a "product" concept like Printful.
        Instead, orders are placed directly with product SKUs and image URLs.
        This method creates a "template" in our system for tracking.
        """
        try:
            # Upload the design file
            file_url = await self.upload_file(design_path)
            if not file_url:
                return ProductResult(
                    success=False,
                    error="Failed to upload design file"
                )

            # Prodigi works on-demand, so we just validate the SKU exists
            sku = product_config.get("sku")

            # Validate SKU by checking catalog
            catalog = await self.get_catalog()
            valid_skus = [p.get("sku") for p in catalog]

            if sku and sku not in valid_skus:
                return ProductResult(
                    success=False,
                    error=f"Invalid SKU: {sku}"
                )

            # Return a "virtual" product ID for tracking
            product_id = f"prodigi_{metadata.get('slug')}_{sku}"

            return ProductResult(
                success=True,
                product_id=product_id,
                data={
                    "sku": sku,
                    "image_url": file_url,
                    "name": metadata.get("name"),
                    "retail_price": product_config.get("retail_price"),
                },
            )

        except Exception as e:
            return ProductResult(success=False, error=str(e))

    async def update_product(
        self,
        product_id: str,
        design_path: Path,
        metadata: dict,
    ) -> ProductResult:
        """Update product by re-uploading the design file."""
        try:
            file_url = await self.upload_file(design_path)
            if not file_url:
                return ProductResult(
                    success=False,
                    error="Failed to upload design file"
                )

            return ProductResult(
                success=True,
                product_id=product_id,
                data={"image_url": file_url},
            )

        except Exception as e:
            return ProductResult(success=False, error=str(e))

    async def generate_mockup(
        self,
        product_id: str,
        variant: Optional[str] = None,
    ) -> MockupResult:
        """
        Generate product mockup.

        Note: Prodigi doesn't have a built-in mockup generator.
        This would need to use a third-party service or custom solution.
        """
        return MockupResult(
            success=False,
            error="Prodigi does not provide mockup generation. Use external mockup service."
        )

    async def get_product(self, product_id: str) -> Optional[dict]:
        """
        Get product details.

        Since Prodigi doesn't store products, this returns None.
        Product data should be stored locally in metadata.yaml.
        """
        return None

    async def list_products(self, limit: int = 100) -> list[dict]:
        """
        List products.

        Since Prodigi doesn't store products, returns empty list.
        Use local design list instead.
        """
        return []

    async def get_catalog(self, product_type: Optional[str] = None) -> list[dict]:
        """Get Prodigi product catalog."""
        try:
            response = await self.client.get("/products")
            response.raise_for_status()
            data = response.json()

            products = data.get("products", [])

            if product_type:
                # Filter by type
                type_keywords = {
                    "sticker": ["sticker", "sti"],
                    "print": ["print", "poster", "art"],
                    "canvas": ["canvas"],
                }
                keywords = type_keywords.get(product_type, [product_type])
                products = [
                    p for p in products
                    if any(kw in p.get("sku", "").lower() or
                           kw in p.get("description", "").lower()
                           for kw in keywords)
                ]

            return products

        except Exception:
            return []

    async def upload_file(self, file_path: Path) -> Optional[str]:
        """
        Upload a file to Prodigi.

        Note: Prodigi expects image URLs, not uploaded files.
        You need to host the image somewhere accessible.

        Options:
        1. Use Cloudflare R2/S3
        2. Use a public URL from your server
        3. Use Prodigi's asset upload (if available)
        """
        # For now, return None - in production, implement actual upload
        # to your hosting service (R2, S3, etc.)
        return None

    async def create_order(
        self,
        sku: str,
        image_url: str,
        recipient: dict,
        quantity: int = 1,
    ) -> dict:
        """
        Create an order on Prodigi.

        Args:
            sku: Product SKU
            image_url: URL to the design image
            recipient: Shipping address dict
            quantity: Number of items

        Returns:
            Order data from Prodigi
        """
        try:
            payload = {
                "shippingMethod": "Standard",
                "recipient": recipient,
                "items": [
                    {
                        "sku": sku,
                        "copies": quantity,
                        "assets": [
                            {
                                "printArea": "default",
                                "url": image_url,
                            }
                        ],
                    }
                ],
            }

            response = await self.client.post("/orders", json=payload)
            response.raise_for_status()
            return response.json()

        except Exception as e:
            return {"error": str(e)}

    async def get_order(self, order_id: str) -> Optional[dict]:
        """Get order status from Prodigi."""
        try:
            response = await self.client.get(f"/orders/{order_id}")
            response.raise_for_status()
            return response.json()
        except Exception:
            return None

    async def get_quote(
        self,
        sku: str,
        destination_country: str = "US",
        quantity: int = 1,
    ) -> Optional[dict]:
        """Get a price quote for a product."""
        try:
            payload = {
                "shippingMethod": "Standard",
                "destinationCountryCode": destination_country,
                "items": [
                    {
                        "sku": sku,
                        "copies": quantity,
                    }
                ],
            }

            response = await self.client.post("/quotes", json=payload)
            response.raise_for_status()
            return response.json()

        except Exception:
            return None

    async def close(self) -> None:
        """Close the HTTP client."""
        await self.client.aclose()
