"""
Functions Handler - manages Appwrite serverless functions

Phase I.4: 14 tools
- Functions: 5 (list, get, create, update, delete)
- Deployments: 5 (list, get, create, delete, activate)
- Executions: 4 (list, get, create, delete)
"""

import json
from typing import Any

from plugins.appwrite.client import AppwriteClient


def get_tool_specifications() -> list[dict[str, Any]]:
    """Return tool specifications for ToolGenerator (14 tools)"""
    return [
        # =====================
        # FUNCTIONS (5)
        # =====================
        {
            "name": "list_functions",
            "method_name": "list_functions",
            "description": "List all serverless functions in the project.",
            "schema": {
                "type": "object",
                "properties": {
                    "queries": {
                        "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
                        "description": "Query strings for filtering",
                    },
                    "search": {
                        "anyOf": [{"type": "string"}, {"type": "null"}],
                        "description": "Search term to filter functions",
                    },
                },
                "required": [],
            },
            "scope": "read",
        },
        {
            "name": "get_function",
            "method_name": "get_function",
            "description": "Get function details including deployment status and configuration.",
            "schema": {
                "type": "object",
                "properties": {"function_id": {"type": "string", "description": "Function ID"}},
                "required": ["function_id"],
            },
            "scope": "read",
        },
        {
            "name": "create_function",
            "method_name": "create_function",
            "description": "Create a new serverless function.",
            "schema": {
                "type": "object",
                "properties": {
                    "function_id": {
                        "type": "string",
                        "description": "Unique function ID. Use 'unique()' for auto-generation",
                    },
                    "name": {"type": "string", "description": "Function name"},
                    "runtime": {
                        "type": "string",
                        "description": "Runtime (e.g., 'node-18.0', 'python-3.9', 'php-8.0', 'ruby-3.0')",
                        "examples": [
                            "node-18.0",
                            "node-20.0",
                            "python-3.9",
                            "python-3.11",
                            "php-8.0",
                            "php-8.2",
                            "ruby-3.0",
                            "go-1.21",
                            "dart-3.0",
                            "rust-1.70",
                        ],
                    },
                    "execute": {
                        "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
                        "description": "Execution permissions (e.g., ['any', 'users'])",
                    },
                    "events": {
                        "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
                        "description": "Events to trigger function (e.g., ['databases.*.collections.*.documents.*.create'])",
                    },
                    "schedule": {
                        "anyOf": [{"type": "string"}, {"type": "null"}],
                        "description": "Cron schedule (e.g., '0 * * * *' for every hour)",
                    },
                    "timeout": {
                        "type": "integer",
                        "description": "Execution timeout in seconds",
                        "default": 15,
                        "minimum": 1,
                        "maximum": 900,
                    },
                    "enabled": {
                        "type": "boolean",
                        "description": "Enable function",
                        "default": True,
                    },
                    "logging": {
                        "type": "boolean",
                        "description": "Enable logging",
                        "default": True,
                    },
                    "entrypoint": {
                        "anyOf": [{"type": "string"}, {"type": "null"}],
                        "description": "Entrypoint file (e.g., 'src/main.js')",
                    },
                    "commands": {
                        "anyOf": [{"type": "string"}, {"type": "null"}],
                        "description": "Build commands",
                    },
                },
                "required": ["function_id", "name", "runtime"],
            },
            "scope": "write",
        },
        {
            "name": "update_function",
            "method_name": "update_function",
            "description": "Update function configuration.",
            "schema": {
                "type": "object",
                "properties": {
                    "function_id": {"type": "string", "description": "Function ID"},
                    "name": {"type": "string", "description": "Function name"},
                    "runtime": {
                        "anyOf": [{"type": "string"}, {"type": "null"}],
                        "description": "New runtime",
                    },
                    "execute": {
                        "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
                        "description": "New execution permissions",
                    },
                    "events": {
                        "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
                        "description": "New trigger events",
                    },
                    "schedule": {
                        "anyOf": [{"type": "string"}, {"type": "null"}],
                        "description": "New cron schedule",
                    },
                    "timeout": {
                        "anyOf": [{"type": "integer"}, {"type": "null"}],
                        "description": "New timeout",
                    },
                    "enabled": {
                        "anyOf": [{"type": "boolean"}, {"type": "null"}],
                        "description": "Enable/disable function",
                    },
                },
                "required": ["function_id", "name"],
            },
            "scope": "write",
        },
        {
            "name": "delete_function",
            "method_name": "delete_function",
            "description": "Delete a function and all its deployments.",
            "schema": {
                "type": "object",
                "properties": {
                    "function_id": {"type": "string", "description": "Function ID to delete"}
                },
                "required": ["function_id"],
            },
            "scope": "admin",
        },
        # =====================
        # DEPLOYMENTS (5)
        # =====================
        {
            "name": "list_deployments",
            "method_name": "list_deployments",
            "description": "List all deployments of a function.",
            "schema": {
                "type": "object",
                "properties": {
                    "function_id": {"type": "string", "description": "Function ID"},
                    "queries": {
                        "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
                        "description": "Query strings for filtering",
                    },
                    "search": {
                        "anyOf": [{"type": "string"}, {"type": "null"}],
                        "description": "Search term",
                    },
                },
                "required": ["function_id"],
            },
            "scope": "read",
        },
        {
            "name": "get_deployment",
            "method_name": "get_deployment",
            "description": "Get deployment details including build status and logs.",
            "schema": {
                "type": "object",
                "properties": {
                    "function_id": {"type": "string", "description": "Function ID"},
                    "deployment_id": {"type": "string", "description": "Deployment ID"},
                },
                "required": ["function_id", "deployment_id"],
            },
            "scope": "read",
        },
        {
            "name": "delete_deployment",
            "method_name": "delete_deployment",
            "description": "Delete a deployment.",
            "schema": {
                "type": "object",
                "properties": {
                    "function_id": {"type": "string", "description": "Function ID"},
                    "deployment_id": {"type": "string", "description": "Deployment ID to delete"},
                },
                "required": ["function_id", "deployment_id"],
            },
            "scope": "write",
        },
        {
            "name": "activate_deployment",
            "method_name": "activate_deployment",
            "description": "Activate a deployment (set as the active version for the function).",
            "schema": {
                "type": "object",
                "properties": {
                    "function_id": {"type": "string", "description": "Function ID"},
                    "deployment_id": {"type": "string", "description": "Deployment ID to activate"},
                },
                "required": ["function_id", "deployment_id"],
            },
            "scope": "write",
        },
        {
            "name": "get_active_deployment",
            "method_name": "get_active_deployment",
            "description": "Get the currently active deployment for a function.",
            "schema": {
                "type": "object",
                "properties": {"function_id": {"type": "string", "description": "Function ID"}},
                "required": ["function_id"],
            },
            "scope": "read",
        },
        # =====================
        # EXECUTIONS (4)
        # =====================
        {
            "name": "list_executions",
            "method_name": "list_executions",
            "description": "List execution history for a function.",
            "schema": {
                "type": "object",
                "properties": {
                    "function_id": {"type": "string", "description": "Function ID"},
                    "queries": {
                        "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
                        "description": "Query strings for filtering",
                    },
                    "search": {
                        "anyOf": [{"type": "string"}, {"type": "null"}],
                        "description": "Search term",
                    },
                },
                "required": ["function_id"],
            },
            "scope": "read",
        },
        {
            "name": "get_execution",
            "method_name": "get_execution",
            "description": "Get execution details including response, logs, and timing.",
            "schema": {
                "type": "object",
                "properties": {
                    "function_id": {"type": "string", "description": "Function ID"},
                    "execution_id": {"type": "string", "description": "Execution ID"},
                },
                "required": ["function_id", "execution_id"],
            },
            "scope": "read",
        },
        {
            "name": "execute_function",
            "method_name": "execute_function",
            "description": "Execute a function immediately.",
            "schema": {
                "type": "object",
                "properties": {
                    "function_id": {"type": "string", "description": "Function ID"},
                    "body": {
                        "anyOf": [{"type": "string"}, {"type": "null"}],
                        "description": "Request body (JSON string)",
                    },
                    "async_execution": {
                        "type": "boolean",
                        "description": "Run asynchronously (don't wait for response)",
                        "default": False,
                    },
                    "path": {
                        "anyOf": [{"type": "string"}, {"type": "null"}],
                        "description": "Custom execution path",
                    },
                    "method": {
                        "type": "string",
                        "enum": ["GET", "POST", "PUT", "PATCH", "DELETE"],
                        "description": "HTTP method",
                        "default": "POST",
                    },
                    "headers": {
                        "anyOf": [{"type": "object"}, {"type": "null"}],
                        "description": "Custom headers",
                    },
                },
                "required": ["function_id"],
            },
            "scope": "write",
        },
        {
            "name": "delete_execution",
            "method_name": "delete_execution",
            "description": "Delete an execution log entry.",
            "schema": {
                "type": "object",
                "properties": {
                    "function_id": {"type": "string", "description": "Function ID"},
                    "execution_id": {"type": "string", "description": "Execution ID to delete"},
                },
                "required": ["function_id", "execution_id"],
            },
            "scope": "write",
        },
    ]


