"""Viewport Domain Tools for Godot MCP.

This module provides MCP tools for viewport-related operations in Godot projects,
including creating sub-viewports and configuring rendering options.
"""

import asyncio
from pathlib import Path

from godot_mcp.core import (
    create_error_response,
    godot_server,
    mcp,
    validate_path,
)

__all__ = [
    "viewport_add",
    "viewport_set_size",
    "viewport_configure",
]


@mcp.tool()
def viewport_add(
    project_path: str,
    scene_path: str,
    parent_node_path: str,
    viewport_name: str,
    width: int = 1024,
    height: int = 600,
) -> str:
    """Add a SubViewport node to a scene for rendering to texture.

    Category: Viewport

    Args:
        project_path: Path to the Godot project directory
        scene_path: Path to the scene file (relative to project)
        parent_node_path: Path to the parent node
        viewport_name: Name for the new viewport node
        width: Viewport width in pixels (default: 1024)
        height: Viewport height in pixels (default: 600)

    Returns:
        Success message or error description
    """
    if not all([project_path, scene_path, parent_node_path, viewport_name]):
        return create_error_response("All parameters except width and height are required")

    if not validate_path(project_path) or not validate_path(scene_path):
        return create_error_response("Invalid path")

    try:
        project_file = Path(project_path) / "project.godot"
        if not project_file.exists():
            return create_error_response(f"Not a valid Godot project: {project_path}")

        scene_full_path = Path(project_path) / scene_path
        if not scene_full_path.exists():
            return create_error_response(f"Scene file does not exist: {scene_path}")

        params = {
            "scenePath": scene_path,
            "parentNodePath": parent_node_path,
            "viewportName": viewport_name,
            "width": width,
            "height": height,
        }

        stdout, stderr = asyncio.run(
            godot_server.execute_operation("add_viewport", params, project_path)
        )

        if stderr and ("Failed to" in stderr or "[ERROR]" in stderr):
            return create_error_response(f"Failed to add viewport: {stderr}")

        return f"Viewport '{viewport_name}' added to '{parent_node_path}' with size {width}x{height}."

    except Exception as error:
        return create_error_response(f"Failed to add viewport: {error}")


@mcp.tool()
def viewport_set_size(
    project_path: str,
    scene_path: str,
    viewport_path: str,
    width: int,
    height: int,
) -> str:
    """Set the size of a SubViewport.

    Category: Viewport

    Args:
        project_path: Path to the Godot project directory
        scene_path: Path to the scene file (relative to project)
        viewport_path: Path to the viewport node
        width: New width in pixels
        height: New height in pixels

    Returns:
        Success message or error description
    """
    if not all([project_path, scene_path, viewport_path]):
        return create_error_response("All parameters are required")

    if not validate_path(project_path) or not validate_path(scene_path):
        return create_error_response("Invalid path")

    try:
        project_file = Path(project_path) / "project.godot"
        if not project_file.exists():
            return create_error_response(f"Not a valid Godot project: {project_path}")

        params = {
            "scenePath": scene_path,
            "viewportPath": viewport_path,
            "width": width,
            "height": height,
        }

        stdout, stderr = asyncio.run(
            godot_server.execute_operation("set_viewport_size", params, project_path)
        )

        if stderr and ("Failed to" in stderr or "[ERROR]" in stderr):
            return create_error_response(f"Failed to set viewport size: {stderr}")

        return f"Viewport '{viewport_path}' size set to {width}x{height}."

    except Exception as error:
        return create_error_response(f"Failed to set viewport size: {error}")


@mcp.tool()
def viewport_configure(
    project_path: str,
    scene_path: str,
    viewport_path: str,
    transparent_bg: bool | None = None,
    handle_input_locally: bool | None = None,
    render_target_update_mode: str | None = None,
    msaa: str | None = None,
) -> str:
    """Configure rendering options for a SubViewport.

    Category: Viewport

    Args:
        project_path: Path to the Godot project directory
        scene_path: Path to the scene file (relative to project)
        viewport_path: Path to the viewport node
        transparent_bg: Whether to use a transparent background
        handle_input_locally: Whether to handle input locally
        render_target_update_mode: Update mode (Disabled, Once, WhenVisible, WhenParentVisible, Always)
        msaa: MSAA mode (Disabled, 2x, 4x, 8x)

    Returns:
        Success message or error description
    """
    if not all([project_path, scene_path, viewport_path]):
        return create_error_response("project_path, scene_path, and viewport_path are required")

    config_params = [transparent_bg, handle_input_locally, render_target_update_mode, msaa]
    if all(param is None for param in config_params):
        return create_error_response("At least one configuration parameter must be specified")

    if not validate_path(project_path) or not validate_path(scene_path):
        return create_error_response("Invalid path")

    try:
        project_file = Path(project_path) / "project.godot"
        if not project_file.exists():
            return create_error_response(f"Not a valid Godot project: {project_path}")

        params = {
            "scenePath": scene_path,
            "viewportPath": viewport_path,
        }

        if transparent_bg is not None:
            params["transparentBg"] = transparent_bg
        if handle_input_locally is not None:
            params["handleInputLocally"] = handle_input_locally
        if render_target_update_mode:
            params["renderTargetUpdateMode"] = render_target_update_mode
        if msaa:
            params["msaa"] = msaa

        stdout, stderr = asyncio.run(
            godot_server.execute_operation("configure_viewport", params, project_path)
        )

        if stderr and ("Failed to" in stderr or "[ERROR]" in stderr):
            return create_error_response(f"Failed to configure viewport: {stderr}")

        return f"Viewport '{viewport_path}' configured successfully."

    except Exception as error:
        return create_error_response(f"Failed to configure viewport: {error}")
