"""Catalog tools for Meta Marketing API.

This module provides tools for managing product catalogs, feeds, and sets
for dynamic ads and e-commerce campaigns.
"""

from __future__ import annotations

from typing import Any, Dict

from .errors import MetaApiError
from .logging import get_logger
from .meta_client import get_client
from .schemas import ToolResult

logger = get_logger(__name__)


async def create_catalog_handler(arguments: Dict[str, Any]) -> ToolResult:
    """Create a new product catalog.
    
    Args:
        arguments: {
            "business_id": "123",
            "name": "My Product Catalog",
            "vertical": "commerce"  # or "hotels", "flights", "destinations", "home_listings"
        }
        
    Returns:
        ToolResult with created catalog ID
    """
    try:
        client = get_client()
        business_id = arguments.get("business_id")
        
        if not business_id:
            return ToolResult(ok=False, error={"message": "business_id is required"})
        
        catalog_data = {
            "name": arguments.get("name"),
            "vertical": arguments.get("vertical", "commerce"),
        }
        
        response = await client.post(
            f"{business_id}/owned_product_catalogs",
            body=catalog_data
        )
        
        return ToolResult(ok=True, data=response)
    except MetaApiError as exc:
        logger.error("create_catalog_failed", **exc.to_dict())
        return ToolResult(ok=False, error=exc.to_dict())


async def get_catalog_handler(arguments: Dict[str, Any]) -> ToolResult:
    """Get details of a specific product catalog.
    
    Args:
        arguments: {"catalog_id": "123"}
        
    Returns:
        ToolResult with catalog details
    """
    try:
        client = get_client()
        catalog_id = arguments.get("catalog_id")
        
        if not catalog_id:
            return ToolResult(ok=False, error={"message": "catalog_id is required"})
        
        fields = [
            "id",
            "name",
            "vertical",
            "business",
            "product_count",
            "flight_catalog_settings",
            "hotel_catalog_settings",
        ]
        
        response = await client.get(
            catalog_id,
            params={"fields": ",".join(fields)}
        )
        
        return ToolResult(ok=True, data=response)
    except MetaApiError as exc:
        logger.error("get_catalog_failed", catalog_id=catalog_id, **exc.to_dict())
        return ToolResult(ok=False, error=exc.to_dict())


async def update_catalog_handler(arguments: Dict[str, Any]) -> ToolResult:
    """Update an existing product catalog.
    
    Args:
        arguments: {
            "catalog_id": "123",
            "name": "Updated Name"
        }
        
    Returns:
        ToolResult with success status
    """
    try:
        client = get_client()
        catalog_id = arguments.get("catalog_id")
        
        if not catalog_id:
            return ToolResult(ok=False, error={"message": "catalog_id is required"})
        
        update_data = {}
        
        if "name" in arguments:
            update_data["name"] = arguments["name"]
        
        response = await client.post(catalog_id, body=update_data)
        
        return ToolResult(ok=True, data=response)
    except MetaApiError as exc:
        logger.error("update_catalog_failed", catalog_id=catalog_id, **exc.to_dict())
        return ToolResult(ok=False, error=exc.to_dict())


async def delete_catalog_handler(arguments: Dict[str, Any]) -> ToolResult:
    """Delete a product catalog.
    
    Args:
        arguments: {"catalog_id": "123"}
        
    Returns:
        ToolResult with success status
    """
    try:
        client = get_client()
        catalog_id = arguments.get("catalog_id")
        
        if not catalog_id:
            return ToolResult(ok=False, error={"message": "catalog_id is required"})
        
        response = await client.delete(catalog_id)
        
        return ToolResult(ok=True, data=response)
    except MetaApiError as exc:
        logger.error("delete_catalog_failed", catalog_id=catalog_id, **exc.to_dict())
        return ToolResult(ok=False, error=exc.to_dict())


async def batch_upload_catalog_products_handler(arguments: Dict[str, Any]) -> ToolResult:
    """Batch upload products to a catalog.
    
    Args:
        arguments: {
            "catalog_id": "123",
            "products": [
                {
                    "id": "SKU123",
                    "title": "Product Name",
                    "description": "Product description",
                    "availability": "in stock",
                    "condition": "new",
                    "price": "19.99 USD",
                    "link": "https://...",
                    "image_link": "https://...",
                    "brand": "Brand Name"
                }
            ]
        }
        
    Returns:
        ToolResult with upload status
    """
    try:
        client = get_client()
        catalog_id = arguments.get("catalog_id")
        products = arguments.get("products", [])
        
        if not catalog_id:
            return ToolResult(ok=False, error={"message": "catalog_id is required"})
        
        if not products:
            return ToolResult(ok=False, error={"message": "products list is required"})
        
        # Batch upload using the batch API
        batch_data = {
            "requests": [
                {
                    "method": "POST",
                    "relative_url": f"{catalog_id}/products",
                    "body": product
                }
                for product in products
            ]
        }
        
        response = await client.post("", body=batch_data)
        
        return ToolResult(
            ok=True,
            data={
                "uploaded_count": len(products),
                "results": response,
            }
        )
    except MetaApiError as exc:
        logger.error("batch_upload_products_failed", catalog_id=catalog_id, **exc.to_dict())
        return ToolResult(ok=False, error=exc.to_dict())


