import base64
import io
import os

from mcp.types import TextContent
from PIL import Image

from .state import state

# Maximum file size (100MB)
MAX_FILE_SIZE = 100 * 1024 * 1024

# Image size constraints
MIN_WIDTH = 20
MAX_WIDTH = 800

def read_image_file_tool():
    return {
        "name": "read_image_file",
        "description": "Read an image file from the file system and return its contents as a base64-encoded string. "
                    "This tool supports common image formats like PNG, JPEG, GIF, and WebP. "
                    "The image data is returned in a format that can be displayed or processed by other tools. "
                    "Only works within the allowed directory. "
                    "Maximum file size is 100MB. "
                    "Example: Enter 'images/logo.png' to read a PNG image file.",
        "inputSchema": {
            "type": "object",
            "properties": {
                "path": {
                    "type": "string",
                    "description": "Path to the image file to read"
                },
                "max_size": {
                    "type": "integer",
                    "description": "Maximum file size in bytes (default: 100MB)",
                    "optional": True
                }
            },
            "required": ["path"]
        },
    }

async def handle_read_image_file(arguments: dict):
    """Handle reading an image file and converting it to base64."""
    path = arguments.get("path")
    max_size = arguments.get("max_size", MAX_FILE_SIZE)

    if not path:
        raise ValueError("path must be provided")

    # Determine full path based on whether input is absolute or relative
    if os.path.isabs(path):
        full_path = os.path.abspath(path)  # Just normalize the absolute path
    else:
        # For relative paths, join with allowed_directory
        full_path = os.path.abspath(os.path.join(state.allowed_directory, path))

    if not full_path.startswith(state.allowed_directory):
        raise ValueError(f"Access denied: Path ({full_path}) must be within allowed directory ({state.allowed_directory})")

    if not os.path.exists(full_path):
        raise ValueError(f"File does not exist: {full_path}")
    if not os.path.isfile(full_path):
        raise ValueError(f"Path is not a file: {full_path}")

    # Check file size before attempting to read
    file_size = os.path.getsize(full_path)
    if file_size > max_size:
        raise ValueError(f"File size ({file_size} bytes) exceeds maximum allowed size ({max_size} bytes)")

    try:
        # Try to open the image with PIL to validate it's a valid image
        with Image.open(full_path) as img:
            # Get the image format
            image_format = img.format.lower()
            if not image_format:
                # Try to determine format from file extension
                ext = os.path.splitext(full_path)[1].lower().lstrip('.')
                if ext in ['jpg', 'jpeg']:
                    image_format = 'jpeg'
                elif ext in ['png', 'gif', 'webp']:
                    image_format = ext
                else:
                    raise ValueError(f"Unsupported image format: {ext}")

            # Resize image if width is greater than MAX_WIDTH or less than MIN_WIDTH
            if img.width > MAX_WIDTH or img.width < MIN_WIDTH:
                # Calculate new dimensions maintaining aspect ratio
                if img.width > MAX_WIDTH:
                    target_width = MAX_WIDTH
                else:
                    target_width = MIN_WIDTH

                ratio = target_width / img.width
                new_height = int(img.height * ratio)
                img = img.resize((target_width, new_height), Image.Resampling.LANCZOS)

            # Convert image to bytes
            img_byte_arr = io.BytesIO()
            if image_format.lower() == 'jpeg':
                img.save(img_byte_arr, format=image_format, quality=85)  # Specify quality for JPEG
            else:
                img.save(img_byte_arr, format=image_format)
            img_byte_arr = img_byte_arr.getvalue()

            # Convert to base64
            base64_data = base64.b64encode(img_byte_arr).decode('utf-8')

            # Return the image data with its type
            return [TextContent(
                type="text",
                text=f"data:image/{image_format};base64,{base64_data}"
            )]
    except Image.UnidentifiedImageError:
        raise ValueError(f"File is not a valid image: {path}")
    except Exception as e:
        raise ValueError(f"Error reading image file: {str(e)}")