# =====================
# HANDLER FUNCTIONS
# =====================


async def list_functions(
    client: AppwriteClient, queries: list[str] | None = None, search: str | None = None
) -> str:
    """List all functions."""
    try:
        result = await client.list_functions(queries=queries, search=search)
        functions = result.get("functions", [])

        response = {
            "success": True,
            "total": result.get("total", len(functions)),
            "functions": functions,
        }
        return json.dumps(response, indent=2, ensure_ascii=False)

    except Exception as e:
        return json.dumps({"success": False, "error": str(e)}, indent=2)


async def get_function(client: AppwriteClient, function_id: str) -> str:
    """Get function by ID."""
    try:
        result = await client.get_function(function_id)
        return json.dumps({"success": True, "function": result}, indent=2, ensure_ascii=False)

    except Exception as e:
        return json.dumps({"success": False, "error": str(e)}, indent=2)


async def create_function(
    client: AppwriteClient,
    function_id: str,
    name: str,
    runtime: str,
    execute: list[str] | None = None,
    events: list[str] | None = None,
    schedule: str | None = None,
    timeout: int = 15,
    enabled: bool = True,
    logging: bool = True,
    entrypoint: str | None = None,
    commands: str | None = None,
) -> str:
    """Create a new function."""
    try:
        result = await client.create_function(
            function_id=function_id,
            name=name,
            runtime=runtime,
            execute=execute,
            events=events,
            schedule=schedule,
            timeout=timeout,
            enabled=enabled,
            logging=logging,
            entrypoint=entrypoint,
            commands=commands,
        )
        return json.dumps(
            {
                "success": True,
                "message": f"Function '{name}' created successfully",
                "function": result,
            },
            indent=2,
            ensure_ascii=False,
        )

    except Exception as e:
        return json.dumps({"success": False, "error": str(e)}, indent=2)


