"""Database Handler — manages Coolify databases, lifecycle, and backups."""

import json
from typing import Any

from plugins.coolify.client import CoolifyClient


def _create_db_spec(db_type: str, description: str) -> dict[str, Any]:
    """Generate a create_* tool spec for a database type."""
    return {
        "name": f"create_{db_type}",
        "category": "crud",
        "method_name": f"create_{db_type}",
        "description": description,
        "schema": {
            "type": "object",
            "properties": {
                "project_uuid": {
                    "type": "string",
                    "description": "Project UUID",
                    "minLength": 1,
                },
                "server_uuid": {
                    "type": "string",
                    "description": "Server UUID",
                    "minLength": 1,
                },
                "environment_name": {
                    "type": "string",
                    "description": "Environment name (e.g., 'production')",
                    "minLength": 1,
                },
                "name": {
                    "anyOf": [{"type": "string"}, {"type": "null"}],
                    "description": "Database name",
                },
                "description": {
                    "anyOf": [{"type": "string"}, {"type": "null"}],
                    "description": "Database description",
                },
                "instant_deploy": {
                    "type": "boolean",
                    "description": "Deploy immediately after creation",
                    "default": False,
                },
            },
            "required": ["project_uuid", "server_uuid", "environment_name"],
        },
        "scope": "write",
    }


def get_tool_specifications() -> list[dict[str, Any]]:
    """Return tool specifications for ToolGenerator."""
    specs = [
        {
            "name": "list_databases",
            "category": "read",
            "method_name": "list_databases",
            "description": "List all Coolify databases.",
            "schema": {
                "type": "object",
                "properties": {},
            },
            "scope": "read",
        },
        {
            "name": "get_database",
            "category": "read_sensitive",
            "sensitivity": "sensitive",
            "method_name": "get_database",
            "description": "Get details of a specific Coolify database by UUID.",
            "schema": {
                "type": "object",
                "properties": {
                    "uuid": {
                        "type": "string",
                        "description": "Database UUID",
                        "minLength": 1,
                    },
                },
                "required": ["uuid"],
            },
            "scope": "read",
        },
        {
            "name": "update_database",
            "category": "crud",
            "method_name": "update_database",
            "description": "Update a Coolify database settings.",
            "schema": {
                "type": "object",
                "properties": {
                    "uuid": {
                        "type": "string",
                        "description": "Database UUID",
                        "minLength": 1,
                    },
                    "name": {
                        "anyOf": [{"type": "string"}, {"type": "null"}],
                        "description": "Database name",
                    },
                    "description": {
                        "anyOf": [{"type": "string"}, {"type": "null"}],
                        "description": "Database description",
                    },
                    "image": {
                        "anyOf": [{"type": "string"}, {"type": "null"}],
                        "description": "Docker image",
                    },
                    "is_public": {
                        "anyOf": [{"type": "boolean"}, {"type": "null"}],
                        "description": "Make database publicly accessible",
                    },
                    "public_port": {
                        "anyOf": [{"type": "integer"}, {"type": "null"}],
                        "description": "Public port number",
                    },
                },
                "required": ["uuid"],
            },
            "scope": "write",
        },
        {
            "name": "delete_database",
            "category": "system",
            "method_name": "delete_database",
            "description": (
                "Delete a Coolify database permanently. "
                "Optionally clean up volumes and Docker resources."
            ),
            "schema": {
                "type": "object",
                "properties": {
                    "uuid": {
                        "type": "string",
                        "description": "Database UUID",
                        "minLength": 1,
                    },
                    "delete_configurations": {
                        "type": "boolean",
                        "description": "Delete configurations",
                        "default": True,
                    },
                    "delete_volumes": {
                        "type": "boolean",
                        "description": "Delete volumes",
                        "default": True,
                    },
                    "docker_cleanup": {
                        "type": "boolean",
                        "description": "Run Docker cleanup",
                        "default": True,
                    },
                },
                "required": ["uuid"],
            },
            "scope": "admin",
        },
        {
            "name": "start_database",
            "category": "lifecycle",
            "method_name": "start_database",
            "description": "Start a Coolify database.",
            "schema": {
                "type": "object",
                "properties": {
                    "uuid": {
                        "type": "string",
                        "description": "Database UUID",
                        "minLength": 1,
                    },
                },
                "required": ["uuid"],
            },
            "scope": "write",
        },
        {
            "name": "stop_database",
            "category": "lifecycle",
            "method_name": "stop_database",
            "description": "Stop a running Coolify database.",
            "schema": {
                "type": "object",
                "properties": {
                    "uuid": {
                        "type": "string",
                        "description": "Database UUID",
                        "minLength": 1,
                    },
                },
                "required": ["uuid"],
            },
            "scope": "write",
        },
        {
            "name": "restart_database",
            "category": "lifecycle",
            "method_name": "restart_database",
            "description": "Restart a Coolify database.",
            "schema": {
                "type": "object",
                "properties": {
                    "uuid": {
                        "type": "string",
                        "description": "Database UUID",
                        "minLength": 1,
                    },
                },
                "required": ["uuid"],
            },
            "scope": "write",
        },
    ]

    # Add create specs for each database type
    db_types = [
        ("postgresql", "Create a PostgreSQL database on Coolify."),
        ("mysql", "Create a MySQL database on Coolify."),
        ("mariadb", "Create a MariaDB database on Coolify."),
        ("mongodb", "Create a MongoDB database on Coolify."),
        ("redis", "Create a Redis database on Coolify."),
        ("clickhouse", "Create a ClickHouse database on Coolify."),
    ]
    for db_type, desc in db_types:
        specs.append(_create_db_spec(db_type, desc))

    # Backup tools
    specs.extend(
        [
            {
                "name": "get_database_backups",
                "category": "backup",
                "sensitivity": "sensitive",
                "method_name": "get_database_backups",
                "description": "Get backup configuration and history for a Coolify database.",
                "schema": {
                    "type": "object",
                    "properties": {
                        "uuid": {
                            "type": "string",
                            "description": "Database UUID",
                            "minLength": 1,
                        },
                    },
                    "required": ["uuid"],
                },
                "scope": "read",
            },
            {
                "name": "create_database_backup",
                "category": "backup",
                "sensitivity": "sensitive",
                "method_name": "create_database_backup",
                "description": "Create a manual backup of a Coolify database.",
                "schema": {
                    "type": "object",
                    "properties": {
                        "uuid": {
                            "type": "string",
                            "description": "Database UUID",
                            "minLength": 1,
                        },
                    },
                    "required": ["uuid"],
                },
                "scope": "write",
            },
            {
                "name": "list_backup_executions",
                "category": "backup",
                "sensitivity": "sensitive",
                "method_name": "list_backup_executions",
                "description": "List all backup executions across all databases.",
                "schema": {
                    "type": "object",
                    "properties": {},
                },
                "scope": "read",
            },
        ]
    )

    return specs


