#!/usr/bin/env python3
"""
MiniMax Image Generation MCP Server
Provides image generation via MiniMax API
"""

import os
import base64
import requests
from urllib.parse import urlparse
from mcp.server.fastmcp import FastMCP


# Initialize MCP server
mcp = FastMCP("minimax-image-generator")


def read_local_image(file_path: str) -> str | None:
    """
    Read local image file and return as base64 encoded string.
    Returns the base64 string or None if failed.
    """
    try:
        with open(file_path, "rb") as f:
            image_data = f.read()
            return base64.b64encode(image_data).decode("utf-8")
    except Exception as e:
        return None


def build_subject_reference(subject_ref: str, subject_type: str) -> dict | None:
    """
    Build subject_reference object from URL or local file path.
    
    Args:
        subject_ref: URL or local file path
        subject_type: Type of subject (character, product, logo, etc.)
    
    Returns:
        dict with subject_reference structure or None if failed
    """
    # Check if it's a URL or local file
    if subject_ref.startswith(("http://", "https://")):
        # It's a URL
        return {
            "type": subject_type,
            "image_file": subject_ref
        }
    else:
        # It's a local file - convert to base64
        base64_data = read_local_image(subject_ref)
        if base64_data:
            return {
                "type": subject_type,
                "image_file": f"data:image/jpeg;base64,{base64_data}"
            }
        return None


@mcp.tool()
def generate_image(
    prompt: str,
    model: str = "image-01",
    aspect_ratio: str = "1:1",
    n: int = 1,
    prompt_optimizer: bool = False,
    subject_reference: str | None = None,
    subject_type: str = "character",
    seed: int | None = None,
    output_path: str | None = None
) -> str:
    """
    Generate images using MiniMax image generation API.
    
    Args:
        prompt: The image generation prompt describing what to generate
        model: Image generation model (default: image-01)
        aspect_ratio: Image aspect ratio (default: 1:1, options: 1:1, 16:9, 9:16, 4:3, 3:4)
        n: Number of images to generate (default: 1, max: 3)
        prompt_optimizer: Enable prompt optimizer (default: false)
        subject_reference: Reference image URL or local file path for image-to-image generation
        subject_type: Subject reference type (default: character, options: character, product, logo, video_subject, other)
        seed: Random seed for reproducible generation
        output_path: Optional local path to save the generated image
    
    Returns:
        Image URLs and generation status
    """
    api_key = os.environ.get("MINIMAX_API_KEY", "")
    api_base = "https://api.minimaxi.com"
    
    if not api_key:
        return "Error: MINIMAX_API_KEY environment variable is not set"
    
    # Build request payload
    payload = {
        "model": model,
        "prompt": prompt,
        "aspect_ratio": aspect_ratio,
        "response_format": "url",
        "n": n,
        "prompt_optimizer": prompt_optimizer
    }
    
    # Add seed if provided
    if seed is not None:
        payload["seed"] = seed
    
    # Add subject_reference for image-to-image generation
    if subject_reference:
        subject_ref = build_subject_reference(subject_reference, subject_type)
        if subject_ref:
            payload["subject_reference"] = [subject_ref]
    
    # Make API request
    url = f"{api_base}/v1/image_generation"
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    }
    
    try:
        response = requests.post(url, headers=headers, json=payload, timeout=60)
        response.raise_for_status()
        result = response.json()
        
        # Check for API errors
        if result.get("base_resp", {}).get("status_code") != 0:
            error_msg = result.get("base_resp", {}).get("status_msg", "Unknown error")
            return f"API Error: {error_msg}"
        
        # Extract image URLs
        image_urls = result.get("data", {}).get("image_urls", [])
        metadata = result.get("metadata", {})
        request_id = result.get("id", "N/A")
        success_count = metadata.get("success_count", len(image_urls))
        
        # Save image if output_path provided
        saved_paths = []
        if output_path and image_urls:
            try:
                import time
                timestamp = int(time.time())
                
                for i, img_url in enumerate(image_urls, 1):
                    img_response = requests.get(img_url, timeout=30)
                    img_response.raise_for_status()
                    
                    # Determine file extension
                    parsed = urlparse(img_url)
                    ext = os.path.splitext(parsed.path)[1] if "." in parsed.path else ".jpeg"
                    if not ext or len(ext) > 5:
                        ext = ".jpeg"
                    
                    # Handle multiple images
                    if len(image_urls) > 1:
                        base_path = output_path.rsplit('.', 1)[0] if '.' in output_path else output_path
                        file_ext = output_path.rsplit('.', 1)[1] if '.' in output_path else ext
                        img_path = f"{base_path}_{i}_{timestamp}.{file_ext}"
                    else:
                        if not output_path.endswith(ext):
                            img_path = output_path + ext
                        else:
                            img_path = output_path
                    
                    # Ensure directory exists
                    os.makedirs(os.path.dirname(img_path) if os.path.dirname(img_path) else ".", exist_ok=True)
                    
                    with open(img_path, "wb") as f:
                        f.write(img_response.content)
                    saved_paths.append(os.path.abspath(img_path))
            except Exception as e:
                return f"Failed to save image: {str(e)}"
        
        # Build response
        response_text = f"Successfully generated {success_count} image(s)\n\n"
        response_text += f"Request ID: {request_id}\n\n"
        
        if saved_paths:
            response_text += "Saved to:\n"
            for path in saved_paths:
                response_text += f"  - {path}\n"
            response_text += "\n"
        
        response_text += "Image URLs:\n"
        for i, img_url in enumerate(image_urls, 1):
            response_text += f"  {i}. {img_url}\n"
        
        return response_text
        
    except requests.exceptions.RequestException as e:
        return f"Request Error: {str(e)}"
    except Exception as e:
        return f"Unexpected Error: {str(e)}"


if __name__ == "__main__":
    mcp.run()