async def update_function(
    client: AppwriteClient,
    function_id: str,
    name: str,
    runtime: str | None = None,
    execute: list[str] | None = None,
    events: list[str] | None = None,
    schedule: str | None = None,
    timeout: int | None = None,
    enabled: bool | None = None,
) -> str:
    """Update function."""
    try:
        result = await client.update_function(
            function_id=function_id,
            name=name,
            runtime=runtime,
            execute=execute,
            events=events,
            schedule=schedule,
            timeout=timeout,
            enabled=enabled,
        )
        return json.dumps(
            {"success": True, "message": "Function updated successfully", "function": result},
            indent=2,
            ensure_ascii=False,
        )

    except Exception as e:
        return json.dumps({"success": False, "error": str(e)}, indent=2)


async def delete_function(client: AppwriteClient, function_id: str) -> str:
    """Delete function."""
    try:
        await client.delete_function(function_id)
        return json.dumps(
            {"success": True, "message": f"Function '{function_id}' deleted successfully"}, indent=2
        )

    except Exception as e:
        return json.dumps({"success": False, "error": str(e)}, indent=2)


async def list_deployments(
    client: AppwriteClient,
    function_id: str,
    queries: list[str] | None = None,
    search: str | None = None,
) -> str:
    """List function deployments."""
    try:
        result = await client.list_deployments(
            function_id=function_id, queries=queries, search=search
        )
        deployments = result.get("deployments", [])

        response = {
            "success": True,
            "function_id": function_id,
            "total": result.get("total", len(deployments)),
            "deployments": deployments,
        }
        return json.dumps(response, indent=2, ensure_ascii=False)

    except Exception as e:
        return json.dumps({"success": False, "error": str(e)}, indent=2)


