"""Asset template and upload tools for Influ2 MCP."""

from __future__ import annotations

import base64
import json
import os
from typing import Annotated, Literal

from influ2_mcp.client import get_api_client
from influ2_mcp.config import resolve_client_id
from influ2_mcp.errors import Influ2Error, format_error_for_llm
from influ2_mcp.server import mcp


@mcp.tool()
async def influ2_list_asset_templates(
    client_id: Annotated[
        str | None,
        "Influ2 client ID. Omit to use configured default.",
    ] = None,
    asset_type: Annotated[
        str | None,
        "Filter by ad format: 'social', 'native', 'display', or 'thumbnail'. "
        "Omit for all formats.",
    ] = None,
    content_type: Annotated[
        str | None,
        "Filter by media type: 'image' or 'video'. Omit for all.",
    ] = None,
    resolution: Annotated[
        str | None,
        "Filter by specific resolution (e.g., '1080x1080', '300x250'). Omit for all.",
    ] = None,
) -> str:
    """List available asset templates showing required image/video specifications per ad format.

    Returns resolution requirements, supported file types, and format-specific constraints.
    Call this BEFORE uploading assets to ensure your creatives meet the requirements.

    Key resolution requirements by format:
    - Social & Native: 1080x1080 AND 1200x628 (both required)
    - Display banners: 300x250 AND 728x90 (required), plus optional 300x600, 970x250, etc.
    - Carousel cards: 1080x1080 per card
    - Video: up to 1920x1920, requires a thumbnail image
    - Images: PNG/JPEG/JPG, max 10MB
    - Video: MP4/MOV/M4V, max 1GB

    When a user asks: "What ad sizes do I need?", "What image resolutions are required?",
    "What are the display banner specs?", "What format should my video be?",
    "What size should my LinkedIn ad image be?", "What are the file requirements?"
    """
    try:
        cid = resolve_client_id(client_id)
        api_client = get_api_client()

        params: dict = {}
        if asset_type:
            params["asset_type"] = asset_type
        if content_type:
            params["content_type"] = content_type
        if resolution:
            params["resolution"] = resolution

        response = await api_client.get(
            f"/public/v1/clients/{cid}/assets",
            params=params if params else None,
        )

        templates = response.get("data", response.get("items", []))

        result = {
            "templates": templates,
            "count": len(templates) if isinstance(templates, list) else 0,
            "_summary": {
                "social_image": "1080x1080 + 1200x628 (PNG/JPEG, max 10MB each)",
                "native_image": "1080x1080 + 1200x628 (PNG/JPEG, max 10MB each)",
                "display_required": "300x250 + 728x90 (PNG/JPEG, max 10MB each)",
                "display_optional": "300x600, 970x250, 160x600, 320x50",
                "carousel_card": "1080x1080 per card (PNG/JPEG, max 10MB)",
                "video": "Up to 1920x1920 (MP4/MOV/M4V, max 1GB) + thumbnail image",
            },
            "_next_steps": [
                "Upload assets with influ2_upload_asset(source_type='url', media_type='image', source='...')",
            ],
        }
        return json.dumps(result, indent=2, default=str)

    except Influ2Error as e:
        return json.dumps(format_error_for_llm(e))
    except Exception as e:
        return json.dumps(format_error_for_llm(e))


@mcp.tool()
async def influ2_upload_asset(
    source_type: Annotated[
        Literal["url", "base64", "file_path"],
        "How to provide the asset:\n"
        "- 'url': A publicly accessible URL to the image or video\n"
        "- 'base64': Base64-encoded image data (images only)\n"
        "- 'file_path': Local file path (for programmatic use)",
    ],
    media_type: Annotated[
        Literal["image", "video"],
        "Whether this is an image or video asset",
    ],
    source: Annotated[
        str,
        "The actual data source — a URL, base64 string, or file path depending on source_type",
    ],
    filename: Annotated[
        str | None,
        "Optional filename (e.g., 'hero-1080x1080.png'). Auto-detected from URL/path if omitted.",
    ] = None,
    client_id: Annotated[
        str | None,
        "Influ2 client ID. Omit to use configured default.",
    ] = None,
    content_external_id: Annotated[
        str | None,
        "Optional external ID to tag this asset with for cross-system referencing.",
    ] = None,
) -> str:
    """Upload an image or video asset for use in ad creatives.

    Returns an asset_id to use when creating content with influ2_add_content.

    Supported formats:
    - Images: PNG, JPEG, JPG (max 10MB)
    - Video: MP4, MOV, M4V (max 1GB)

    Check influ2_list_asset_templates first for required resolutions per ad format.

    When a user asks: "Upload this image", "Upload images from these URLs",
    "Upload my ad creative", "Import this video", "Upload the banner images",
    "Upload the carousel card images", "Add this base64 image"
    """
    try:
        cid = resolve_client_id(client_id)
        api_client = get_api_client()

        params: dict = {}
        if content_external_id:
            params["content_external_id"] = content_external_id

        if source_type == "url":
            # Upload via URL
            endpoint = (
                f"/public/v1/clients/{cid}/upload/{'image' if media_type == 'image' else 'video'}/link"
            )
            response = await api_client.post(
                endpoint,
                json={"urls": [source]},
                **({"params": params} if params else {}),
            )

        elif source_type == "base64":
            if media_type != "image":
                return json.dumps({
                    "error": True,
                    "message": "Base64 upload is only supported for images, not video.",
                    "suggestion": "Use source_type='url' or 'file_path' for video uploads.",
                })

            fname = filename or "image.png"
            response = await api_client.post(
                f"/public/v1/clients/{cid}/upload/image/base64",
                json={"images": [{"filename": fname, "data": source}]},
            )

        elif source_type == "file_path":
            if not os.path.exists(source):
                return json.dumps({
                    "error": True,
                    "message": f"File not found: {source}",
                    "suggestion": "Check the file path and try again.",
                })

            fname = filename or os.path.basename(source)
            endpoint = (
                f"/public/v1/clients/{cid}/upload/{'image' if media_type == 'image' else 'video'}/file"
            )

            with open(source, "rb") as f:
                response = await api_client.post(
                    endpoint,
                    files={"file": (fname, f)},
                )
        else:
            return json.dumps({
                "error": True,
                "message": f"Invalid source_type '{source_type}'.",
            })

        # Extract asset info from response
        assets = response.get("assets", [response] if "id" in response else [])

        result = {
            "assets": assets,
            "count": len(assets),
            "_next_steps": [
                "Use the asset_id(s) when creating content with influ2_add_content()",
                "Upload more assets for different resolutions if needed",
            ],
        }
        return json.dumps(result, indent=2, default=str)

    except Influ2Error as e:
        return json.dumps(format_error_for_llm(e))
    except Exception as e:
        return json.dumps(format_error_for_llm(e))