# --- Handler Functions ---


async def list_databases(client: CoolifyClient) -> str:
    """List all databases."""
    databases = await client.list_databases()
    result = {"success": True, "count": len(databases), "databases": databases}
    return json.dumps(result, indent=2, ensure_ascii=False)


async def get_database(client: CoolifyClient, uuid: str) -> str:
    """Get database details."""
    db = await client.get_database(uuid)
    result = {"success": True, "database": db}
    return json.dumps(result, indent=2, ensure_ascii=False)


async def update_database(client: CoolifyClient, uuid: str, **kwargs) -> str:
    """Update database settings."""
    data = {k: v for k, v in kwargs.items() if v is not None and k != "uuid"}
    db = await client.update_database(uuid, data)
    result = {
        "success": True,
        "message": f"Database '{uuid}' updated successfully",
        "database": db,
    }
    return json.dumps(result, indent=2, ensure_ascii=False)


async def delete_database(
    client: CoolifyClient,
    uuid: str,
    delete_configurations: bool = True,
    delete_volumes: bool = True,
    docker_cleanup: bool = True,
) -> str:
    """Delete a database."""
    result_data = await client.delete_database(
        uuid,
        delete_configurations=delete_configurations,
        delete_volumes=delete_volumes,
        docker_cleanup=docker_cleanup,
    )
    result = {"success": True, "message": f"Database '{uuid}' deleted", "data": result_data}
    return json.dumps(result, indent=2, ensure_ascii=False)


async def start_database(client: CoolifyClient, uuid: str) -> str:
    """Start a database."""
    result_data = await client.start_database(uuid)
    result = {"success": True, "message": f"Database '{uuid}' starting", "data": result_data}
    return json.dumps(result, indent=2, ensure_ascii=False)


async def stop_database(client: CoolifyClient, uuid: str) -> str:
    """Stop a database."""
    result_data = await client.stop_database(uuid)
    result = {"success": True, "message": f"Database '{uuid}' stopping", "data": result_data}
    return json.dumps(result, indent=2, ensure_ascii=False)


async def restart_database(client: CoolifyClient, uuid: str) -> str:
    """Restart a database."""
    result_data = await client.restart_database(uuid)
    result = {"success": True, "message": f"Database '{uuid}' restarting", "data": result_data}
    return json.dumps(result, indent=2, ensure_ascii=False)


async def _create_database(client: CoolifyClient, db_type: str, **kwargs) -> str:
    """Create a database of given type."""
    data = {k: v for k, v in kwargs.items() if v is not None}
    db = await client.create_database(db_type, data)
    result = {
        "success": True,
        "message": f"{db_type.title()} database created successfully",
        "database": db,
    }
    return json.dumps(result, indent=2, ensure_ascii=False)


async def create_postgresql(client: CoolifyClient, **kwargs) -> str:
    """Create a PostgreSQL database."""
    return await _create_database(client, "postgresql", **kwargs)


async def create_mysql(client: CoolifyClient, **kwargs) -> str:
    """Create a MySQL database."""
    return await _create_database(client, "mysql", **kwargs)


async def create_mariadb(client: CoolifyClient, **kwargs) -> str:
    """Create a MariaDB database."""
    return await _create_database(client, "mariadb", **kwargs)


async def create_mongodb(client: CoolifyClient, **kwargs) -> str:
    """Create a MongoDB database."""
    return await _create_database(client, "mongodb", **kwargs)


async def create_redis(client: CoolifyClient, **kwargs) -> str:
    """Create a Redis database."""
    return await _create_database(client, "redis", **kwargs)


async def create_clickhouse(client: CoolifyClient, **kwargs) -> str:
    """Create a ClickHouse database."""
    return await _create_database(client, "clickhouse", **kwargs)


async def get_database_backups(client: CoolifyClient, uuid: str) -> str:
    """Get database backups."""
    backups = await client.get_database_backups(uuid)
    result = {"success": True, "backups": backups}
    return json.dumps(result, indent=2, ensure_ascii=False)


async def create_database_backup(client: CoolifyClient, uuid: str) -> str:
    """Create a manual database backup."""
    result_data = await client.create_database_backup(uuid)
    result = {
        "success": True,
        "message": f"Backup created for database '{uuid}'",
        "data": result_data,
    }
    return json.dumps(result, indent=2, ensure_ascii=False)


async def list_backup_executions(client: CoolifyClient) -> str:
    """List all backup executions."""
    executions = await client.list_backup_executions()
    result = {"success": True, "count": len(executions), "executions": executions}
    return json.dumps(result, indent=2, ensure_ascii=False)
