# This file was auto-generated by Fern from our API Definition.

import typing

from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.request_options import RequestOptions
from ..types.database_data_response import DatabaseDataResponse
from ..types.database_mutation_response import DatabaseMutationResponse
from ..types.database_table_schema_response import DatabaseTableSchemaResponse
from ..types.database_tables_response import DatabaseTablesResponse
from ..types.delete_data_request import DeleteDataRequest
from .raw_client import AsyncRawDatabasesClient, RawDatabasesClient
from .types.data import Data

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class DatabasesClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._raw_client = RawDatabasesClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> RawDatabasesClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        RawDatabasesClient
        """
        return self._raw_client

    def list_tables(
        self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> DatabaseTablesResponse:
        """
        Get a list of all tables in the database with optional row counts.

        Parameters
        ----------
        asset_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DatabaseTablesResponse
            Successful Response

        Examples
        --------
        from athena import Athena

        client = Athena(
            api_key="YOUR_API_KEY",
        )
        client.databases.list_tables(
            asset_id="asset_id",
        )
        """
        _response = self._raw_client.list_tables(asset_id, request_options=request_options)
        return _response.data

    def select(
        self,
        asset_id: str,
        table_name: str,
        *,
        select: typing.Optional[str] = None,
        order: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> DatabaseDataResponse:
        """
        Query rows from a table in the database. Supports filtering, ordering, and pagination using PostgREST-style query parameters.

        **Filter Syntax:**
        - `?column=eq.value` - Equal
        - `?column=neq.value` - Not equal
        - `?column=gt.value` - Greater than
        - `?column=gte.value` - Greater than or equal
        - `?column=lt.value` - Less than
        - `?column=lte.value` - Less than or equal
        - `?column=like.*pattern*` - LIKE (case-sensitive)
        - `?column=ilike.*pattern*` - ILIKE (case-insensitive)
        - `?column=in.(a,b,c)` - IN list
        - `?column=is.null` - IS NULL

        Parameters
        ----------
        asset_id : str

        table_name : str

        select : typing.Optional[str]
            Columns to return (comma-separated, e.g., 'id,name,email')

        order : typing.Optional[str]
            Order by clause (e.g., 'created_at.desc', 'name.asc')

        limit : typing.Optional[int]
            Maximum number of rows to return

        offset : typing.Optional[int]
            Number of rows to skip

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DatabaseDataResponse
            Successful Response

        Examples
        --------
        from athena import Athena

        client = Athena(
            api_key="YOUR_API_KEY",
        )
        client.databases.select(
            asset_id="asset_id",
            table_name="table_name",
            select="select",
            order="order",
            limit=1,
            offset=1,
        )
        """
        _response = self._raw_client.select(
            asset_id,
            table_name,
            select=select,
            order=order,
            limit=limit,
            offset=offset,
            request_options=request_options,
        )
        return _response.data

    def insert(
        self,
        asset_id: str,
        table_name: str,
        *,
        data: Data,
        return_representation: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> DatabaseMutationResponse:
        """
        Insert one or more rows into a table.

        Parameters
        ----------
        asset_id : str

        table_name : str

        data : Data
            Single row object or array of row objects to insert

        return_representation : typing.Optional[bool]
            If true, return the inserted rows in the response

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DatabaseMutationResponse
            Successful Response

        Examples
        --------
        from athena import Athena

        client = Athena(
            api_key="YOUR_API_KEY",
        )
        client.databases.insert(
            asset_id="asset_id",
            table_name="table_name",
            data={"email": "alice@example.com", "name": "Alice"},
            return_representation=True,
        )
        """
        _response = self._raw_client.insert(
            asset_id,
            table_name,
            data=data,
            return_representation=return_representation,
            request_options=request_options,
        )
        return _response.data

    def delete(
        self,
        asset_id: str,
        table_name: str,
        *,
        request: typing.Optional[DeleteDataRequest] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> DatabaseMutationResponse:
        """
        Delete rows matching the filter conditions. Filter conditions are passed as query parameters using PostgREST syntax (e.g., `?id=eq.5`).

        **Warning:** Without filters, this will delete ALL rows in the table.

        Parameters
        ----------
        asset_id : str

        table_name : str

        request : typing.Optional[DeleteDataRequest]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DatabaseMutationResponse
            Successful Response

        Examples
        --------
        from athena import Athena, DeleteDataRequest

        client = Athena(
            api_key="YOUR_API_KEY",
        )
        client.databases.delete(
            asset_id="asset_id",
            table_name="table_name",
            request=DeleteDataRequest(
                return_representation=False,
            ),
        )
        """
        _response = self._raw_client.delete(asset_id, table_name, request=request, request_options=request_options)
        return _response.data

    def update(
        self,
        asset_id: str,
        table_name: str,
        *,
        data: typing.Dict[str, typing.Optional[typing.Any]],
        return_representation: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> DatabaseMutationResponse:
        """
        Update rows matching the filter conditions. Filter conditions are passed as query parameters using PostgREST syntax (e.g., `?id=eq.5`).

        **Warning:** Without filters, this will update ALL rows in the table.

        Parameters
        ----------
        asset_id : str

        table_name : str

        data : typing.Dict[str, typing.Optional[typing.Any]]
            Column values to update

        return_representation : typing.Optional[bool]
            If true, return the updated rows in the response

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DatabaseMutationResponse
            Successful Response

        Examples
        --------
        from athena import Athena

        client = Athena(
            api_key="YOUR_API_KEY",
        )
        client.databases.update(
            asset_id="asset_id",
            table_name="table_name",
            data={"email": "alice.smith@example.com", "name": "Alice Smith"},
            return_representation=True,
        )
        """
        _response = self._raw_client.update(
            asset_id,
            table_name,
            data=data,
            return_representation=return_representation,
            request_options=request_options,
        )
        return _response.data

    def get_table_schema(
        self, asset_id: str, table_name: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> DatabaseTableSchemaResponse:
        """
        Get the schema for a specific table, including column names, types, nullability, and default values. Useful for agent tooling and dynamic form generation.

        Parameters
        ----------
        asset_id : str

        table_name : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DatabaseTableSchemaResponse
            Successful Response

        Examples
        --------
        from athena import Athena

        client = Athena(
            api_key="YOUR_API_KEY",
        )
        client.databases.get_table_schema(
            asset_id="asset_id",
            table_name="table_name",
        )
        """
        _response = self._raw_client.get_table_schema(asset_id, table_name, request_options=request_options)
        return _response.data


class AsyncDatabasesClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._raw_client = AsyncRawDatabasesClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> AsyncRawDatabasesClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        AsyncRawDatabasesClient
        """
        return self._raw_client

    async def list_tables(
        self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> DatabaseTablesResponse:
        """
        Get a list of all tables in the database with optional row counts.

        Parameters
        ----------
        asset_id : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DatabaseTablesResponse
            Successful Response

        Examples
        --------
        import asyncio

        from athena import AsyncAthena

        client = AsyncAthena(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.databases.list_tables(
                asset_id="asset_id",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.list_tables(asset_id, request_options=request_options)
        return _response.data

    async def select(
        self,
        asset_id: str,
        table_name: str,
        *,
        select: typing.Optional[str] = None,
        order: typing.Optional[str] = None,
        limit: typing.Optional[int] = None,
        offset: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> DatabaseDataResponse:
        """
        Query rows from a table in the database. Supports filtering, ordering, and pagination using PostgREST-style query parameters.

        **Filter Syntax:**
        - `?column=eq.value` - Equal
        - `?column=neq.value` - Not equal
        - `?column=gt.value` - Greater than
        - `?column=gte.value` - Greater than or equal
        - `?column=lt.value` - Less than
        - `?column=lte.value` - Less than or equal
        - `?column=like.*pattern*` - LIKE (case-sensitive)
        - `?column=ilike.*pattern*` - ILIKE (case-insensitive)
        - `?column=in.(a,b,c)` - IN list
        - `?column=is.null` - IS NULL

        Parameters
        ----------
        asset_id : str

        table_name : str

        select : typing.Optional[str]
            Columns to return (comma-separated, e.g., 'id,name,email')

        order : typing.Optional[str]
            Order by clause (e.g., 'created_at.desc', 'name.asc')

        limit : typing.Optional[int]
            Maximum number of rows to return

        offset : typing.Optional[int]
            Number of rows to skip

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DatabaseDataResponse
            Successful Response

        Examples
        --------
        import asyncio

        from athena import AsyncAthena

        client = AsyncAthena(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.databases.select(
                asset_id="asset_id",
                table_name="table_name",
                select="select",
                order="order",
                limit=1,
                offset=1,
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.select(
            asset_id,
            table_name,
            select=select,
            order=order,
            limit=limit,
            offset=offset,
            request_options=request_options,
        )
        return _response.data

    async def insert(
        self,
        asset_id: str,
        table_name: str,
        *,
        data: Data,
        return_representation: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> DatabaseMutationResponse:
        """
        Insert one or more rows into a table.

        Parameters
        ----------
        asset_id : str

        table_name : str

        data : Data
            Single row object or array of row objects to insert

        return_representation : typing.Optional[bool]
            If true, return the inserted rows in the response

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DatabaseMutationResponse
            Successful Response

        Examples
        --------
        import asyncio

        from athena import AsyncAthena

        client = AsyncAthena(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.databases.insert(
                asset_id="asset_id",
                table_name="table_name",
                data={"email": "alice@example.com", "name": "Alice"},
                return_representation=True,
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.insert(
            asset_id,
            table_name,
            data=data,
            return_representation=return_representation,
            request_options=request_options,
        )
        return _response.data

    async def delete(
        self,
        asset_id: str,
        table_name: str,
        *,
        request: typing.Optional[DeleteDataRequest] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> DatabaseMutationResponse:
        """
        Delete rows matching the filter conditions. Filter conditions are passed as query parameters using PostgREST syntax (e.g., `?id=eq.5`).

        **Warning:** Without filters, this will delete ALL rows in the table.

        Parameters
        ----------
        asset_id : str

        table_name : str

        request : typing.Optional[DeleteDataRequest]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DatabaseMutationResponse
            Successful Response

        Examples
        --------
        import asyncio

        from athena import AsyncAthena, DeleteDataRequest

        client = AsyncAthena(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.databases.delete(
                asset_id="asset_id",
                table_name="table_name",
                request=DeleteDataRequest(
                    return_representation=False,
                ),
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.delete(
            asset_id, table_name, request=request, request_options=request_options
        )
        return _response.data

    async def update(
        self,
        asset_id: str,
        table_name: str,
        *,
        data: typing.Dict[str, typing.Optional[typing.Any]],
        return_representation: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> DatabaseMutationResponse:
        """
        Update rows matching the filter conditions. Filter conditions are passed as query parameters using PostgREST syntax (e.g., `?id=eq.5`).

        **Warning:** Without filters, this will update ALL rows in the table.

        Parameters
        ----------
        asset_id : str

        table_name : str

        data : typing.Dict[str, typing.Optional[typing.Any]]
            Column values to update

        return_representation : typing.Optional[bool]
            If true, return the updated rows in the response

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DatabaseMutationResponse
            Successful Response

        Examples
        --------
        import asyncio

        from athena import AsyncAthena

        client = AsyncAthena(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.databases.update(
                asset_id="asset_id",
                table_name="table_name",
                data={"email": "alice.smith@example.com", "name": "Alice Smith"},
                return_representation=True,
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.update(
            asset_id,
            table_name,
            data=data,
            return_representation=return_representation,
            request_options=request_options,
        )
        return _response.data

    async def get_table_schema(
        self, asset_id: str, table_name: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> DatabaseTableSchemaResponse:
        """
        Get the schema for a specific table, including column names, types, nullability, and default values. Useful for agent tooling and dynamic form generation.

        Parameters
        ----------
        asset_id : str

        table_name : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DatabaseTableSchemaResponse
            Successful Response

        Examples
        --------
        import asyncio

        from athena import AsyncAthena

        client = AsyncAthena(
            api_key="YOUR_API_KEY",
        )


        async def main() -> None:
            await client.databases.get_table_schema(
                asset_id="asset_id",
                table_name="table_name",
            )


        asyncio.run(main())
        """
        _response = await self._raw_client.get_table_schema(asset_id, table_name, request_options=request_options)
        return _response.data
