"""
Databases Handler - manages Appwrite databases, collections, attributes, and indexes

Phase I.1: 18 tools
- Databases: 5 (list, get, create, update, delete)
- Collections: 5 (list, get, create, update, delete)
- Attributes: 5 (list, create_string, create_integer, create_boolean, delete)
- Indexes: 3 (list, 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 (18 tools)"""
    return [
        # =====================
        # DATABASES (5)
        # =====================
        {
            "name": "list_databases",
            "method_name": "list_databases",
            "description": "List all databases in the Appwrite project. Returns database ID, name, and creation date.",
            "schema": {
                "type": "object",
                "properties": {
                    "queries": {
                        "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
                        "description": "Query strings for filtering (e.g., 'limit(25)', 'offset(0)')",
                    },
                    "search": {
                        "anyOf": [{"type": "string"}, {"type": "null"}],
                        "description": "Search term to filter databases by name",
                    },
                },
                "required": [],
            },
            "scope": "read",
        },
        {
            "name": "get_database",
            "method_name": "get_database",
            "description": "Get database details by ID.",
            "schema": {
                "type": "object",
                "properties": {"database_id": {"type": "string", "description": "Database ID"}},
                "required": ["database_id"],
            },
            "scope": "read",
        },
        {
            "name": "create_database",
            "method_name": "create_database",
            "description": "Create a new database. Use 'unique()' as database_id to auto-generate a unique ID.",
            "schema": {
                "type": "object",
                "properties": {
                    "database_id": {
                        "type": "string",
                        "description": "Unique database ID. Use 'unique()' for auto-generation",
                    },
                    "name": {"type": "string", "description": "Database name"},
                    "enabled": {
                        "type": "boolean",
                        "description": "Enable or disable the database",
                        "default": True,
                    },
                },
                "required": ["database_id", "name"],
            },
            "scope": "write",
        },
        {
            "name": "update_database",
            "method_name": "update_database",
            "description": "Update database name or enabled status.",
            "schema": {
                "type": "object",
                "properties": {
                    "database_id": {"type": "string", "description": "Database ID"},
                    "name": {"type": "string", "description": "New database name"},
                    "enabled": {
                        "anyOf": [{"type": "boolean"}, {"type": "null"}],
                        "description": "Enable or disable the database",
                    },
                },
                "required": ["database_id", "name"],
            },
            "scope": "write",
        },
        {
            "name": "delete_database",
            "method_name": "delete_database",
            "description": "Delete a database and all its collections. This action is irreversible.",
            "schema": {
                "type": "object",
                "properties": {
                    "database_id": {"type": "string", "description": "Database ID to delete"}
                },
                "required": ["database_id"],
            },
            "scope": "admin",
        },
        # =====================
        # COLLECTIONS (5)
        # =====================
        {
            "name": "list_collections",
            "method_name": "list_collections",
            "description": "List all collections in a database.",
            "schema": {
                "type": "object",
                "properties": {
                    "database_id": {"type": "string", "description": "Database ID"},
                    "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 collections",
                    },
                },
                "required": ["database_id"],
            },
            "scope": "read",
        },
        {
            "name": "get_collection",
            "method_name": "get_collection",
            "description": "Get collection details including attributes and indexes.",
            "schema": {
                "type": "object",
                "properties": {
                    "database_id": {"type": "string", "description": "Database ID"},
                    "collection_id": {"type": "string", "description": "Collection ID"},
                },
                "required": ["database_id", "collection_id"],
            },
            "scope": "read",
        },
        {
            "name": "create_collection",
            "method_name": "create_collection",
            "description": "Create a new collection in a database. Use 'unique()' for auto-generated ID.",
            "schema": {
                "type": "object",
                "properties": {
                    "database_id": {"type": "string", "description": "Database ID"},
                    "collection_id": {
                        "type": "string",
                        "description": "Unique collection ID. Use 'unique()' for auto-generation",
                    },
                    "name": {"type": "string", "description": "Collection name"},
                    "permissions": {
                        "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
                        "description": "Collection permissions (e.g., 'read(\"any\")', 'write(\"users\")')",
                    },
                    "document_security": {
                        "type": "boolean",
                        "description": "Enable document-level security",
                        "default": True,
                    },
                    "enabled": {
                        "type": "boolean",
                        "description": "Enable or disable the collection",
                        "default": True,
                    },
                },
                "required": ["database_id", "collection_id", "name"],
            },
            "scope": "write",
        },
        {
            "name": "update_collection",
            "method_name": "update_collection",
            "description": "Update collection settings.",
            "schema": {
                "type": "object",
                "properties": {
                    "database_id": {"type": "string", "description": "Database ID"},
                    "collection_id": {"type": "string", "description": "Collection ID"},
                    "name": {"type": "string", "description": "New collection name"},
                    "permissions": {
                        "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
                        "description": "New permissions",
                    },
                    "document_security": {
                        "anyOf": [{"type": "boolean"}, {"type": "null"}],
                        "description": "Enable/disable document-level security",
                    },
                    "enabled": {
                        "anyOf": [{"type": "boolean"}, {"type": "null"}],
                        "description": "Enable/disable the collection",
                    },
                },
                "required": ["database_id", "collection_id", "name"],
            },
            "scope": "write",
        },
        {
            "name": "delete_collection",
            "method_name": "delete_collection",
            "description": "Delete a collection and all its documents. This action is irreversible.",
            "schema": {
                "type": "object",
                "properties": {
                    "database_id": {"type": "string", "description": "Database ID"},
                    "collection_id": {"type": "string", "description": "Collection ID to delete"},
                },
                "required": ["database_id", "collection_id"],
            },
            "scope": "admin",
        },
        # =====================
        # ATTRIBUTES (5)
        # =====================
        {
            "name": "list_attributes",
            "method_name": "list_attributes",
            "description": "List all attributes (fields/columns) of a collection.",
            "schema": {
                "type": "object",
                "properties": {
                    "database_id": {"type": "string", "description": "Database ID"},
                    "collection_id": {"type": "string", "description": "Collection ID"},
                    "queries": {
                        "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
                        "description": "Query strings for filtering",
                    },
                },
                "required": ["database_id", "collection_id"],
            },
            "scope": "read",
        },
        {
            "name": "create_string_attribute",
            "method_name": "create_string_attribute",
            "description": "Create a string attribute in a collection.",
            "schema": {
                "type": "object",
                "properties": {
                    "database_id": {"type": "string", "description": "Database ID"},
                    "collection_id": {"type": "string", "description": "Collection ID"},
                    "key": {"type": "string", "description": "Attribute key (field name)"},
                    "size": {
                        "type": "integer",
                        "description": "Maximum string length",
                        "default": 255,
                    },
                    "required": {
                        "type": "boolean",
                        "description": "Is this field required?",
                        "default": False,
                    },
                    "default": {
                        "anyOf": [{"type": "string"}, {"type": "null"}],
                        "description": "Default value",
                    },
                    "array": {
                        "type": "boolean",
                        "description": "Is this an array attribute?",
                        "default": False,
                    },
                    "encrypt": {
                        "type": "boolean",
                        "description": "Encrypt the attribute value",
                        "default": False,
                    },
                },
                "required": ["database_id", "collection_id", "key"],
            },
            "scope": "write",
        },
        {
            "name": "create_integer_attribute",
            "method_name": "create_integer_attribute",
            "description": "Create an integer attribute in a collection.",
            "schema": {
                "type": "object",
                "properties": {
                    "database_id": {"type": "string", "description": "Database ID"},
                    "collection_id": {"type": "string", "description": "Collection ID"},
                    "key": {"type": "string", "description": "Attribute key (field name)"},
                    "required": {
                        "type": "boolean",
                        "description": "Is this field required?",
                        "default": False,
                    },
                    "min": {
                        "anyOf": [{"type": "integer"}, {"type": "null"}],
                        "description": "Minimum value",
                    },
                    "max": {
                        "anyOf": [{"type": "integer"}, {"type": "null"}],
                        "description": "Maximum value",
                    },
                    "default": {
                        "anyOf": [{"type": "integer"}, {"type": "null"}],
                        "description": "Default value",
                    },
                    "array": {
                        "type": "boolean",
                        "description": "Is this an array attribute?",
                        "default": False,
                    },
                },
                "required": ["database_id", "collection_id", "key"],
            },
            "scope": "write",
        },
        {
            "name": "create_boolean_attribute",
            "method_name": "create_boolean_attribute",
            "description": "Create a boolean attribute in a collection.",
            "schema": {
                "type": "object",
                "properties": {
                    "database_id": {"type": "string", "description": "Database ID"},
                    "collection_id": {"type": "string", "description": "Collection ID"},
                    "key": {"type": "string", "description": "Attribute key (field name)"},
                    "required": {
                        "type": "boolean",
                        "description": "Is this field required?",
                        "default": False,
                    },
                    "default": {
                        "anyOf": [{"type": "boolean"}, {"type": "null"}],
                        "description": "Default value",
                    },
                    "array": {
                        "type": "boolean",
                        "description": "Is this an array attribute?",
                        "default": False,
                    },
                },
                "required": ["database_id", "collection_id", "key"],
            },
            "scope": "write",
        },
        {
            "name": "delete_attribute",
            "method_name": "delete_attribute",
            "description": "Delete an attribute from a collection. This will remove the field from all documents.",
            "schema": {
                "type": "object",
                "properties": {
                    "database_id": {"type": "string", "description": "Database ID"},
                    "collection_id": {"type": "string", "description": "Collection ID"},
                    "key": {"type": "string", "description": "Attribute key to delete"},
                },
                "required": ["database_id", "collection_id", "key"],
            },
            "scope": "admin",
        },
        # =====================
        # INDEXES (3)
        # =====================
        {
            "name": "list_indexes",
            "method_name": "list_indexes",
            "description": "List all indexes of a collection.",
            "schema": {
                "type": "object",
                "properties": {
                    "database_id": {"type": "string", "description": "Database ID"},
                    "collection_id": {"type": "string", "description": "Collection ID"},
                    "queries": {
                        "anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
                        "description": "Query strings for filtering",
                    },
                },
                "required": ["database_id", "collection_id"],
            },
            "scope": "read",
        },
        {
            "name": "create_index",
            "method_name": "create_index",
            "description": "Create an index on collection attributes for faster queries.",
            "schema": {
                "type": "object",
                "properties": {
                    "database_id": {"type": "string", "description": "Database ID"},
                    "collection_id": {"type": "string", "description": "Collection ID"},
                    "key": {"type": "string", "description": "Index key (unique name)"},
                    "type": {
                        "type": "string",
                        "enum": ["key", "unique", "fulltext"],
                        "description": "Index type: key (regular), unique, or fulltext",
                    },
                    "attributes": {
                        "type": "array",
                        "items": {"type": "string"},
                        "description": "Array of attribute keys to index",
                    },
                    "orders": {
                        "anyOf": [
                            {"type": "array", "items": {"type": "string", "enum": ["ASC", "DESC"]}},
                            {"type": "null"},
                        ],
                        "description": "Sort order for each attribute (ASC or DESC)",
                    },
                },
                "required": ["database_id", "collection_id", "key", "type", "attributes"],
            },
            "scope": "write",
        },
        {
            "name": "delete_index",
            "method_name": "delete_index",
            "description": "Delete an index from a collection.",
            "schema": {
                "type": "object",
                "properties": {
                    "database_id": {"type": "string", "description": "Database ID"},
                    "collection_id": {"type": "string", "description": "Collection ID"},
                    "key": {"type": "string", "description": "Index key to delete"},
                },
                "required": ["database_id", "collection_id", "key"],
            },
            "scope": "admin",
        },
    ]


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


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

        response = {
            "success": True,
            "total": result.get("total", len(databases)),
            "databases": databases,
        }
        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_database(client: AppwriteClient, database_id: str) -> str:
    """Get database by ID."""
    try:
        result = await client.get_database(database_id)
        return json.dumps({"success": True, "database": result}, indent=2, ensure_ascii=False)

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


