"""FastMCP server for Midjourney image generation via ImagineAPI."""

from typing import Any

from mcp.server.fastmcp import FastMCP
from mcp.server.fastmcp.utilities.types import Image

from .models import ImageStatus
from .resources import get_generation_by_id, get_generations, get_stats
from .tools import (
    midjourney_get_image,
    midjourney_get_status,
    midjourney_imagine,
    midjourney_list_images,
)

VALID_STATUSES = {s.value for s in ImageStatus}

mcp = FastMCP(
    "midjourney_mcp",
    instructions="Generate Midjourney images via ImagineAPI",
)


@mcp.tool(name="midjourney_imagine")
async def imagine(prompt: str, ref: str | None = None) -> dict[str, Any]:
    """Generate an image using Midjourney.

    Args:
        prompt: Image generation prompt (supports Midjourney syntax, e.g., --ar 16:9)
        ref: Reference ID for tracking (optional)

    Returns:
        Generated image info (id, prompt, status, message)
    """
    return await midjourney_imagine(prompt=prompt, ref=ref)


@mcp.tool(name="midjourney_get_status")
async def get_status(image_id: str) -> dict[str, Any]:
    """Get image generation status.

    Args:
        image_id: Image ID to query

    Returns:
        Image status info (id, prompt, status, progress, url, upscaled_urls, error)
    """
    return await midjourney_get_status(image_id=image_id)


@mcp.tool(name="midjourney_list_images")
async def list_images(limit: int = 10, status: str | None = None) -> dict[str, Any]:
    """List recently generated images.

    Args:
        limit: Maximum number to retrieve (default: 10, max: 100)
        status: Status to filter by (pending, in-progress, completed, failed)

    Returns:
        Image list (images, total)

    Raises:
        ValueError: If status value is not allowed
    """
    if status is not None and status not in VALID_STATUSES:
        raise ValueError(
            f"Invalid status '{status}'. Allowed values: {', '.join(sorted(VALID_STATUSES))}"
        )
    return await midjourney_list_images(limit=limit, status=status)


@mcp.tool(name="midjourney_get_image")
async def get_image(image_id: str, upscale_index: int | None = None) -> Image:
    """Get image data for inline display.

    Args:
        image_id: Image ID to retrieve
        upscale_index: Index of upscaled image (0-3). If None, returns grid image.

    Returns:
        Image data for inline display in Claude Desktop

    Raises:
        ValueError: If image is not completed or upscale_index is invalid
    """
    return await midjourney_get_image(image_id=image_id, upscale_index=upscale_index)


# =============================================================================
# Resources
# =============================================================================


@mcp.resource("midjourney://generations")
async def resource_generations() -> list[dict[str, Any]]:
    """List all image generations.

    Returns all recent image generation records with status, prompts,
    and URLs for completed images.
    """
    return await get_generations()


@mcp.resource("midjourney://generations/{status}")
async def resource_generations_by_status(status: str) -> list[dict[str, Any]]:
    """List image generations filtered by status.

    Args:
        status: Status to filter by (pending, in-progress, completed, failed)

    Returns:
        Filtered list of image generation records.

    Raises:
        ValueError: If status value is not allowed.
    """
    if status not in VALID_STATUSES:
        raise ValueError(
            f"Invalid status '{status}'. Allowed values: {', '.join(sorted(VALID_STATUSES))}"
        )
    return await get_generations(status=status)


@mcp.resource("midjourney://generation/{id}")
async def resource_generation_by_id(id: str) -> dict[str, Any]:
    """Get detailed information for a specific image generation.

    Args:
        id: The ID of the image to retrieve.

    Returns:
        Detailed image generation record with full prompt, status,
        progress, URLs, and metadata.
    """
    return await get_generation_by_id(image_id=id)


@mcp.resource("midjourney://stats")
async def resource_stats() -> dict[str, Any]:
    """Get generation statistics.

    Returns aggregated statistics including total generations,
    counts by status, and completion rate.
    """
    return await get_stats()


def main() -> None:
    """Run the MCP server."""
    mcp.run()


if __name__ == "__main__":
    main()
