from typing import Annotated, Optional

from arcade.sdk import ToolContext, tool
from arcade.sdk.auth import Dropbox
from arcade.sdk.errors import ToolExecutionError

from arcade_dropbox.constants import Endpoint
from arcade_dropbox.exceptions import DropboxApiError
from arcade_dropbox.utils import parse_dropbox_path, send_dropbox_request


@tool(
    requires_auth=Dropbox(
        scopes=["files.content.read"],
    )
)
async def download_file(
    context: ToolContext,
    file_path: Annotated[
        Optional[str],
        "The path of the file to download. E.g. '/AcmeInc/Reports/Q1_2025.txt'. Defaults to None.",
    ] = None,
    file_id: Annotated[
        Optional[str],
        "The ID of the file to download. E.g. 'id:a4ayc_80_OEAAAAAAAAAYa'. Defaults to None.",
    ] = None,
) -> Annotated[dict, "Contents of the specified file"]:
    """Downloads the specified file.

    Note: either one of `file_path` or `file_id` must be provided.
    """
    if not file_path and not file_id:
        raise ToolExecutionError("Either `file_path` or `file_id` must be provided.")

    if file_path and file_id:
        raise ToolExecutionError("Only one of `file_path` or `file_id` can be provided.")

    try:
        result = await send_dropbox_request(
            context.get_auth_token_or_empty(),
            endpoint=Endpoint.DOWNLOAD_FILE,
            path=parse_dropbox_path(file_path) or file_id,
        )
    except DropboxApiError as api_error:
        return {"error": api_error.message}

    return {"file": result}