async def create_database(
    client: AppwriteClient, database_id: str, name: str, enabled: bool = True
) -> str:
    """Create a new database."""
    try:
        result = await client.create_database(database_id=database_id, name=name, enabled=enabled)
        return json.dumps(
            {
                "success": True,
                "message": f"Database '{name}' created successfully",
                "database": result,
            },
            indent=2,
            ensure_ascii=False,
        )

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


async def update_database(
    client: AppwriteClient, database_id: str, name: str, enabled: bool | None = None
) -> str:
    """Update database."""
    try:
        result = await client.update_database(database_id=database_id, name=name, enabled=enabled)
        return json.dumps(
            {"success": True, "message": "Database updated successfully", "database": result},
            indent=2,
            ensure_ascii=False,
        )

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


async def delete_database(client: AppwriteClient, database_id: str) -> str:
    """Delete database."""
    try:
        await client.delete_database(database_id)
        return json.dumps(
            {"success": True, "message": f"Database '{database_id}' deleted successfully"}, indent=2
        )

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


async def list_collections(
    client: AppwriteClient,
    database_id: str,
    queries: list[str] | None = None,
    search: str | None = None,
) -> str:
    """List collections in a database."""
    try:
        result = await client.list_collections(
            database_id=database_id, queries=queries, search=search
        )
        collections = result.get("collections", [])

        response = {
            "success": True,
            "database_id": database_id,
            "total": result.get("total", len(collections)),
            "collections": collections,
        }
        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_collection(client: AppwriteClient, database_id: str, collection_id: str) -> str:
    """Get collection details."""
    try:
        result = await client.get_collection(database_id, collection_id)
        return json.dumps({"success": True, "collection": result}, indent=2, ensure_ascii=False)

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