async def get_deployment(client: AppwriteClient, function_id: str, deployment_id: str) -> str:
    """Get deployment by ID."""
    try:
        result = await client.get_deployment(function_id, deployment_id)
        return json.dumps({"success": True, "deployment": result}, indent=2, ensure_ascii=False)

    except Exception as e:
        return json.dumps({"success": False, "error": str(e)}, indent=2)


async def delete_deployment(client: AppwriteClient, function_id: str, deployment_id: str) -> str:
    """Delete deployment."""
    try:
        await client.delete_deployment(function_id, deployment_id)
        return json.dumps(
            {"success": True, "message": f"Deployment '{deployment_id}' deleted successfully"},
            indent=2,
        )

    except Exception as e:
        return json.dumps({"success": False, "error": str(e)}, indent=2)


async def activate_deployment(client: AppwriteClient, function_id: str, deployment_id: str) -> str:
    """Activate deployment."""
    try:
        result = await client.update_deployment(function_id, deployment_id)
        return json.dumps(
            {
                "success": True,
                "message": f"Deployment '{deployment_id}' activated successfully",
                "deployment": result,
            },
            indent=2,
            ensure_ascii=False,
        )

    except Exception as e:
        return json.dumps({"success": False, "error": str(e)}, indent=2)


async def get_active_deployment(client: AppwriteClient, function_id: str) -> str:
    """Get active deployment for function."""
    try:
        func = await client.get_function(function_id)
        deployment_id = func.get("deployment")

        if not deployment_id:
            return json.dumps(
                {
                    "success": True,
                    "message": "No active deployment",
                    "function_id": function_id,
                    "active_deployment": None,
                },
                indent=2,
            )

        deployment = await client.get_deployment(function_id, deployment_id)
        return json.dumps(
            {"success": True, "function_id": function_id, "active_deployment": deployment},
            indent=2,
            ensure_ascii=False,
        )

    except Exception as e:
        return json.dumps({"success": False, "error": str(e)}, indent=2)


async def list_executions(
    client: AppwriteClient,
    function_id: str,
    queries: list[str] | None = None,
    search: str | None = None,
) -> str:
    """List function executions."""
    try:
        result = await client.list_executions(
            function_id=function_id, queries=queries, search=search
        )
        executions = result.get("executions", [])

        response = {
            "success": True,
            "function_id": function_id,
            "total": result.get("total", len(executions)),
            "executions": executions,
        }
        return json.dumps(response, indent=2, ensure_ascii=False)

    except Exception as e:
        return json.dumps({"success": False, "error": str(e)}, indent=2)


async def get_execution(client: AppwriteClient, function_id: str, execution_id: str) -> str:
    """Get execution by ID."""
    try:
        result = await client.get_execution(function_id, execution_id)
        return json.dumps({"success": True, "execution": result}, indent=2, ensure_ascii=False)

    except Exception as e:
        return json.dumps({"success": False, "error": str(e)}, indent=2)


async def execute_function(
    client: AppwriteClient,
    function_id: str,
    body: str | None = None,
    async_execution: bool = False,
    path: str | None = None,
    method: str = "POST",
    headers: dict[str, str] | None = None,
) -> str:
    """Execute function."""
    try:
        result = await client.create_execution(
            function_id=function_id,
            body=body,
            async_execution=async_execution,
            path=path,
            method=method,
            headers=headers,
        )

        response = {
            "success": True,
            "execution_id": result.get("$id"),
            "status": result.get("status"),
            "status_code": result.get("responseStatusCode"),
            "duration": result.get("duration"),
            "response_body": result.get("responseBody"),
            "logs": result.get("logs"),
            "errors": result.get("errors"),
        }

        if async_execution:
            response["message"] = "Function execution started asynchronously"
        else:
            response["message"] = "Function executed successfully"

        return json.dumps(response, indent=2, ensure_ascii=False)

    except Exception as e:
        return json.dumps({"success": False, "error": str(e)}, indent=2)


async def delete_execution(client: AppwriteClient, function_id: str, execution_id: str) -> str:
    """Delete execution."""
    try:
        await client.delete_execution(function_id, execution_id)
        return json.dumps(
            {"success": True, "message": f"Execution '{execution_id}' deleted successfully"},
            indent=2,
        )

    except Exception as e:
        return json.dumps({"success": False, "error": str(e)}, indent=2)