async def update_catalog_products_handler(arguments: Dict[str, Any]) -> ToolResult:
    """Update products in a catalog.
    
    Args:
        arguments: {
            "catalog_id": "123",
            "product_id": "SKU123",
            "updates": {
                "price": "29.99 USD",
                "availability": "in stock"
            }
        }
        
    Returns:
        ToolResult with update status
    """
    try:
        client = get_client()
        catalog_id = arguments.get("catalog_id")
        product_id = arguments.get("product_id")
        updates = arguments.get("updates", {})
        
        if not catalog_id or not product_id:
            return ToolResult(ok=False, error={"message": "catalog_id and product_id are required"})
        
        response = await client.post(
            f"{catalog_id}/products",
            body={"id": product_id, **updates}
        )
        
        return ToolResult(ok=True, data=response)
    except MetaApiError as exc:
        logger.error("update_catalog_product_failed", **exc.to_dict())
        return ToolResult(ok=False, error=exc.to_dict())


async def delete_catalog_products_handler(arguments: Dict[str, Any]) -> ToolResult:
    """Delete products from a catalog.
    
    Args:
        arguments: {
            "catalog_id": "123",
            "product_ids": ["SKU123", "SKU456"]
        }
        
    Returns:
        ToolResult with deletion status
    """
    try:
        client = get_client()
        catalog_id = arguments.get("catalog_id")
        product_ids = arguments.get("product_ids", [])
        
        if not catalog_id or not product_ids:
            return ToolResult(ok=False, error={"message": "catalog_id and product_ids are required"})
        
        # Delete products using batch API
        response = await client.post(
            f"{catalog_id}/products_batch",
            body={"requests": [{"method": "DELETE", "data": {"id": pid}} for pid in product_ids]}
        )
        
        return ToolResult(
            ok=True,
            data={
                "deleted_count": len(product_ids),
                "response": response,
            }
        )
    except MetaApiError as exc:
        logger.error("delete_catalog_products_failed", **exc.to_dict())
        return ToolResult(ok=False, error=exc.to_dict())


async def create_catalog_feed_handler(arguments: Dict[str, Any]) -> ToolResult:
    """Create a product feed for a catalog.
    
    Args:
        arguments: {
            "catalog_id": "123",
            "name": "My Product Feed",
            "schedule": "DAILY",
            "url": "https://example.com/feed.xml",
            "format": "XML"  # or "CSV"
        }
        
    Returns:
        ToolResult with created feed ID
    """
    try:
        client = get_client()
        catalog_id = arguments.get("catalog_id")
        
        if not catalog_id:
            return ToolResult(ok=False, error={"message": "catalog_id is required"})
        
        feed_data = {
            "name": arguments.get("name"),
            "schedule": arguments.get("schedule", "DAILY"),
            "url": arguments.get("url"),
            "format": arguments.get("format", "XML"),
        }
        
        # Add optional fields
        if "delimiter" in arguments:
            feed_data["delimiter"] = arguments["delimiter"]
        if "quoted_fields_mode" in arguments:
            feed_data["quoted_fields_mode"] = arguments["quoted_fields_mode"]
        
        response = await client.post(
            f"{catalog_id}/product_feeds",
            body=feed_data
        )
        
        return ToolResult(ok=True, data=response)
    except MetaApiError as exc:
        logger.error("create_catalog_feed_failed", **exc.to_dict())
        return ToolResult(ok=False, error=exc.to_dict())


async def get_catalog_feed_status_handler(arguments: Dict[str, Any]) -> ToolResult:
    """Get the status of a product feed.
    
    Args:
        arguments: {"feed_id": "123"}
        
    Returns:
        ToolResult with feed status and upload history
    """
    try:
        client = get_client()
        feed_id = arguments.get("feed_id")
        
        if not feed_id:
            return ToolResult(ok=False, error={"message": "feed_id is required"})
        
        # Get feed details
        feed_response = await client.get(
            feed_id,
            params={"fields": "id,name,schedule,latest_upload"}
        )
        
        # Get upload history
        uploads_response = await client.get(
            f"{feed_id}/uploads",
            params={"fields": "id,start_time,end_time,num_detected_items,num_persisted_items,num_invalid_items"}
        )
        
        return ToolResult(
            ok=True,
            data={
                "feed": feed_response,
                "uploads": uploads_response.get("data", []),
            }
        )
    except MetaApiError as exc:
        logger.error("get_catalog_feed_status_failed", feed_id=feed_id, **exc.to_dict())
        return ToolResult(ok=False, error=exc.to_dict())


async def create_catalog_product_set_handler(arguments: Dict[str, Any]) -> ToolResult:
    """Create a product set within a catalog.
    
    Args:
        arguments: {
            "catalog_id": "123",
            "name": "Summer Collection",
            "filter": {
                "product_type": {"eq": "shoes"}
            }
        }
        
    Returns:
        ToolResult with created product set ID
    """
    try:
        client = get_client()
        catalog_id = arguments.get("catalog_id")
        
        if not catalog_id:
            return ToolResult(ok=False, error={"message": "catalog_id is required"})
        
        set_data = {
            "name": arguments.get("name"),
            "filter": arguments.get("filter", {}),
        }
        
        response = await client.post(
            f"{catalog_id}/product_sets",
            body=set_data
        )
        
        return ToolResult(ok=True, data=response)
    except MetaApiError as exc:
        logger.error("create_catalog_product_set_failed", **exc.to_dict())
        return ToolResult(ok=False, error=exc.to_dict())