async def create_collection(
    client: AppwriteClient,
    database_id: str,
    collection_id: str,
    name: str,
    permissions: list[str] | None = None,
    document_security: bool = True,
    enabled: bool = True,
) -> str:
    """Create a new collection."""
    try:
        result = await client.create_collection(
            database_id=database_id,
            collection_id=collection_id,
            name=name,
            permissions=permissions,
            document_security=document_security,
            enabled=enabled,
        )
        return json.dumps(
            {
                "success": True,
                "message": f"Collection '{name}' created successfully",
                "collection": result,
            },
            indent=2,
            ensure_ascii=False,
        )

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


async def update_collection(
    client: AppwriteClient,
    database_id: str,
    collection_id: str,
    name: str,
    permissions: list[str] | None = None,
    document_security: bool | None = None,
    enabled: bool | None = None,
) -> str:
    """Update collection."""
    try:
        result = await client.update_collection(
            database_id=database_id,
            collection_id=collection_id,
            name=name,
            permissions=permissions,
            document_security=document_security,
            enabled=enabled,
        )
        return json.dumps(
            {"success": True, "message": "Collection updated successfully", "collection": result},
            indent=2,
            ensure_ascii=False,
        )

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


async def delete_collection(client: AppwriteClient, database_id: str, collection_id: str) -> str:
    """Delete collection."""
    try:
        await client.delete_collection(database_id, collection_id)
        return json.dumps(
            {"success": True, "message": f"Collection '{collection_id}' deleted successfully"},
            indent=2,
        )

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


async def list_attributes(
    client: AppwriteClient, database_id: str, collection_id: str, queries: list[str] | None = None
) -> str:
    """List collection attributes."""
    try:
        result = await client.list_attributes(
            database_id=database_id, collection_id=collection_id, queries=queries
        )
        attributes = result.get("attributes", [])

        response = {
            "success": True,
            "database_id": database_id,
            "collection_id": collection_id,
            "total": result.get("total", len(attributes)),
            "attributes": attributes,
        }
        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 create_string_attribute(
    client: AppwriteClient,
    database_id: str,
    collection_id: str,
    key: str,
    size: int = 255,
    required: bool = False,
    default: str | None = None,
    array: bool = False,
    encrypt: bool = False,
) -> str:
    """Create string attribute."""
    try:
        result = await client.create_string_attribute(
            database_id=database_id,
            collection_id=collection_id,
            key=key,
            size=size,
            required=required,
            default=default,
            array=array,
            encrypt=encrypt,
        )
        return json.dumps(
            {
                "success": True,
                "message": f"String attribute '{key}' created successfully",
                "attribute": result,
            },
            indent=2,
            ensure_ascii=False,
        )

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


async def create_integer_attribute(
    client: AppwriteClient,
    database_id: str,
    collection_id: str,
    key: str,
    required: bool = False,
    min: int | None = None,
    max: int | None = None,
    default: int | None = None,
    array: bool = False,
) -> str:
    """Create integer attribute."""
    try:
        result = await client.create_integer_attribute(
            database_id=database_id,
            collection_id=collection_id,
            key=key,
            required=required,
            min=min,
            max=max,
            default=default,
            array=array,
        )
        return json.dumps(
            {
                "success": True,
                "message": f"Integer attribute '{key}' created successfully",
                "attribute": result,
            },
            indent=2,
            ensure_ascii=False,
        )

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


async def create_boolean_attribute(
    client: AppwriteClient,
    database_id: str,
    collection_id: str,
    key: str,
    required: bool = False,
    default: bool | None = None,
    array: bool = False,
) -> str:
    """Create boolean attribute."""
    try:
        result = await client.create_boolean_attribute(
            database_id=database_id,
            collection_id=collection_id,
            key=key,
            required=required,
            default=default,
            array=array,
        )
        return json.dumps(
            {
                "success": True,
                "message": f"Boolean attribute '{key}' created successfully",
                "attribute": result,
            },
            indent=2,
            ensure_ascii=False,
        )

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


async def delete_attribute(
    client: AppwriteClient, database_id: str, collection_id: str, key: str
) -> str:
    """Delete attribute."""
    try:
        await client.delete_attribute(database_id, collection_id, key)
        return json.dumps(
            {"success": True, "message": f"Attribute '{key}' deleted successfully"}, indent=2
        )

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


async def list_indexes(
    client: AppwriteClient, database_id: str, collection_id: str, queries: list[str] | None = None
) -> str:
    """List collection indexes."""
    try:
        result = await client.list_indexes(
            database_id=database_id, collection_id=collection_id, queries=queries
        )
        indexes = result.get("indexes", [])

        response = {
            "success": True,
            "database_id": database_id,
            "collection_id": collection_id,
            "total": result.get("total", len(indexes)),
            "indexes": indexes,
        }
        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 create_index(
    client: AppwriteClient,
    database_id: str,
    collection_id: str,
    key: str,
    type: str,
    attributes: list[str],
    orders: list[str] | None = None,
) -> str:
    """Create index."""
    try:
        result = await client.create_index(
            database_id=database_id,
            collection_id=collection_id,
            key=key,
            type=type,
            attributes=attributes,
            orders=orders,
        )
        return json.dumps(
            {"success": True, "message": f"Index '{key}' created successfully", "index": result},
            indent=2,
            ensure_ascii=False,
        )

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


async def delete_index(
    client: AppwriteClient, database_id: str, collection_id: str, key: str
) -> str:
    """Delete index."""
    try:
        await client.delete_index(database_id, collection_id, key)
        return json.dumps(
            {"success": True, "message": f"Index '{key}' deleted successfully"}, indent=2
        )

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